%% options
copyright owner = Dirk Krause
copyright year = 2015-xxxx
license = bsd
%% header
/** @file
String output over dk4_stream_t API,
32 bit character strings.
CRT on Windows: Not used.
*/
#include "dk4strm.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Set output encoding for 32 bit character output.
@param strm Stream to modify.
@param oe New output encoding.
*/
void
dk4stream_set_output_encoding(dk4_stream_t *strm, int oe);
/** Write one 32 bit character to stream.
@param strm Stream to write to.
@param c32 Character to write.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if strm is null or not set up for writing,
- DK4_E_ENCODING_FAILED
if it is not possible to encode c32 to the output encoding for the
stream,
- DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed,
- DK4_E_FLUSH_FAILED
if flushing data downwards failed.
*/
int
dk4stream_c32_putc(dk4_stream_t *strm, dk4_c32_t c32, dk4_er_t *erp);
/** Write one 32 bit character string to stream.
@param strm Stream to write to.
@param txt Text string to write.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if strm is null or not set up for writing,
- DK4_E_ENCODING_FAILED
if it is not possible to encode c32 to the output encoding for the
stream,
- DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed,
- DK4_E_FLUSH_FAILED
if flushing data downwards failed.
*/
int
dk4stream_c32_puts(dk4_stream_t *strm, const dk4_c32_t *txt, dk4_er_t *erp);
/** Write byte order marker for those output encodings
supporting a BOM.
@param strm Stream to write the BOM to.
@param erp Error report, may be NULL.
@return 1 on success (BOM written or not required), 0 on error.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if strm is null or not set up for writing,
- DK4_E_ENCODING_FAILED
if it is not possible to encode c32 to the output encoding for the
stream,
- DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed,
- DK4_E_FLUSH_FAILED
if flushing data downwards failed.
*/
int
dk4stream_write_bom_if_necessary(dk4_stream_t *strm, dk4_er_t *erp);
#ifdef __cplusplus
}
#endif
%% module
#include "dk4strmo32.h"
#include "dk4mem.h"
#include "dk4ansi.h"
#include "dk4utf8.h"
#include "dk4utf16.h"
#include "dk4enc.h"
$!trace-include
void
dk4stream_set_output_encoding(dk4_stream_t *strm, int oe)
{
$? "+ dk4stream_set_output_encoding %d", oe
if (NULL != strm) {
switch (oe) {
case DK4_FILE_ENCODING_ASCII:
case DK4_FILE_ENCODING_ANSI:
case DK4_FILE_ENCODING_UTF8:
case DK4_FILE_ENCODING_UTF16_LE:
case DK4_FILE_ENCODING_UTF16_BE:
case DK4_FILE_ENCODING_32_LE:
case DK4_FILE_ENCODING_32_BE:
{
strm->oenc = oe;
} break;
}
} $? "- dk4stream_set_output_encoding"
}
int
dk4stream_c32_putc(dk4_stream_t *strm, dk4_c32_t c32, dk4_er_t *erp)
{
unsigned char buf[16];
dk4_c16_t b16[4];
size_t sz;
int back = 0;
$? "+ dk4stream_c32_putc %lx", (unsigned long)c32
if (NULL != strm) { $? ". stream ok"
if (0 != ((strm->fl) & DK4_STREAM_WRITE)) { $? ". wr flag ok"
switch (strm->oenc) {
case DK4_FILE_ENCODING_ASCII: { $? ". ASCII"
if (dkC32(0x00000100) > c32) {
back = dk4stream_write_byte(strm, (unsigned char)c32, erp);
} else {
dk4error_set_simple_error_code(erp, DK4_E_ENCODING_FAILED);
}
} break;
case DK4_FILE_ENCODING_ANSI: { $? ". ANSI"
if (0 != dk4ansi_encode(buf, c32)) {
back = dk4stream_write_byte(strm, buf[0], erp);
} else {
dk4error_set_simple_error_code(erp, DK4_E_ENCODING_FAILED);
}
} break;
case DK4_FILE_ENCODING_UTF8: { $? ". UTF-8"
sz = sizeof(buf);
if (0 != dk4utf8_encode(buf, &sz, c32, NULL)) {
back = dk4stream_write(strm, (void *)buf, sz, erp);
} else {
dk4error_set_simple_error_code(erp, DK4_E_ENCODING_FAILED);
}
} break;
case DK4_FILE_ENCODING_UTF16_LE: { $? ". UTF-16.LSB"
sz = DK4_SIZEOF(b16,dk4_c16_t);
if (0 != dk4utf16_encode(b16, &sz, c32, erp)) { $? ". enc"
if ((1 == sz) || (2 == sz)) {
buf[0] = (unsigned char)( b16[0] & 0x00FF);
buf[1] = (unsigned char)((b16[0] >> 8) & 0x00FF);
if (2 == sz) { $? ". 2 words"
buf[2] = (unsigned char)( b16[1] & 0x00FF);
buf[3] = (unsigned char)((b16[1] >> 8) & 0x00FF);
$? ". write 4 bytes to stream"
back = dk4stream_write(strm, (void *)buf, 4, erp);
} else { $? ". 1 word"
$? ". write 2 bytes to stream"
back = dk4stream_write(strm, (void *)buf, 2, erp);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_ENCODING_FAILED);
}
} else { $? "! enc"
dk4error_set_simple_error_code(erp, DK4_E_ENCODING_FAILED);
}
} break;
case DK4_FILE_ENCODING_UTF16_BE: { $? ". UTF-16.MSB"
sz = DK4_SIZEOF(b16,dk4_c16_t);
if (0 != dk4utf16_encode(b16, &sz, c32, erp)) { $? ". enc"
if ((1 == sz) || (2 == sz)) {
buf[1] = (unsigned char)( b16[0] & 0x00FF);
buf[0] = (unsigned char)((b16[0] >> 8) & 0x00FF);
if (2 == sz) { $? ". 2 bytes"
buf[3] = (unsigned char)( b16[1] & 0x00FF);
buf[2] = (unsigned char)((b16[1] >> 8) & 0x00FF);
back = dk4stream_write(strm, (void *)buf, 4, erp);
} else { $? ". 1 byte"
back = dk4stream_write(strm, (void *)buf, 2, erp);
}
} else { $? "! enc"
dk4error_set_simple_error_code(erp, DK4_E_ENCODING_FAILED);
}
} else { $? "! enc"
dk4error_set_simple_error_code(erp, DK4_E_ENCODING_FAILED);
}
} break;
case DK4_FILE_ENCODING_32_LE: { $? ". C32.LSB"
buf[0] = (unsigned char)( c32 & dkC32(0x000000FF));
buf[1] = (unsigned char)((c32 >> 8) & dkC32(0x000000FF));
buf[2] = (unsigned char)((c32 >> 16) & dkC32(0x000000FF));
buf[3] = (unsigned char)((c32 >> 24) & dkC32(0x000000FF));
back = dk4stream_write(strm, (void *)buf, 4, erp);
} break;
case DK4_FILE_ENCODING_32_BE: { $? ". C32.MSB"
buf[3] = (unsigned char)( c32 & dkC32(0x000000FF));
buf[2] = (unsigned char)((c32 >> 8) & dkC32(0x000000FF));
buf[1] = (unsigned char)((c32 >> 16) & dkC32(0x000000FF));
buf[0] = (unsigned char)((c32 >> 24) & dkC32(0x000000FF));
back = dk4stream_write(strm, (void *)buf, 4, erp);
} break;
default: {
dk4error_set_simple_error_code(erp, DK4_E_BUG);
} break;
}
} else{
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
} $? "- dk4stream_c32_putc %d", back
return back;
}
int
dk4stream_c32_puts(dk4_stream_t *strm, const dk4_c32_t *txt, dk4_er_t *erp)
{
int back = 0;
if ((NULL != strm) && (NULL != txt)) {
if (0 != ((strm->fl) & DK4_STREAM_WRITE)) {
back = 1;
while ((dkC32(0) != *txt) && (1 == back)) {
if (0 == dk4stream_c32_putc(strm, *(txt++), erp)) {
back = 0;
}
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}
int
dk4stream_write_bom_if_necessary(dk4_stream_t *strm, dk4_er_t *erp)
{
int back = 0;
$? "+ dk4stream_write_bom_if_necessary"
if (NULL != strm) {
if (0 != ((strm->fl) & DK4_STREAM_WRITE)) {
switch (strm->oenc) {
#if VERSION_BEFORE_20141218
/* For UTF-8 files most text editors do not handle
the BOM correctly, they show a glyph for unrepresentable
characters.
So I decided to write a BOM only for 16 bit and 32 bit
character output.
*/
case DK4_FILE_ENCODING_UTF8:
#endif
case DK4_FILE_ENCODING_UTF16_LE:
case DK4_FILE_ENCODING_UTF16_BE:
case DK4_FILE_ENCODING_32_LE:
case DK4_FILE_ENCODING_32_BE:
{ $? ". attempt to write bom"
back = dk4stream_c32_putc(strm, dkC32(0x0000FEFF), erp);
} break;
default: {
back = 1;
} break;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
} $? "- dk4stream_write_bom_if_necessary %d", back
return back;
}