%% options copyright owner = Dirk Krause copyright year = 2016-xxxx license = bsd %% header /** @file dk4c8dbl.h Write double value to file or stream without scientific notation. */ #ifndef DK4CONF_H_INCLUDED #include #endif #ifndef DK4TYPES_H_INCLUDED #include #endif #ifndef STDIO_H_INCLUDED #include #define STDIO_H_INCLUDED 1 #endif #ifndef DK4ERROR_H_INCLUDED #include #endif #ifndef DK4STRM_H_INCLUDED #include #endif #ifdef __cplusplus extern "C" { #endif /** Write double value to stream, avoid scientific notation. @param strm Stream to write to. @param v Value to write. @param exact Flag: Exact representation. @param minim Flag: Minimize an exact representation. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4c8dbl_double_to_stream( dk4_stream_t *strm, double v, int exact, int minim, dk4_er_t *erp ); /** Write double value to stream, avoid scientific notation. @param fipo File to write to. @param v Value to write. @param exact Flag: Exact representation. @param minim Flag: Minimize an exact representation. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4c8dbl_double_to_file( FILE *fipo, double v, int exact, int minim, dk4_er_t *erp ); /** Write double string to stream, avoid scientific notation. @param fipo File to write to. @param str String containing the value. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ int dk4c8dbl_str_double_to_file( FILE *fipo, const char *str, dk4_er_t *erp ); #ifdef __cplusplus } #endif /* vim: set ai sw=4 ts=4 : */ %% module #include "dk4c8dbl.h" #if DK4_HAVE_STRING_H #include #endif #if DK4_HAVE_STDLIB_H #include #endif #include "dk4mao8dbl.h" #include "dk4mai8ddi.h" #include "dk4str8.h" $!trace-include /** Write character to stream or file. @param dptr Destination for write operations. @param dtp Type of dptr: 0=FILE, 1=dk4_stream_t. @param c 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 opened for writing, - DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed, - DK4_E_FLUSH_FAILED
if flusing data downwards failed. */ static int dk4c8dbl_i_byte_to_void( void *dptr, int dtp, char c, dk4_er_t *erp ) { int back; switch (dtp) { case 1: { back = dk4stream_write_byte((dk4_stream_t*)dptr, c, erp); } break; default: { if (EOF != fputc(c, (FILE *)dptr)) { back = 1; } else { back = 0; dk4error_set_simple_error_code(erp, DK4_E_WRITE_FAILED); } } break; } return back; } static void dk4c8dbl_i_cut_trailing_zeroes(char *str) { char *cutpos = NULL; $? "+ dk4c8dbl_i_cut_trailing_zeroes \"%!8s\"", str while ('\0' != *str) { $? ". c = \"%c\"", *str if ('0' == *str) { $? ". 0" if (NULL == cutpos) { $? ". new cut position" cutpos = str; } } else { $? ". not 0" cutpos = NULL; $? ". can not cut" } str++; } if (NULL != cutpos) { $? ". can cut" *cutpos = '\0'; } $? "- dk4c8dbl_i_cut_trailing_zeroes" } /** Write double value to stream or file, avoid scientific notation. @param dptr Destination for write operations. @param dtp Type of dptr: 0=FILE, 1=dk4_stream_t. @param str String representation of double. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr is NULL, - DK4_E_BUFFER_TOO_SMALL
if the internal destination buffer is too small to store the string, - DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed, - DK4_E_FLUSH_FAILED
if flusing data downwards failed. */ static int dk4c8dbl_i_str_to_void( void *dptr, int dtp, char *str, dk4_er_t *erp ) { char *eptr; /* Position of 'e' */ char *ddptr; /* Position of decimal dot */ char *p1; /* Traverse string */ const char *endptr = NULL; /* End of processed data exponent */ dk4_im_t expo = (dk4_im_t)0L; /* Exponent value */ size_t dotpos; /* Position of decimal dot */ int isneg = 0; /* Flag: Negative number */ int back = 0; /* Function result */ int res; /* Conversion result */ $? "+ dk4c8dbl_i_str_to_void \"%!8s\"", str /* Check for scientific notation */ eptr = strchr(str, 'e'); if (NULL == eptr) { eptr = strchr(str, 'E'); } if (NULL != eptr) { $? ". exponent found" /* Scientific notation found, analyse string first ----------------------------------------------- */ /* Check for negative value (unary minus) */ if ('-' == *str) { isneg = 1; str++; } /* Retrieve exponent value */ *(eptr++) = '\0'; res = dk4ma_input_c8_dec_dk4_im_t( &expo, eptr, &endptr, 1, erp); if (0 == res) { expo = (dk4_im_t)0L; } $? ". expo = %ld", (long)expo /* Find position of decimal dot and convert string digit sequence */ ddptr = strchr(str, '.'); if (NULL != ddptr) { *ddptr = '\0'; dotpos = strlen(str); dk4str8_cpy_to_left(ddptr, &(ddptr[1])); dk4c8dbl_i_cut_trailing_zeroes(&(ddptr[1])); } else { dotpos = strlen(str); } /* Calculate real position of decimal dot. */ expo += (dk4_im_t)dotpos; /* Remove leading zeroes */ while (('0' == *str) && ('\0' != str[1])) { str++; expo--; } /* Now write the number -------------------- */ back = 1; /* Write unary minus for negative numbers */ if (0 != isneg) { if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '-', erp)) { back = 0; } } if ((dk4_im_t)0L >= expo) { /* Decimal dot is before first digit in string */ if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '0', erp)) { back = 0; } if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '.', erp)) { back = 0; } while ((dk4_im_t)0L > expo++) { if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '0', erp)) { back = 0; } } p1 = str; while ('\0' != *p1) { if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, *(p1++), erp)) { back = 0; } } } else { /* Decimal dot is in string or after string */ p1 = str; while ('\0' != *p1) { if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, *p1, erp)) { back = 0; } expo--; p1++; if ((dk4_im_t)0L == expo) { if ('\0' != *p1) { if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '.', erp)) { back = 0; } } } } while ((dk4_im_t)0L < expo--) { if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '0', erp)) { back = 0; } } } } else { $? ". no exponent" /* No exponent, can ship out string as is -------------------------------------- */ /* Remove leading zeroes */ while (('0' == *str) && ('\0' != str[1])) { str++; } /* Remove trailing zeroes */ ddptr = strchr(str, '.'); if (NULL != ddptr) { ddptr++; ddptr++; dk4c8dbl_i_cut_trailing_zeroes(ddptr); $? ". str = \"%!8s\"", str } /* Write output */ back = 1; p1 = str; if ('.' == *str) { if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, '0', erp)) { back = 0; } } while ('\0' != *p1) { if (0 == dk4c8dbl_i_byte_to_void(dptr, dtp, *(p1++), erp)) { back = 0; } } } $? "- dk4c8dbl_i_str_to_void" return back; } /** Write double value to stream or file, avoid scientific notation. @param dptr Destination for write operations. @param dtp Type of dptr: 0=FILE, 1=dk4_stream_t. @param v Value to write. @param exact Flag: Exact representation. @param minim Flag: Minimize an exact representation. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr is NULL, - DK4_E_BUFFER_TOO_SMALL
if the internal destination buffer is too small to store the string, - DK4_E_WRITE_FAILED
if writing one ore multiple bytes to the stream failed, - DK4_E_FLUSH_FAILED
if flusing data downwards failed. */ static int dk4c8dbl_i_double_to_void( void *dptr, int dtp, double v, int exact, int minim, dk4_er_t *erp ) { char buf[16*sizeof(double)]; size_t szbuf = sizeof(buf); int res = 0; int back = 0; if (NULL != dptr) { res = dk4ma_write_c8_double(buf, szbuf, v, exact, minim, erp); if (0 != res) { back = dk4c8dbl_i_str_to_void(dptr, dtp, buf, erp); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4c8dbl_double_to_stream( dk4_stream_t *strm, double v, int exact, int minim, dk4_er_t *erp ) { return (dk4c8dbl_i_double_to_void((void *)strm, 1, v, exact, minim, erp)); } int dk4c8dbl_double_to_file( FILE *fipo, double v, int exact, int minim, dk4_er_t *erp ) { return (dk4c8dbl_i_double_to_void((void *)fipo, 0, v, exact, minim, erp)); } int dk4c8dbl_str_double_to_file( FILE *fipo, const char *str, dk4_er_t *erp ) { char buf[16*sizeof(double)]; int back = 0; if ((NULL != fipo) && (NULL != str)) { if (strlen(str) < sizeof(buf)) { strcpy(buf, str); back = dk4c8dbl_i_str_to_void((void *)fipo, 0, buf, erp); } else { dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } /* vim: set ai sw=4 ts=4 : */