%% options copyright owner = Dirk Krause copyright year = 2011-2014 license = bsd %% header #include "dk3conf.h" #include "dk3types.h" #ifdef __cplusplus extern "C" { #endif /** Open a stream, allocate memory. @param d Stream data object. @param f Stream low-level function. @param fl Flags to indicate read and/or write access. @param app Application structure, used for diagnostics. @return Pointer to new stream on success, NULL on error. */ dk3_stream_t * dk3stream_open_app(void *d, dk3_stream_api_fct_t *f, int fl, dk3_app_t *app); /** Close a stream, release memory. @param st Stream to close. @return 1 on success, 0 on error. */ int dk3stream_close(dk3_stream_t *st); /** Set up automatic flushing when writing newlines. @param st Stream to set up. @param fl Flag value (0=no flush, 1=flush buffer, 2=buffer and low-level object). @return 1 on success, 0 on error. */ int dk3stream_set_line_flush(dk3_stream_t *st, int fl); /** Write a buffer of bytes to stream. @param st Stream to write to. @param sb Source buffer. @param sz Size of \ sb (number of bytes). The size must not exceed 32767 as it is converted to int for some compression libraries. @return Number of bytes written. */ size_t dk3stream_write_bytes(dk3_stream_t *st, char const *sb, size_t sz); /** Read bytes into buffer. @param st Stream to read from. @param db Destination buffer address. @param sz Size of \a db in bytes. The size must not exceed 32767 as it is converted to int for some compression libraries. @return Number of bytes read (may be 0). */ size_t dk3stream_read_bytes(dk3_stream_t *st, char *db, size_t sz); /** Check whether end of input data was reached. @param st Stream to check. @return 1 for end of input reached, 0 otherwise. */ int dk3stream_feof(dk3_stream_t const *st); /** Get a text line (8-bit characters). @param st Stream to read from. @param db Destination buffer. @param sz Size of \a db in bytes. The size must not exceed 32767 as it is converted to int for some compression libraries. @return 1 on success (line found), 0 on error. */ int dk3stream_c8_fgets(dk3_stream_t *st, char *db, size_t sz); /** Write a text line (8-bit characters) without any re-encoding. @param st Stream to write to. @param str Text to write. @return 1 on success, 0 on error. */ int dk3stream_c8_fputs(dk3_stream_t *st, char const *str); /** Set output encoding. @param st Stream to set up. @param oe New output encoding. */ void dk3stream_set_output_encoding(dk3_stream_t *st, int oe); /** Write byte order marker 0xFEFF converted to the streams output encoding. @param st Stream to write to. @return 1 on success, 0 on error. */ int dk3stream_write_byte_order_marker(dk3_stream_t *st); /** Write byte order marker if necessary on the system. @param st Stream to write to. @param se System encoding. @return 1 on success, 0 on error. */ int dk3stream_write_byte_order_marker_if_necessary(dk3_stream_t *st, int se); /** Write 8-bit character text, convert to the streams output encoding. @param st Stream to write to. @param s String to write. @return 1 on success, 0 on error. */ int dk3stream_fputs_c8_plain(dk3_stream_t *st, char const *s); /** Write UTF-8 encoded text, convert to the streams output encoding. @param st Stream to write to. @param s String to write. @return 1 on success, 0 on error. */ int dk3stream_fputs_c8_utf8(dk3_stream_t *st, char const *s); /** Write UTF-16 encoded text, convert to the streams output encoding. @param st Stream to write to. @param s String to write. @return 1 on success, 0 on error. */ int dk3stream_fputs_c16(dk3_stream_t *st, dk3_c16_t const *s); /** Write UNICODE text, convert to the streams output encoding. @param st Stream to write to. @param s String to write. @return 1 on success, 0 on error. */ int dk3stream_fputs_c32(dk3_stream_t *st, dk3_c32_t const *s); /** Write generic dkChar text, convert to the streams output encoding. @param st Stream to write to. @param s String to write. @param ie Input encoding (used for 8-bit characters only). @return 1 on success, 0 on error. */ int dk3stream_strputs(dk3_stream_t *st, dkChar const *s, int ie); /** Write newline to stream. @param st Stream to write to. @return 1 on success, 0 on error. */ int dk3stream_strnl(dk3_stream_t *st); /** Get number of bytes written. @param st Stream to check. @return Number of bytes written to the stream. */ dk3_um_t dk3stream_bytes_written(dk3_stream_t const *st); /** Open stream for a file. The file is not closed when the stream is closed. @param fi File. @param fl Read/write flags. @param app Application structure, used for diagnostics. @return Stream pointer on success, NULL on error. */ dk3_stream_t * dk3stream_open_file_app(FILE *fi, int fl, dk3_app_t *app); /** Get 16-bit text line. @param st Stream. @param db Destination buffer. @param sz Size of \a db (number of 16-bit characters). The size must not exceed 16383 as buffer sizes arre converted to int for some compression libraries. @param msbfirst Flag: MSB first. @return 1 on success, 0 on error. */ int dk3stream_c16_fgets(dk3_stream_t *st, dk3_c16_t *db, size_t sz, int msbfirst); /** Get 32-bit text line. @param st Stream. @param db Destination buffer. @param sz Size of \a db (number of 32-bit characters). The size must not exceed 8191 as buffer sizes are converted to int for some compression libraries and 4*8192 exceeds the int range on 16-bit systems. @param msbfirst Flag: MSB first. @return 1 on success, 0 on error. */ int dk3stream_c32_fgets(dk3_stream_t *st, dk3_c32_t *db, size_t sz, int msbfirst); #if DK3_HAVE_ZLIB_H /** Open stream for a gzFile. The gzFile is not closed when the stream is closed. @param g gzFile. @param fl Read/write flags. @param app Application structure, used for diagnostics. @return Stream pointer on success, NULL on error. */ dk3_stream_t * dk3stream_open_gz_app(gzFile g, int fl, dk3_app_t *app); #endif #if DK3_HAVE_BZLIB_H /** Open stream for a BZFILE. The BZFILE is not closed when the stream is closed. @param b BZFILE. @param fl Read/write flags. @param app Application structure, used for diagnostics. @return Stream pointer on success, NULL on error. */ dk3_stream_t * dk3stream_open_bz2_app(BZFILE *b, int fl, dk3_app_t *app); #endif /** Process an input stream character by character. @param st Stream containing the input data to process. @param obj Object to modify with input stream. @param hf Character handler function. @param ie Input encoding. @return 1 on success, 0 on error. */ int dk3stream_process_chars( dk3_stream_t *st, void *obj, dk3_char_handler_t *hf, int ie ); /** Process all characters in a file. NOTE: If you have the file name, you should use dk3stream_process_filename_chars_app() instead. The dk3stream_process_filename_chars_app() checks for a BOM at the beginning of the file and corrects the input encoding if necessary. @param obj Object to modify while processing the input file. @param hf Handler function. @param fipo Input file. @param fn File name. @param ie Input file encoding. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3stream_process_file_chars_app( void *obj, dk3_char_handler_t *hf, FILE *fipo, dkChar const *fn, int ie, dk3_app_t *app ); /** Process all characters in a file. @param obj Object to modify while processing the input file. @param hf Handler function. @param fn File name. @param de Default file encoding. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3stream_process_filename_chars_app( void *obj, dk3_char_handler_t *hf, dkChar const *fn, int de, dk3_app_t *app ); /** Put 32-bit character to stream, convert if necessary. @param st Output stream. @param c32 Character to write. @param err_enc_rep Pointer to flag: Encoding error reported. @return 1 on success, 0 on error. */ int dk3stream_fputc_c32(dk3_stream_t *st, dk3_c32_t c32, int *err_enc_rep); /** Process stream contents line by line. @param st Input stream. @param obj Object to modify while processing input. @param hf Handler function. @param buf Buffer for input lines. @param szbuf Size of \a buf (number of characters). The size must not exceed 8191 as buffer sizes are converted to int for some compression libraries and 4*8192 exceeds the int range on 16-bit systems. @param se System character encoding (DK3_ENCODING_xxx). @param ie Input encoding (DK3_FILE_ENCODING_xxx). @return 1 on success, 0 on error, -1 on error with abort. */ int dk3stream_process_lines( dk3_stream_t *st, void *obj, dk3_line_handler_t *hf, dkChar *buf, size_t szbuf, int se, int ie ); /** Process input file contents line by line. NOTE: If you have a file name available, you should use dk3stream_process_filename_lines_app() instead, as the dk3stream_process_filename_lines_app() function checks for a BOM at the start of the file and corrects the input encoding if necessary. @param obj Object to modify while processing input. @param hf Handler function. @param fipo Input file. @param fn File name. @param buf Input line buffer. @param szbuf Size of \a buf (number of characters). The size must not exceed 8191 as buffer sizes are converted to int for some compression libraries. @param se System character encoding (DK3_ENCODING_xxx). @param ie Input encoding (DK3_FILE_ENCODING_xxx). @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error, -1 on error with abort. */ int dk3stream_process_file_lines_app( void *obj, dk3_line_handler_t *hf, FILE *fipo, dkChar const *fn, dkChar *buf, size_t szbuf, int se, int ie, dk3_app_t *app ); /** Process input file line by line. @param obj Object to modify while processing input. @param hf Handler function. @param fn File name. @param buf Input line buffer. @param szbuf Size of \a buf (number of characters). The size must not exceed 8191 as buffer sizes are converted to int for some compression libraries. @param se System character encoding (DK3_ENCODING_xxx). @param de Default file encoding (DK3_FILE_ENCODING_xxx). @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error, -1 on error with abort. */ int dk3stream_process_filename_lines_app( void *obj, dk3_line_handler_t *hf, dkChar const *fn, dkChar *buf, size_t szbuf, int se, int de, dk3_app_t *app ); /** Write double value to stream as text, avoid exponential notation. @param os Stream to write to. @param x Value to write. @return 1 on success, 0 on error. */ int dk3strm_double_c8_no_sci(dk3_stream_t *os, double x); /** Write double value from string buffer to stream, avoid exponential notation. @param os Stream to write to. @param buffer Buffer containing double converted to text. @return 1 on success, 0 on error. */ int dk3strm_double_c8_str_no_sci(dk3_stream_t *os, char *buffer); #ifdef __cplusplus } #endif %% module #include "dk3all.h" $(trace-include) #if 0 /** Low-level stream function to deal with bzip2 compression. Closing the stream also closes the bzip2-file. @param api API structure. */ static void dk3stream_bz_fct(dk3_stream_api_t *api) { #if DK3_HAVE_BZLIB_H BZFILE *b = NULL; /* Low level I/O object. */ int res = 0; /* Operation result. */ #endif api->suc = 0; (api->res).sz = 0; (api->res).ec = DK3_ERROR_NOT_SUPPORTED; #if DK3_HAVE_BZLIB_H b = (BZFILE *)((api->arg).d); (api->res).ec = 0; switch(api->cmd) { case DK3_STREAM_API_READ: { if(((api->arg).b) && ((api->arg).sz) && ((api->arg).d)) { res = BZ2_bzread(b, (api->arg).b, (api->arg).sz); if(res > 0) { api->suc = 1; (api->res).ec = 0; (api->res).sz = (size_t)res; } } } break; case DK3_STREAM_API_WRITE: { if(((api->arg).b) && ((api->arg).sz) && ((api->arg).d)) { res = BZ2_bzwrite(b, (api->arg).b, (api->arg).sz); if(res > 0) { (api->res).sz = (size_t)res; if((size_t)res == (api->arg).sz) { api->suc = 1; (api->res).ec = 0; } } } } break; case DK3_STREAM_API_FLUSH: { if((api->arg).d) { BZ2_bzflush(b); api->suc = 1; (api->res).ec = 0; /* As the library manual explains BZ2_bzflush() does nothing. So we always return success. */ } } break; case DK3_STREAM_API_AT_END: { } break; case DK3_STREAM_API_CLOSE: { if((api->arg).d) { BZ2_bzclose(b); api->suc = 1; (api->res).ec = 0; } } break; case DK3_STREAM_API_ZERO_IS_END: { api->suc = 1; (api->res).ec = 0; /* Correct if necessary */ } break; case DK3_STREAM_API_ERROR: { } break; } #endif } /** Low-level stream function to deal with bzip2 compression. Closing the stream does not close the bzip2 file. @param api API structure. */ static void dk3stream_bz_fct_no_close(dk3_stream_api_t *api) { if(api->cmd != DK3_STREAM_API_CLOSE) { dk3stream_bz_fct(api); } else { api->suc = 1; (api->res).ec = 0; } } #endif #if 0 /** Low-level stream function to deal with gzip compression. Closing the stream also closes the gzip-file. @param api API structure. */ static void dk3stream_gz_fct(dk3_stream_api_t *api) { #if DK3_HAVE_ZLIB_H int res = 0; /* Operation result. */ gzFile g = NULL; /* Low-level I/O object. */ #endif api->suc = 0; (api->res).sz = 0; (api->res).ec = DK3_ERROR_NOT_SUPPORTED; #if DK3_HAVE_ZLIB_H (api->res).ec = 0; g = (gzFile)((api->arg).d); switch(api->cmd) { case DK3_STREAM_API_READ: { if(((api->arg).b) && ((api->arg).sz) && ((api->arg).d)) { res = gzread(g, (api->arg).b, (api->arg).sz); if(res > 0) { api->suc = 1; (api->res).ec = 0; (api->res).sz = (size_t)res; } } } break; case DK3_STREAM_API_WRITE: { if(((api->arg).b) && ((api->arg).sz) && ((api->arg).d)) { res = gzwrite(g, (api->arg).b, (api->arg).sz); (api->res).sz = (size_t)res; if((size_t)res == (api->arg).sz) { api->suc = 1; (api->res).ec = 0; } } } break; case DK3_STREAM_API_FLUSH: { if((api->arg).d) { if(gzflush(g, Z_FULL_FLUSH) == Z_OK) { api->suc = 1; (api->res).ec = 0; } } } break; case DK3_STREAM_API_AT_END: { if((api->arg).d) { if(gzeof(g) == 1) { api->suc = 1; } } } break; case DK3_STREAM_API_CLOSE: { if((api->arg).d) { if(gzclose(g) == Z_OK) { api->suc = 1; } } } break; case DK3_STREAM_API_ZERO_IS_END: { api->suc = 0; } break; case DK3_STREAM_API_ERROR: { api->suc = 0; } break; } #endif } /** Low-level stream function to deal with gzip compression. Closing the stream does not close the gzip-file. @param api API structure. */ static void dk3stream_gz_fct_no_close(dk3_stream_api_t *api) { if(api->cmd != DK3_STREAM_API_CLOSE) { dk3stream_gz_fct(api); } else { api->suc = 1; (api->res).ec = 0; } } #endif /** Low-level stream function to deal with plain files. Closing the stream also closes the file. @param api API structure. */ static void dk3stream_file_fct(dk3_stream_api_t *api) { FILE *fipo = NULL; /* Low-level I/O object. */ size_t res = 0; /* Operation result. */ $? "+ dk3stream_file_fct" api->suc = 0; (api->res).sz = 0; (api->res).ec = 0; switch(api->cmd) { case DK3_STREAM_API_READ: { $? ". read" if(((api->arg).b) && ((api->arg).sz) && ((api->arg).d)) { fipo = (FILE *)((api->arg).d); #if DK3_ON_WINDOWS res = fread((api->arg).b, 1, (api->arg).sz, fipo); if(res) { api->suc = 1; (api->res).ec = 0; (api->res).sz = res; } else { if(!ferror(fipo)) { api->suc = 1; (api->res).ec = 0; } } #else #if DK3_HAVE_FREAD res = fread((api->arg).b, 1, (api->arg).sz, fipo); if(res) { api->suc = 1; (api->res).ec = 0; (api->res).sz = res; } else { if(!ferror(fipo)) { api->suc = 1; (api->res).ec = 0; } } #else #if DK3_HAVE__FREAD res = _fread((api->arg).b, 1, (api->arg).sz, fipo); if(res) { api->suc = 1; (api->res).ec = 0; (api->res).sz = res; } else { if(!ferror(fipo)) { api->suc = 1; (api->res).ec = 0; } } #else #error "No fread() function!" #endif #endif #endif } } break; case DK3_STREAM_API_WRITE: { $? ". write" if(((api->arg).b) && ((api->arg).sz) && ((api->arg).d)) { fipo = (FILE *)((api->arg).d); #if DK3_ON_WINDOWS res = fwrite((api->arg).b, 1, (api->arg).sz, fipo); (api->res).sz = res; if(res == (api->arg).sz) { api->suc = 1; (api->res).ec = 0; } #else #if DK3_HAVE_FWRITE res = fwrite((api->arg).b, 1, (api->arg).sz, fipo); (api->res).sz = res; if(res == (api->arg).sz) { api->suc = 1; (api->res).ec = 0; } #else #if DK3_HAVE__FWRITE res = _fwrite((api->arg).b, 1, (api->arg).sz, fipo); if(res == (api->arg).sz) { api->suc = 1; (api->res).ec = 0; (api->res).sz = res; } #else #error "No fwrite() function!" #endif #endif #endif } } break; case DK3_STREAM_API_FLUSH: { $? ". flush" if((api->arg).d) { fipo = (FILE *)((api->arg).d); if(fflush(fipo) == 0) { api->suc = 1; (api->res).ec = 0; } } } break; case DK3_STREAM_API_AT_END: { $? ". at-end" if((api->arg).d) { fipo = (FILE *)((api->arg).d); if(feof(fipo)) { api->suc = 1; (api->res).ec = 0; } } } break; case DK3_STREAM_API_CLOSE: { $? ". close" if((api->arg).d) { fipo = (FILE *)((api->arg).d); if(fclose(fipo) == 0) { api->suc = 1; (api->res).ec = 0; } } } break; case DK3_STREAM_API_ZERO_IS_END: { $? ". zero-is-end" if((api->arg).d) { api->suc = 1; (api->res).ec = 0; } } break; case DK3_STREAM_API_ERROR: { $? ". error" if((api->arg).d) { fipo = (FILE *)((api->arg).d); if(ferror(fipo)) { api->suc = 1; (api->res).ec = 0; } } } break; } $? "- dk3stream_file_fct %d", api->suc } /** Low-level stream function to deal with plain files. Closing the stream does not close the file. @param api API structure. */ static void dk3stream_file_fct_no_close(dk3_stream_api_t *api) { $? "+ dk3stream_file_fct_no_close" if(api->cmd != DK3_STREAM_API_CLOSE) { dk3stream_file_fct(api); } else { api->suc = 1; (api->res).ec = 0; } $? "- dk3stream_file_fct_no_close" } /** Initialize stream API structure. @param api Structure to initialize. */ static void dk3stream_api_init(dk3_stream_api_t *api) { $? "+ dk3stream_api_init" if(api) { api->cmd = 0; api->suc = 0; (api->arg).b = NULL; (api->arg).sz = 0; (api->arg).d = NULL; (api->res).sz = 0; (api->res).ec = 0; } $? "- dk3stream_api_init" } /** Delete stream, release memory. @param st Stream to delete. */ static void dk3stream_delete_stream(dk3_stream_t *st) { $? "+ dk3stream_delete_stream" if(st) { dk3_release(st->ib); dk3_release(st->ob); dk3_delete(st); } $? "- dk3stream_delete_stream" } /** Flush stream. @param st Stream to flush. @param fd Flag: Flush downstream object. @return 1 on success, 0 on error. */ static int dk3stream_do_flush(dk3_stream_t *st, int fd) { int back = 0; dk3_stream_api_t api; $? "+ dk3stream_do_flush" if(st) { back = 1; st->ec = 0; if((st->fl) & DK3_STREAM_FLAG_WRITE) { if(st->us_ob) { dk3stream_api_init(&api); api.cmd = DK3_STREAM_API_WRITE; api.arg.b = st->ob; api.arg.sz = st->us_ob; api.arg.d = st->d; (*(st->f))(&api); if(!(api.suc)) { st->ec = api.res.ec; back = 0; if(st->app) { /* ERROR: Failed to write data! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 120); } } } st->us_ob = 0; if(fd) { dk3stream_api_init(&api); api.cmd = DK3_STREAM_API_FLUSH; api.arg.d = st->d; (*(st->f))(&api); if(!(api.suc)) { if(back) { if(st->app) { /* ERROR: Flush failed! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 121); } st->ec = api.res.ec; } back = 0; } } } } $? "- dk3stream_do_flush %d", back return back; } /** Open new stream, allocate memory. @param app Application structure, used for diagnostics. @return Pointer to new stream on success, NULL on error. */ static dk3_stream_t * dk3stream_new_stream(dk3_app_t *app) { dk3_stream_t *back = NULL; $? "+ dk3stream_new_stream" back = dk3_new_app(dk3_stream_t,1,app); if(back) { back->app = NULL; back->d = NULL; back->f = NULL; back->ib = NULL; back->ob = NULL; back->wr = DK3_UM_0; back->sz_ib = 0; back->av_ib = 0; back->us_ib = 0; back->sz_ob = 0; back->us_ob = 0; back->fl = 0; back->lf = 0; back->fe = 0; back->ec = 0; back->oe = 0; back->ze = 0; back->er = 0; back->ib = dk3_new_app(char,4096,app); back->ob = dk3_new_app(char,4096,app); if((back->ib) && (back->ob)) { back->sz_ib = 4096; back->sz_ob = 4096; } else { dk3stream_delete_stream(back); back = NULL; } } $? "- dk3stream_new_stream %s", TR_PTR(back) return back; } int dk3stream_close(dk3_stream_t *st) { int back = 0; dk3_stream_api_t api; $? "+ dk3stream_close" if(st) { back = dk3stream_do_flush(st, 1); dk3stream_api_init(&api); api.cmd = DK3_STREAM_API_CLOSE; api.arg.d = st->d; (*(st->f))(&api); if(!(api.suc)) { back = 0; if(st->app) { /* ERROR: Failed to close stream data object! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 122); } } st->d = NULL; st->f = NULL; st->app = NULL; dk3stream_delete_stream(st); } $? "- dk3stream_close %d", back return back; } dk3_stream_t * dk3stream_open_app(void *d, dk3_stream_api_fct_t *f, int fl, dk3_app_t *app) { dk3_stream_t *back = NULL; dk3_stream_api_t api; $? "+ dk3stream_open_app" if((d) && (f)) { back = dk3stream_new_stream(app); if(back) { back->app = app; back->d = d; back->f = f; back->fl = fl; dk3stream_api_init(&api); api.cmd = DK3_STREAM_API_ZERO_IS_END; api.arg.d = d; (*f)(&api); if(api.suc) { back->ze = 1; } } } $? "- dk3stream_open_app %s", TR_PTR(back) return back; } /** Write one byte. @param st Stream to write to. @param ch Byte to write. @return 1 on success, 0 on error. */ static int dk3stream_my_write_byte(dk3_stream_t *st, char ch) { int back = 1; int fld = 0; /* Flag: Flush downwards. */ $? "+ dk3stream_my_write_byte" (st->ob)[st->us_ob] = ch; st->us_ob += 1; st->wr += DK3_UM_1; if((st->us_ob == st->sz_ob) || ((ch == '\n') && (st->lf))) { if(ch == '\n') { if(st->lf == 2) { fld = 1; } } back = dk3stream_do_flush(st, fld); } $? "- dk3stream_my_write_byte %d", back return back; } size_t dk3stream_write_bytes(dk3_stream_t *st, char const *sb, size_t sz) { size_t back = 0; char const *sp = NULL; /* Source pointer. */ size_t l = 0; /* Bytes remaining. */ $? "+ dk3stream_write_bytes" if((st) && (sb) && (sz)) { if((st->fl) & DK3_STREAM_FLAG_WRITE) { sp = sb; l = sz; while(l--) { if(dk3stream_my_write_byte(st, *sp)) { back++; } sp++; } } else { if(st->app) { /* ERROR: Stream not opened for write operations! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 123); } } } $? "- dk3stream_write_bytes %lu", (unsigned long)back return back; } /** Read one byte from buffer, reload buffer if necessary. @param st Stream to read from. @param cp One-byte buffer for destination. @return 1 on success, 0 on error. */ static int dk3stream_my_read_byte(dk3_stream_t *st, char *cp) { int back = 0; dk3_stream_api_t api; $? "+ dk3stream_my_read_byte" if(st->us_ib >= st->av_ib) { $? ". must read from downstream" st->us_ib = 0; st->av_ib = 0; dk3stream_api_init(&api); api.cmd = DK3_STREAM_API_READ; api.arg.b = st->ib; api.arg.sz = st->sz_ib; api.arg.d = st->d; (*(st->f))(&api); if(api.suc) { $? ". read operation succeeded" st->av_ib = api.res.sz; if(st->av_ib) { $? ". bytes found" if(st->av_ib < st->sz_ib) { $? ". less bytes than expected" dk3stream_api_init(&api); api.cmd = DK3_STREAM_API_AT_END; api.arg.d = st->d; (*(st->f))(&api); if(api.suc) { $? ". end of input" st->fe = 1; } } } else { $? "! 0 bytes were read" if(st->ze) { st->fe = 1; /* End of input reached. */ } else { dk3stream_api_init(&api); api.cmd = DK3_STREAM_API_ERROR; api.arg.d = st->d; (*(st->f))(&api); if(api.suc) { st->er = 1; st->fe = 1; } } } } else { $? "! read operation failed" st->ec = api.res.ec; st->fe = 1; /* Error found, end of input data. */ dk3stream_api_init(&api); api.cmd = DK3_STREAM_API_AT_END; api.arg.d = st->d; (*(st->f))(&api); if(api.suc) { st->ec = 0; } else { if(st->app) { /* ERROR: Read operation failed! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 124); } st->er = 1; } } } if(st->us_ib < st->av_ib) { $? ". data available" *cp = (st->ib)[st->us_ib]; st->us_ib += 1; back = 1; } $? "- dk3stream_my_read_byte %d", back return back; } size_t dk3stream_read_bytes(dk3_stream_t *st, char *db, size_t sz) { size_t back = 0; char c = 0x00; /* Current byte read. */ char *dp = NULL; /* Destination pointer. */ int cc = 0; /* Flag: Can continue. */ $? "+ dk3stream_read_bytes" if((st) && (db) && (sz)) { dp = db; cc = 1; while((back < sz) && (cc)) { if(dk3stream_my_read_byte(st, &c)) { *(dp++) = c; back++; } else { cc = 0; } } } $? "- dk3stream_read_bytes %lu", (unsigned long)back return back; } int dk3stream_feof(dk3_stream_t const *st) { int back = 0; if(st) { if(st->fe) { if(st->us_ib >= st->av_ib) { back = 1; } } } return back; } int dk3stream_c8_fgets(dk3_stream_t *st, char *db, size_t sz) { int back = 0; char *dp = NULL; /* Destination pointer. */ size_t l = 0; /* Number of bytes already found. */ int cc = 0; /* Flag: Can continue. */ char c = 0x00; /* Current character. */ $? "+ dk3stream_c8_fgets" if((st) && (db) && (sz)) { *db = '\0'; dp = db; l = 0; cc = 1; while((l < (sz - 1)) && (cc)) { if(dk3stream_my_read_byte(st, &c)) { *(dp++) = c; l++; if(c == '\n') { cc = 0; } } else { cc = 0; } } if(l < sz) { *dp = '\0'; } else { db[sz - 1] = '\0'; } if(l) { back = 1; } } $? "- dk3stream_c8_fgets %d", back return back; } int dk3stream_c8_fputs(dk3_stream_t *st, char const *str) { int back = 0; char const *sp = NULL; /* Source pointer. */ if((st) && (str)) { back = 1; sp = str; while(*sp) { if(!dk3stream_my_write_byte(st, *(sp++))) { back = 0; } } } return back; } int dk3stream_c16_fgets(dk3_stream_t *st, dk3_c16_t *db, size_t sz, int msbfirst) { int back = 0; int cc = 1; /* Flag: Can continue. */ int eo = 0; /* Flag: 0=first byte, 1=second byte */ int res = 0; /* Result from my_read_byte. */ int msbf = 0; /* Flag: MSB first. */ char c1 = 0x00; /* First byte. */ char c2 = 0x00; /* Second byte. */ dk3_c16_t *ptr = NULL; /* Pointer into destination buffer. */ size_t bt = 0; /* Number of characters read. */ unsigned char uc1; /* First byte as unsigned char. */ unsigned char uc2; /* Second byte as unsigned char. */ unsigned u1; /* First byte as unsigned. */ unsigned u2; /* Second byte as unsigned. */ if((st) && (db) && (sz)) { back = 1; ptr = db; bt = 0; msbf = msbfirst; cc = 1; eo = 0; while(cc) { res = 0; if(eo) { res = dk3stream_my_read_byte(st, &c2); } else { res = dk3stream_my_read_byte(st, &c1); } if(res) { if(eo) { eo = 0; uc1 = (unsigned char)c1; uc2 = (unsigned char)c2; u1 = (unsigned)uc1; u2 = (unsigned)uc2; u1 &= 0x00FFU; u2 &= 0x00FFU; if(msbf) { u1 = ((u1 << 8) & 0xFF00U) | u2; } else { u1 = ((u2 << 8) & 0xFF00U) | u1; } if(u1 != 0xFEFFU) { if(u1 == 0xFFFEU) { msbf = (msbf ? 0 : 1); } else { *(ptr++) = (dk3_c16_t)u1; bt++; if(u1 == (dk3_c16_t)'\n') { cc = 0; } } } } else { eo = 1; } } else { cc = 0; if(eo) { back = 0; } } if(bt >= (sz - 1)) { cc = 0; } } if(bt < sz) { *ptr = 0U; } db[sz - 1] = 0U; } if(bt == 0) { back = 0; } return back; } int dk3stream_c32_fgets(dk3_stream_t *st, dk3_c32_t *db, size_t sz, int msbfirst) { int back = 0; int cc = 1; /* Flag: Can continue. */ int eo = 0; /* Flag: 0=first byte, 1=second byte */ int res = 0; /* Result from my_read_byte. */ int msbf = 0; /* Flag: MSB first. */ char c1 = 0x00; /* First byte. */ char c2 = 0x00; /* Second byte. */ char c3 = 0x00; /* Third byte. */ char c4 = 0x00; /* Fourth byte. */ dk3_c32_t *ptr = NULL; /* Pointer into destination buffer. */ size_t bt = 0; /* Number of characters read. */ unsigned char uc1; /* First byte as unsigned char. */ unsigned char uc2; /* Second byte as unsigned char. */ unsigned char uc3; /* Third byte as unsigned char. */ unsigned char uc4; /* Fourth byte as unsigned char. */ unsigned long u1; /* First byte as unsigned. */ unsigned long u2; /* Second byte as unsigned. */ unsigned long u3; /* Third byte as unsigned. */ unsigned long u4; /* Fourth byte as unsigned. */ if((st) && (db) && (sz)) { back = 1; ptr = db; bt = 0; msbf = msbfirst; cc = 1; eo = 0; while(cc) { res = 0; switch(eo) { case 0: { res = dk3stream_my_read_byte(st, &c1); } break; case 1: { res = dk3stream_my_read_byte(st, &c2); } break; case 2: { res = dk3stream_my_read_byte(st, &c3); } break; case 3: { res = dk3stream_my_read_byte(st, &c4); } break; } if(res) { eo++; if(eo >= 4) { eo = 0; uc1 = (unsigned char)c1; uc2 = (unsigned char)c2; uc3 = (unsigned char)c3; uc4 = (unsigned char)c4; u1 = (unsigned long)uc1; u2 = (unsigned long)uc2; u3 = (unsigned long)uc3; u4 = (unsigned long)uc4; if(msbf) { u1 = (u1 << 24) & 0xFF000000UL; u2 = (u2 << 16) & 0x00FF0000UL; u3 = (u2 << 8) & 0x0000FF00UL; u4 = u4 & 0x000000FFUL; } else { u1 = u1 & 0x000000FFUL; u2 = (u2 << 8) & 0x0000FF00UL; u3 = (u3 << 16) & 0x00FF0000UL; u4 = (u4 << 24) & 0xFF000000UL; } u1 = (u1 | u2 | u3 | u4); if(u1 != 0x0000FEFFUL) { if(u1 == 0x0000FFFEUL) { msbf = (msbf ? 0 : 1); } else { *(ptr++) = u1; bt++; if(u1 == 0x0000000AUL) { cc = 0; } } } } } else { cc = 0; if(eo) { back = 0; } } if(bt >= (sz - 1)) { cc = 0; } } if(bt < sz) { *ptr = 0UL; } db[sz - 1] = 0UL; } if(bt == 0) { back = 0; } return back; } void dk3stream_set_output_encoding(dk3_stream_t *st, int oe) { if(st) { switch(oe) { case DK3_FILE_ENCODING_ASCII: case DK3_FILE_ENCODING_UTF8: case DK3_FILE_ENCODING_UTF16_MSB_FIRST: case DK3_FILE_ENCODING_UTF16_LSB_FIRST: case DK3_FILE_ENCODING_UNICODE_MSB_FIRST: case DK3_FILE_ENCODING_UNICODE_LSB_FIRST: { st->oe = oe; } break; default: { if(st->app) { /* ERROR: Illegal output encoding! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 114); } } break; } } } /** Write one 16-bit character to stream. @param st Output stream. @param c16 Character to write. @return 1 on success, 0 on error. */ static int dk3stream_my_write_16(dk3_stream_t *st, dk3_c16_t c16) { int back = 0; switch(st->oe) { case DK3_FILE_ENCODING_UTF16_MSB_FIRST: { if(dk3stream_my_write_byte(st, (char)((c16 >> 8) & 0x00FFU))) { if(dk3stream_my_write_byte(st, (char)(c16 & 0x00FFU))) { back = 1; } } } break; case DK3_FILE_ENCODING_UTF16_LSB_FIRST: { if(dk3stream_my_write_byte(st, (char)(c16 & 0x00FFU))) { if(dk3stream_my_write_byte(st, (char)((c16 >> 8) & 0x00FFU))) { back = 1; } } } break; } return back; } /** Write one 32-bit character to output stream. @param st Stream. @param c32 Character to write. @return 1 on success, 0 on error. */ static int dk3stream_my_write_32(dk3_stream_t *st, dk3_c32_t c32) { int back = 0; switch(st->oe) { case DK3_FILE_ENCODING_UNICODE_MSB_FIRST: { if(dk3stream_my_write_byte(st, (char)((c32 >> 24) & 0x000000FFUL))) { if(dk3stream_my_write_byte(st, (char)((c32 >> 16) & 0x000000FFUL))) { if(dk3stream_my_write_byte(st, (char)((c32 >> 8) & 0x000000FFUL))) { if(dk3stream_my_write_byte(st, (char)(c32 & 0x000000FFUL))) { back = 1; } } } } } break; case DK3_FILE_ENCODING_UNICODE_LSB_FIRST: { if(dk3stream_my_write_byte(st, (char)(c32 & 0x000000FFUL))) { if(dk3stream_my_write_byte(st, (char)((c32 >> 8) & 0x000000FFUL))) { if(dk3stream_my_write_byte(st, (char)((c32 >> 16) & 0x000000FFUL))) { if(dk3stream_my_write_byte(st, (char)((c32 >> 24) & 0x000000FFUL))) { back = 1; } } } } } break; } return back; } int dk3stream_fputc_c32(dk3_stream_t *st, dk3_c32_t c32, int *err_enc_rep) { int back = 0; dk3_c16_t myc16[4]; /* Buffer for UTF-16 encoding. */ unsigned char myuc[16]; /* Buffer for UTF-8 encoding. */ size_t l = 0; /* Length of encoded string. */ size_t i = 0; /* Index of current element to write. */ $? "+ dk3stream_fputc_c32" switch(st->oe) { case DK3_FILE_ENCODING_UNICODE_MSB_FIRST: case DK3_FILE_ENCODING_UNICODE_LSB_FIRST: { back = dk3stream_my_write_32(st, c32); } break; case DK3_FILE_ENCODING_UTF16_MSB_FIRST: case DK3_FILE_ENCODING_UTF16_LSB_FIRST: { l = dk3enc_uc2utf16(c32, myc16, 4); if(l) { back = 1; for(i = 0; i < l; i++) { if(!dk3stream_my_write_16(st, myc16[i])) { back = 1; } } } else { if(!(*err_enc_rep)) { if(st->app) { $? "! conversion to UTF-16" /* ERROR: UTF-16 encode failed! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 116); } } *err_enc_rep = 1; } } break; case DK3_FILE_ENCODING_ASCII: { if(c32 < (dk3_c32_t)0x00000100UL) { back = dk3stream_my_write_byte(st, (char)(c32 & 0x000000FFUL)); } else { if(!(*err_enc_rep)) { if(st->app) { /* ERROR: Character out of range! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 117); } } *err_enc_rep = 1; } } break; case DK3_FILE_ENCODING_UTF8: { l = dk3enc_uc2utf8(c32, myuc, 16); if(l) { i = dk3stream_write_bytes(st, (char const *)myuc, l); if(i == l) { back = 1; } } else { if(!(*err_enc_rep)) { if(st->app) { /* ERROR: UTF-8 encode failed! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 115); } } *err_enc_rep = 1; } } break; } $? "- dk3stream_fputc_c32 %d", back return back; } int dk3stream_write_byte_order_marker(dk3_stream_t *st) { int back = 0; if(st) { switch(st->oe) { case DK3_FILE_ENCODING_UTF16_MSB_FIRST: case DK3_FILE_ENCODING_UTF16_LSB_FIRST: { back = dk3stream_my_write_16(st, 0xFEFFU); } break; case DK3_FILE_ENCODING_UNICODE_MSB_FIRST: case DK3_FILE_ENCODING_UNICODE_LSB_FIRST: { back = dk3stream_my_write_32(st, 0x0000FEFFUL); } break; default: { back = 1; } break; } } return back; } int dk3stream_write_byte_order_marker_if_necessary(dk3_stream_t *st, int se) { int back = 1; switch(st->oe) { case DK3_FILE_ENCODING_UTF16_MSB_FIRST: case DK3_FILE_ENCODING_UTF16_LSB_FIRST: case DK3_FILE_ENCODING_UNICODE_MSB_FIRST: case DK3_FILE_ENCODING_UNICODE_LSB_FIRST: { back = dk3stream_write_byte_order_marker(st); } break; case DK3_FILE_ENCODING_UTF8: { if(DK3_FILE_ENCODING_UTF8 != se) { back = dk3stream_write_byte_order_marker(st); } } break; default: { } break; } return back; } int dk3stream_fputs_c8_plain(dk3_stream_t *st, char const *s) { int back = 0; int err_rep_enc = 0; /* Flag: Encoding error reported. */ char const *sp = NULL; /* Source pointer. */ char c = 0x00; /* Current character. */ unsigned char uc = 0x00; /* Unsigned version of current char. */ unsigned long ul = 0UL; /* 32-bit version of current char. */ if((st) && (s)) { switch(st->oe) { case DK3_FILE_ENCODING_ASCII: { back = dk3stream_c8_fputs(st, s); } break; default: { back = 1; sp = s; while(*sp) { c = *(sp++); uc = (unsigned char)c; ul = (unsigned long)uc; ul &= 0x000000FFUL; if(!dk3stream_fputc_c32(st, ul, &err_rep_enc)) { back = 0; } } } break; } } return back; } int dk3stream_fputs_c8_utf8(dk3_stream_t *st, char const *s) { int back = 0; int err_rep_dec = 0; /* Flag: Decoding error reported. */ int err_rep_enc = 0; /* Flag: Encoding error reported. */ unsigned char const *sp = NULL; /* Source pointer. */ dk3_c32_t c32 = 0UL; /* 32-bit version of current char. */ size_t sl = 0; /* Remaining source bytes. */ size_t used = 0; /* Bytes used. */ if((st) && (s)) { switch(st->oe) { case DK3_FILE_ENCODING_UTF8: { back = dk3stream_c8_fputs(st, s); } break; default: { back = 1; sp = (unsigned char const *)s; sl = dk3str_c8_len(s); while(sl) { used = 0; if(dk3enc_utf82uc(&c32, sp, sl, &used)) { if(used) { if(!dk3stream_fputc_c32(st, c32, &err_rep_enc)) { back = 0; } if(sl >= used) { sl = sl - used; sp = &(sp[used]); } else { sl = 0; } } else { sl = 0; back = 0; if(!err_rep_dec) { if(st->app) { /* ERROR: UTF-8 decode failed! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } err_rep_dec = 1; } } else { sl = 0; back = 0; if(!err_rep_dec) { if(st->app) { /* ERROR: UTF-8 decode failed! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } err_rep_dec = 1; } } } break; } } return back; } int dk3stream_fputs_c16(dk3_stream_t *st, dk3_c16_t const *s) { int back = 0; int err_rep_dec = 0; /* Flag: Decoding error reported. */ int err_rep_enc = 0; /* Flag: Encoding error reported. */ dk3_c16_t const *sp = NULL; /* Source pointer. */ dk3_c32_t c32 = 0UL; /* 32-bit version of current char. */ size_t sl = 0; /* Remaining source bytes. */ size_t used = 0; /* Source bytes used. */ if((st) && (s)) { switch(st->oe) { case DK3_FILE_ENCODING_UTF16_MSB_FIRST: case DK3_FILE_ENCODING_UTF16_LSB_FIRST: { sp = s; back = 1; while(*sp) { if(!dk3stream_my_write_16(st, *(sp++))) { back = 0; } } } break; default: { sp = s; sl = dk3str_c16_len(s); while(sl) { used = 0; if(dk3enc_utf162uc(&c32, sp, sl, &used)) { if(used) { if(!dk3stream_fputc_c32(st, c32, &err_rep_enc)) { back = 0; } if(sl >= used) { sl = sl - used; sp = &(sp[used]); } else { sl = 0; } } else { back = 0; sl = 0; if(!err_rep_dec) { if(st->app) { /* ERROR: Decode UTF-16 failed! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 119); } } err_rep_dec = 1; } } else { back = 0; sl = 0; if(!err_rep_dec) { if(st->app) { /* ERROR: Decode UTF-16 failed! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 119); } } err_rep_dec = 1; } } } break; } } return back; } int dk3stream_fputs_c32(dk3_stream_t *st, dk3_c32_t const *s) { int back = 0; int err_rep_enc = 0; /* Flag: Encoding error reported. */ dk3_c32_t const *sp = NULL; /* Source pointer. */ if((st) && (s)) { sp = s; back = 1; while(*sp) { if(!dk3stream_fputc_c32(st, *(sp++), &err_rep_enc)) { back = 0; } } } return back; } int dk3stream_strputs(dk3_stream_t *st, dkChar const *s, int ie) { int back = 0; $? "+ dk3stream_strputs" if((st) && (s)) { #if DK3_CHAR_SIZE > 1 #if DK3_CHAR_SIZE > 2 if(ie == DK3_ENCODING_UNICODE) { back = dk3stream_fputs_c32(st, s); } else { if(st->app) { /* ERROR: Encoding does not match character size! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 125); } } #else if(ie == DK3_ENCODING_UTF16) { back = dk3stream_fputs_c16(st, s); } else { if(st->app) { /* ERROR: Encoding does not match character size! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 125); } } #endif #else switch(ie) { case DK3_ENCODING_PLAIN: { back = dk3stream_fputs_c8_plain(st, s); } break; case DK3_ENCODING_UTF8: { back = dk3stream_fputs_c8_utf8(st, s); } break; default: { if(st->app) { /* ERROR: Encoding does not match character size! */ dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 125); } } break; } #endif } $? "- dk3stream_strputs %d", back return back; } int dk3stream_strnl(dk3_stream_t *st) { int back = 1; int err_enc_rep = 0; /* Flag: Encoding error reported. */ #if DK3_ON_WINDOWS if(!dk3stream_fputc_c32(st, 0x0000000DUL, &err_enc_rep)) { back = 0; } #endif if(!dk3stream_fputc_c32(st, 0x0000000AUL, &err_enc_rep)) { back = 0; } return back; } int dk3stream_set_line_flush(dk3_stream_t *st, int fl) { int back = 0; $? "+ dk3stream_set_line_flush" if(st) { st->lf = fl; back = 1; } $? "- dk3stream_set_line_flush %d", back return back; } dk3_um_t dk3stream_bytes_written(dk3_stream_t const *st) { dk3_um_t back = DK3_UM_0; $? "+ dk3stream_bytes_written" if(st) { back = st->wr; } $? "- dk3stream_bytes_written %llu", back return back; } dk3_stream_t * dk3stream_open_file_app(FILE *fi, int fl, dk3_app_t *app) { dk3_stream_t *back = NULL; $? "+ dk3stream_open_file_app" if(fi) { back = dk3stream_open_app((void *)fi, dk3stream_file_fct_no_close, fl, app); } $? "- dk3stream_open_file_app %s", TR_PTR(back) return back; } #if 0 #if DK3_HAVE_ZLIB_H dk3_stream_t * dk3stream_open_gz_app(gzFile g, int fl, dk3_app_t *app) { dk3_stream_t *back = NULL; if(g) { back = dk3stream_open_app((void *)g, dk3stream_gz_fct_no_close, fl, app); } return back; } #endif #endif #if 0 #if DK3_HAVE_BZLIB_H dk3_stream_t * dk3stream_open_bz2_app(BZFILE *b, int fl, dk3_app_t *app) { dk3_stream_t *back = NULL; if(b) { back = dk3stream_open_app((void *)b, dk3stream_bz_fct_no_close, fl, app); } return back; } #endif #endif int dk3stream_process_chars( dk3_stream_t *st, void *obj, dk3_char_handler_t *hf, int ie ) { int back = 0; int res; /* Handler function result. */ int cc; /* Flag: Can continue. */ int myie; /* Input encoding. */ int done; /* Flag: Character already handled. */ int surrogate; /* UTF-16 surrogate type. */ char c1; /* First byte. */ char c2; /* Second byte. */ char c3; /* Third byte. */ char c4; /* Fourth byte. */ unsigned char u1; /* Current byte. */ dk3_c32_t uc1; /* First part of result. */ dk3_c32_t uc2; /* Second part of result. */ dk3_c32_t uc3; /* Third part of result. */ dk3_c32_t uc4; /* Fourth part of result. */ dk3_c32_t c32; /* Character found in decoding. */ unsigned long lineno; /* Current line number. */ unsigned long oldlineno = 0UL; /* Line number before start. */ $? "+ dk3stream_process_chars" if((st) && (hf)) { if(st->app) { $? ". input encoding = %d", ie oldlineno = dk3app_get_source_line((dk3_app_t *)(st->app)); dk3app_set_source_line((dk3_app_t *)(st->app), 1UL); } lineno = 1UL; back = 1; cc = 1; myie = ie; $? ". myie = %d", myie do { $? ". loop start" cc = 0; done = 0; c32 = 0UL; switch(myie) { case DK3_FILE_ENCODING_ASCII: { $? ". ascii" if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 1 ok" cc = 1; c32 = (dk3_c32_t)c1; c32 &= 0x000000FFUL; } } break; case DK3_FILE_ENCODING_UTF8: { $? ". utf-8" if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 1 ok" u1 = (unsigned char)c1; if(u1 > 0x7F) { $? ". > 1 byte" if((u1 & 0xE0) == 0xC0) { $? ". 2 bytes" c32 = ((((dk3_c32_t)u1) << 6) & 0x000007C0UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 2 ok" u1 = (unsigned char)c1; c32 |= (((dk3_c32_t)u1) & 0x0000003FUL); cc = 1; } else { /* ERROR: Incomplete sequence! */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { if((u1 & 0xF0) == 0xE0) { $? ". 3 bytes" c32 = ((((dk3_c32_t)u1) << 12) & 0x0000F000UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 2 ok" u1 = (unsigned char)c1; c32 |= ((((dk3_c32_t)u1) << 6) & 0x00000FC0UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 3 ok" u1 = (unsigned char)c1; c32 |= (((dk3_c32_t)u1) & 0x0000003FUL); cc = 1; } else { /* ERROR: Incomplete sequence! */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence! */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { if((u1 & 0xF8) == 0xF0) { $? ". 4 bytes" c32 = ((((dk3_c32_t)u1) << 18) & 0x001C0000UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 2 ok" u1 = (unsigned char)c1; c32 |= ((((dk3_c32_t)u1) << 12) & 0x0003F000UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 3 ok" u1 = (unsigned char)c1; c32 |= ((((dk3_c32_t)u1) << 6) & 0x00000FC0UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 4 ok" u1 = (unsigned char)c1; c32 |= (((dk3_c32_t)u1) & 0x0000003FUL); cc = 1; } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { if((u1 & 0xFC) == 0xF8) { $? ". 5 bytes" c32 = ((((dk3_c32_t)u1) << 24) & 0x03000000UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 2 ok" u1 = (unsigned char)c1; c32 |= ((((dk3_c32_t)u1) << 18) & 0x00FC0000UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 3 ok" u1 = (unsigned char)c1; c32 |= ((((dk3_c32_t)u1) << 12) & 0x0003F000UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 4 ok" u1 = (unsigned char)c1; c32 |= ((((dk3_c32_t)u1) << 6) & 0x00000FC0UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 5 ok" u1 = (unsigned char)c1; c32 |= (((dk3_c32_t)u1) & 0x0000003FUL); cc = 1; } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { if((u1 & 0xFE) == 0xFC) { $? ". 6 bytes" c32 = 0x40000000UL; if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 2 ok" u1 = (unsigned char)c1; c32 |= ((((dk3_c32_t)u1) << 24) & 0x3F000000UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 3 ok" u1 = (unsigned char)c1; c32 |= ((((dk3_c32_t)u1) << 18) & 0x00FC0000UL); if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 4 ok" u1 = (unsigned char)c1; c32 |= ((((dk3_c32_t)u1) << 12) & 0x0003F000UL); if(dk3stream_my_read_byte(st, &c1)) { u1 = (unsigned char)c1; $? ". byte 5 ok" c32 |= ((((dk3_c32_t)u1) << 6) & 0x00000FC0UL); if(dk3stream_my_read_byte(st, &c1)) { u1 = (unsigned char)c1; $? ". byte 6 ok" c32 |= (((dk3_c32_t)u1) & 0x0000003FUL); cc = 1; } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 118); } } } else { } } } } } } else { c32 = ((dk3_c32_t)u1) & 0x000000FFUL; cc = 1; } } } break; case DK3_FILE_ENCODING_UTF16_MSB_FIRST: case DK3_FILE_ENCODING_UTF16_LSB_FIRST: { $? ". UTF-16" surrogate = 0; if(dk3stream_my_read_byte(st, &c1)) { $? ". c1=%02x", (int)c1 if(dk3stream_my_read_byte(st, &c2)) { $? ". c2=%02x", (int)c2 if(myie == DK3_FILE_ENCODING_UTF16_MSB_FIRST) { uc1 = (((dk3_c32_t)c1) << 8) & 0x0000FF00UL; uc2 = ((dk3_c32_t)c2) & 0x000000FFUL; } else { uc1 = (((dk3_c32_t)c2) << 8) & 0x0000FF00UL; uc2 = ((dk3_c32_t)c1) & 0x000000FFUL; } c32 = (uc1 | uc2); $? ". c32=%08lx", c32 #if 0 if((c32 & 0x0000DC00UL) == 0x0000DC00UL) #else if((c32 & 0x0000FC00UL) == 0x0000DC00UL) #endif { $? ". low surr" if(dk3stream_my_read_byte(st, &c1)) { $? ". b1 ok" if(dk3stream_my_read_byte(st, &c2)) { $? ". b2 ok" if(myie == DK3_FILE_ENCODING_UTF16_MSB_FIRST) { uc1 = (((dk3_c32_t)c1) << 8) & 0x0000FF00UL; uc2 = ((dk3_c32_t)c2) & 0x000000FFUL; } else { uc1 = (((dk3_c32_t)c2) << 8) & 0x0000FF00UL; uc2 = ((dk3_c32_t)c1) & 0x000000FFUL; } uc1 |= uc2; #if 0 if((uc1 & 0x0000DC00UL) == 0x0000D800UL) #else if((uc1 & 0x0000FC00UL) == 0x0000D800UL) #endif { uc1 &= 0x000003FFUL; uc1 = (uc1 << 10); uc1 &= 0x000FFC00UL; c32 &= 0x000003FFUL; c32 |= uc1; c32 += 0x00010000UL; cc = 1; } else { /* ERROR: Decoding. */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 119); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 119); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 119); } } } else { #if 0 if((c32 & 0x0000DC00UL) == 0x0000D800UL) #else if((c32 & 0x0000FC00UL) == 0x0000D800UL) #endif { $? ". hi surr" if(dk3stream_my_read_byte(st, &c1)) { $? ". b1 ok" if(dk3stream_my_read_byte(st, &c2)) { $? ". b2 ok" if(myie == DK3_FILE_ENCODING_UTF16_MSB_FIRST) { uc1 = (((dk3_c32_t)c1) << 8) & 0x0000FF00UL; uc2 = ((dk3_c32_t)c2) & 0x000000FFUL; } else { uc1 = (((dk3_c32_t)c2) << 8) & 0x0000FF00UL; uc2 = ((dk3_c32_t)c1) & 0x000000FFUL; } uc1 |= uc2; #if 0 if((uc1 & 0x0000DC00UL) == 0x0000DC00UL) #else if((uc1 & 0x0000DF00UL) == 0x0000DC00UL) #endif { c32 &= 0x000003FFUL; c32 = (c32 << 10); c32 &= 0x000FFC00UL; uc1 &= 0x000003FFUL; c32 |= uc1; c32 += 0x00010000UL; cc = 1; } else { /* ERROR: Decoding. */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 119); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 119); } } } else { /* ERROR: Incomplete sequence */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 119); } } } else { $? ". no surr" cc = 1; } } } else { /* ERROR: Incomplete word. */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 119); } } } } break; case DK3_FILE_ENCODING_UNICODE_MSB_FIRST: case DK3_FILE_ENCODING_UNICODE_LSB_FIRST: { $? ". UC32" if(dk3stream_my_read_byte(st, &c1)) { $? ". byte 1 ok" if(dk3stream_my_read_byte(st, &c2)) { $? ". byte 2 ok" if(dk3stream_my_read_byte(st, &c3)) { $? ". byte 3 ok" if(dk3stream_my_read_byte(st, &c4)) { $? ". byte 4 ok" if(myie == DK3_FILE_ENCODING_UNICODE_MSB_FIRST) { uc1 = (((dk3_c32_t)c1) << 24) & 0xFF000000UL; uc2 = (((dk3_c32_t)c2) << 16) & 0x00FF0000UL; uc3 = (((dk3_c32_t)c3) << 8) & 0x0000FF00UL; uc4 = (((dk3_c32_t)c4) ) & 0x000000FFUL; } else { uc1 = (((dk3_c32_t)c4) << 24) & 0xFF000000UL; uc2 = (((dk3_c32_t)c3) << 16) & 0x00FF0000UL; uc3 = (((dk3_c32_t)c2) << 8) & 0x0000FF00UL; uc4 = (((dk3_c32_t)c1) ) & 0x000000FFUL; } cc = 1; c32 = (uc1 | uc2 | uc3 | uc4); } else { /* ERROR: Incomplete DWORD */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 218); } } } else { /* ERROR: Incomplete DWORD */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 218); } } } else { /* ERROR: Incomplete DWORD */ if(st->app) { dk3app_log_i1((dk3_app_t *)(st->app), DK3_LL_ERROR, 218); } } } } break; } if(cc) { $? ". character found" if(c32 != 0x0000FEFFUL) { $? ". not BOM" switch(myie) { case DK3_FILE_ENCODING_UTF16_MSB_FIRST: { if(c32 == 0x0000FFFEUL) { $? ". BOM inverted" myie = DK3_FILE_ENCODING_UTF16_LSB_FIRST; done = 1; $? ". myie = %d", myie } } break; case DK3_FILE_ENCODING_UTF16_LSB_FIRST: { if(c32 == 0x0000FFFEUL) { $? ". BOM inverted" myie = DK3_FILE_ENCODING_UTF16_MSB_FIRST; done = 1; $? ". myie = %d", myie } } break; case DK3_FILE_ENCODING_UNICODE_MSB_FIRST: { if((unsigned long)c32 == 0xFFFE0000UL) { $? ". BOM inverted" myie = DK3_FILE_ENCODING_UNICODE_LSB_FIRST; done = 1; $? ". myie = %d", myie } } break; case DK3_FILE_ENCODING_UNICODE_LSB_FIRST: { if((unsigned long)c32 == 0xFFFE0000UL) { $? ". BOM inverted" myie = DK3_FILE_ENCODING_UNICODE_MSB_FIRST; done = 1; $? ". myie = %d", myie } } break; } if(!done) { $? ". process character 0x%08lx=%lu (%c)", c32, c32, (char)c32 res = (*hf)(obj, c32); if(res < 1) { back = 0; if(res < 0) { cc = 0; } } } if(c32 == 0x0000000AUL) { $? ". new line" lineno++; /* Set line number */ if(st->app) { dk3app_set_source_line((dk3_app_t *)(st->app), lineno); } } } } } while(cc); if(st->app) { dk3app_set_source_line((dk3_app_t *)(st->app), oldlineno); } } $? "- dk3stream_process_chars %d", back return back; } /* NOTE: This function does not check the BOM at start of files. Whenever applicable, use dk3stream_process_filename_chars_app() instead. */ int dk3stream_process_file_chars_app( void *obj, dk3_char_handler_t *hf, FILE *fipo, dkChar const *fn, int ie, dk3_app_t *app ) { int back = 0; dkChar const *oldsourcefile = NULL; unsigned long oldsourceline = 0UL; dk3_stream_t *is = NULL; $? "+ dk3stream_process_file_chars_app" if((hf) && (fipo)) { $? ". input encoding = %d", ie if(app) { oldsourcefile = dk3app_get_source_file(app); oldsourceline = dk3app_get_source_line(app); dk3app_set_source_file(app, fn); } is = dk3stream_open_file_app(fipo, DK3_STREAM_FLAG_READ, app); if(is) { back = dk3stream_process_chars(is, obj, hf, ie); dk3stream_close(is); } if(app) { dk3app_set_source_file(app, oldsourcefile); dk3app_set_source_line(app, oldsourceline); } } $? "- dk3stream_process_file_chars_app %d", back return back; } int dk3stream_process_filename_chars_app( void *obj, dk3_char_handler_t *hf, dkChar const *fn, int de, dk3_app_t *app ) { char bombuf[4]; FILE *fipo; /* Input file. */ size_t skb; int back = 0; int ie; /* Input encoding. */ $? "+ dk3stream_process_filename_chars_app \"%s\"", TR_STR(fn) if((hf) && (fn)) { ie = de; $? ". ie (original) = %d", ie skb = 0; ie = dk3sf_inspect_bom_skip_app(fn, ie, &skb, NULL); $? ". ie (BOM) = %d", ie fipo = dk3sf_fopen_app(fn, dk3app_not_localized(36), app); if(fipo) { if((skb > 0) && (skb <=4)) { dk3sf_fread_app(bombuf, 1, skb, fipo, app); } back = dk3stream_process_file_chars_app(obj, hf, fipo, fn, ie, app); fclose(fipo); } } $? "- dk3stream_process_filename_chars_app %d", back return back; } /** Add one found 32-bit character to input line, process input line if newline found or if buffer is full. @param lhv A dk3_line_handler_data_t pointer. @param c32 Current character to process. @return 1=OK, can continue, 0=error, can continue, -1=error, abort. */ static int dk3stream_add_character_to_line(void *lhv, dk3_c32_t c32) { int back = 1; dk3_line_handler_data_t *lh; dkChar *cp; /* Current position. */ int res; /* Handler result. */ #if DK3_CHAR_SIZE > 1 dk3_c16_t u16p[8]; /* Buffer UTF-16 */ size_t used; /* Elements used in u16p. */ size_t i; /* Running index. */ #else unsigned char uc; /* Unsigned char. */ char c; /* Current char. */ unsigned char u8p[8]; /* Buffer UTF-8. */ size_t used; /* Elements used in u8p. */ size_t i; /* Running index. */ #endif $? "+ dk3stream_add_character_to_line" lh = (dk3_line_handler_data_t *)lhv; #if DK3_CHAR_SIZE > 1 used = dk3enc_uc2utf16(c32, u16p, DK3_SIZEOF(u16p,dk3_c16_t)); if(used > 0) { if((lh->bufus + used) < (lh->szbuf - 1)) { cp = lh->cp; for(i = 0; i < used; i++) { cp[i] = u16p[i]; } cp = &(cp[used]); *cp = dkT('\0'); lh->cp = cp; lh->bufus += used; if(c32 == 0x0000000AUL) { /* FLUSH OUTPUT */ (lh->buf)[lh->szbuf - 1] = dkT('\0'); res = (*(lh->hf))(lh->obj, lh->buf); if(res < 1) { back = 0; if(res < 0) { back = -1; } } /* Start new line */ lh->cp = lh->buf; (lh->buf)[0] = '\0'; lh->bufus = 0; } } else { back = 0; /* Warning: Line too long */ if(lh->app) { dk3app_log_i1((dk3_app_t *)(lh->app), DK3_LL_WARNING, 108); } (lh->buf)[lh->szbuf - 1] = dkT('\0'); res = (*(lh->hf))(lh->obj, lh->buf); if(res < -1) { back = -1; } cp = lh->buf; for(i = 0; i < used; i++) { cp[i] = u16p[i]; } cp = &(cp[used]); *cp = dkT('\0'); lh->cp = cp; lh->bufus = used; if(c32 == 0x0000000AUL) { lh->cp = lh->buf; *(lh->buf) = dkT('\0'); lh->bufus = 0; } } } else { /* ERROR: Encoding failed! */ if(lh->app) { dk3app_log_i1((dk3_app_t *)(lh->app), DK3_LL_ERROR, 119); } } #else $? ". 1 byte character" if(lh->se == DK3_ENCODING_UTF8) { $? ". process character as UTF-8" used = dk3enc_uc2utf8(c32, u8p, sizeof(u8p)); if(used > 0) { $? ". conversion result ok" if((lh->bufus + used) < (lh->szbuf - 1)) { $? ". buffer length ok" cp = lh->cp; $? ". copy bytes" for(i = 0; i < used; i++) { cp[i] = u8p[i]; } cp = &(cp[used]); $? ". copy ok" *cp = '\0'; lh->cp = cp; lh->bufus += used; $? ". buffer used %u", (unsigned)(lh->bufus) if(c32 == 0x0000000AUL) { $? ". newline" /* FLUSH OUTPUT */ (lh->buf)[lh->szbuf - 1] = dkT('\0'); res = (*(lh->hf))(lh->obj, lh->buf); if(res < 1) { back = 0; if(res < 0) { back = -1; } } /* Start new line */ lh->cp = lh->buf; (lh->buf)[0] = '\0'; lh->bufus = 0; } $? ". processing finished" } else { $? "! line too long" back = 0; /* Warning: Line too long! */ if(lh->app) { dk3app_log_i1(lh->app, DK3_LL_WARNING, 108); } /* FLUSH OUTPUT */ (lh->buf)[lh->szbuf - 1] = dkT('\0'); res = (*(lh->hf))(lh->obj, lh->buf); if(res < -1) { back = -1; } /* Start new line. */ cp = lh->buf; for(i = 0; i < used; i++) { cp[i] = u8p[i]; } cp = &(cp[used]); *cp = '\0'; lh->cp = cp; lh->bufus = used; if(c32 == 0x0000000AUL) { *(lh->buf) = '\0'; lh->cp = lh->buf; lh->bufus = 0; } } } else { $? "! UTF-8 conversion failed" back = 0; /* ERROR: Encoding failed! */ if(lh->app) { $? "! conversion to UTF-8" dk3app_log_i1(lh->app, DK3_LL_ERROR, 115); } } } else { $? ". process plain character" if((unsigned long)c32 > 0x000000FFUL) { /* Warning: Character out of range. */ if(lh->app) { dk3app_log_i1(lh->app, DK3_LL_WARNING, 219); } } uc = (unsigned char)c32; c = (char)uc; if((lh->bufus + 1) < (lh->szbuf - 1)) { cp = lh->cp; *(cp++) = c; *cp = '\0'; lh->cp = cp; lh->bufus += 1; if(c32 == 0x0000000AUL) { /* FLUSH OUTPUT */ (lh->buf)[lh->szbuf - 1] = dkT('\0'); res = (*(lh->hf))(lh->obj, lh->buf); if(res < 1) { back = 0; if(res < 0) { back = -1; } } /* Start new line */ lh->cp = lh->buf; (lh->buf)[0] = '\0'; lh->bufus = 0; } } else { back = 0; /* Warning: Line too long! */ if(lh->app) { dk3app_log_i1(lh->app, DK3_LL_WARNING, 108); } /* FLUSH OUTPUT */ (lh->buf)[lh->szbuf - 1] = dkT('\0'); res = (*(lh->hf))(lh->obj, lh->buf); if(res < -1) { back = -1; } /* Start new line. */ cp = lh->buf; *(cp++) = c; *cp = '\0'; lh->cp = cp; lh->bufus = 1; if(c32 == 0x0000000AUL) { *(lh->buf) = '\0'; lh->cp = lh->buf; lh->bufus = 0; } } } #endif $? "- dk3stream_add_character_to_line %d", back return back; } int dk3stream_process_lines( dk3_stream_t *st, void *obj, dk3_line_handler_t *hf, dkChar *buf, size_t szbuf, int se, int ie ) { int back = 0; dk3_line_handler_data_t lh; $? "+ dk3stream_process_lines" if((st) && (hf) && (buf) && (szbuf)) { lh.app = (dk3_app_t *)(st->app); lh.obj = obj; lh.hf = hf; lh.buf = buf; buf[0] = dkT('\0'); lh.szbuf = szbuf; lh.cp = lh.buf; lh.bufus = 0; lh.se = se; back = dk3stream_process_chars( st, (void *)(&lh), dk3stream_add_character_to_line, ie ); } $? "- dk3stream_process_lines %d", back return back; } /* NOTE: This function does not check for a BOM at the beginning of the file. Whenever applicable, use dk3stream_process_filename_lines_app() instead. */ int dk3stream_process_file_lines_app( void *obj, dk3_line_handler_t *hf, FILE *fipo, dkChar const *fn, dkChar *buf, size_t szbuf, int se, int ie, dk3_app_t *app ) { int back = 0; dkChar const *oldsourcename = NULL; unsigned long oldsourceline = 0UL; dk3_stream_t *is; $? "+ dk3stream_process_file_lines_app" if((hf) && (fipo)) { $? ". args ok" if(app) { $? ". saving old position" oldsourcename = dk3app_get_source_file(app); oldsourceline = dk3app_get_source_line(app); dk3app_set_source_file(app, fn); dk3app_set_source_line(app, 1UL); } is = dk3stream_open_file_app(fipo, DK3_STREAM_FLAG_READ, app); if(is) { $? ". stream opened" back = dk3stream_process_lines(is, obj, hf, buf, szbuf, se, ie); dk3stream_close(is); } else { $? "! no stream" } if(app) { $? ". restoring old position" dk3app_set_source_file(app, oldsourcename); dk3app_set_source_line(app, oldsourceline); } } $? "- dk3stream_process_file_lines_app %d", back return back; } int dk3stream_process_filename_lines_app( void *obj, dk3_line_handler_t *hf, dkChar const *fn, dkChar *buf, size_t szbuf, int se, int de, dk3_app_t *app ) { char bombuf[4]; FILE *fipo; /* Input file. */ size_t skb; /* Bytes to skip at start of input. */ int ie; /* Input encoding. */ int back = 0; $? "+ dk3stream_process_filename_lines_app \"%s\" %d", TR_STR(fn), de if((hf) && (fn)) { ie = dk3sf_inspect_bom_skip_app(fn, de, &skb, app); $? ". ie=%d", ie fipo = dk3sf_fopen_app(fn, dk3app_not_localized(36), app); if(fipo) { $? ". file opened" if((skb > 0) && (skb <= 4)) { dk3sf_fread_app(bombuf, 1, skb, fipo, app); } back = dk3stream_process_file_lines_app( obj, hf, fipo, fn, buf, szbuf, se, ie, app ); fclose(fipo); } } $? "- dk3stream_process_filename_lines_app %d", back return back; } int dk3strm_double_c8_str_no_sci(dk3_stream_t *os, char *buffer) { char *start; /* Start of string. */ char *eptr; /* Start of exponent substring. */ char *ptr; /* Traverse string. */ size_t lgt; /* String length. */ int dp; /* Decimal dot position. */ int exponent; /* Exponent. */ int i; /* Traverse the string. */ int back = 1; /* Result */ char chr; /* Character to write out */ $? "+ dk3ma_print_double_c8_str_no_sci" if((os) && (buffer)) { eptr = NULL; start = buffer; /* Print sign. */ switch(*start) { case '-': { if (1 != dk3stream_write_bytes(os, start, 1)) { back = 0; } start++; } break; case '+': { start++; } break; } /* Find exponent substring and exponent. */ eptr = NULL; ptr = start; while(*ptr) { switch(*ptr) { case 'e': case 'E': { eptr = ptr; } break; } ptr++; } if(eptr) { *(eptr++) = '\0'; #if VERSION_BEFORE_20140716 if(sscanf(eptr, "%d", &exponent) != 1) #else if (0 == dk3ma_i_from_c8_string(&exponent, eptr, NULL)) #endif { exponent = 0; } } else { exponent = 0; } /* Find decimal dot. */ eptr = strchr(start, '.'); if(eptr) { /* Keep dot position in dp, squeeze string. */ *eptr = '\0'; dp = (int)strlen(start); *eptr = '.'; while(*eptr) { eptr[0] = eptr[1]; eptr++; } } else { /* Dot position is after the string. */ dp = (int)strlen(start); } /* Correct dot position. */ dp = dp + exponent; /* Remove leading zeroes (if any). */ while('0' == *start) { start++; dp--; } /* Remove trailing zeroes (if any). */ eptr = NULL; ptr = start; while(*ptr) { if('0' == *ptr) { if(!(eptr)) { eptr = ptr; } } else { eptr = NULL; } ptr++; } if(eptr) { *eptr = '\0'; } lgt = strlen(start); if(0 < lgt) { if(dp >= (int)lgt) { /* Decimal dot is at end or after string. */ if (1 != dk3stream_c8_fputs(os, start)) { back = 0; } /* Decimal dot is after the string. */ for(i = 0; i < (dp - (int)lgt); i++) { chr = '0'; if (1 != dk3stream_write_bytes(os, &chr, 1)) { back = 0; } } } else { if(dp <= 0) { /* Decimal dot is before the string. */ chr = '0'; if (1 != dk3stream_write_bytes(os, &chr, 1)) { back = 0; } chr = '.'; if (1 != dk3stream_write_bytes(os, &chr, 1)) { back = 0; } chr = 0; while(dp++ < 0) { if (1 != dk3stream_write_bytes(os, &chr, 1)) { back = 0; } } if (1 != dk3stream_c8_fputs(os, start)) { back = 0; } } else { /* Decimal dot is in the string. */ for(i = 0; i < (int)lgt; i++) { if(dp == i) { chr = '.'; if (1 != dk3stream_write_bytes(os, &chr, 1)) { back = 0; } } if (1 != dk3stream_write_bytes(os, &(start[i]), 1)) { back = 0; } } } } } else { /* No non-zero digits in string. */ chr = '0'; if (1 != dk3stream_write_bytes(os, &chr, 1)) { back = 0; } } } $? "- dk3ma_print_double_c8_str_no_sci" return back; } int dk3strm_double_c8_no_sci(dk3_stream_t *os, double x) { char buffer[64]; char *ptr; int back = 0; if (NULL != os) { if (1 == sprintf(buffer, "%lg", x)) { ptr = buffer; while(*ptr) { if (',' == *ptr) { *ptr = '.'; } ptr++; } back = dk3strm_double_c8_str_no_sci(os, buffer); } } return back; } /* vim: set ai sw=2 : */