%% 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; }