From: adam Date: Wed, 7 Nov 2012 09:59:34 +0000 (+0700) Subject: #2 fixed snprintf localization issue X-Git-Tag: v1.2.12~642^2~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d59784c0288abfa09dd2b753870399a00d9e7fb8;p=platform%2Fupstream%2Fejdb.git #2 fixed snprintf localization issue --- diff --git a/Changelog b/Changelog index edd67e7..2df3735 100644 --- a/Changelog +++ b/Changelog @@ -1,8 +1,8 @@ 2012-11-06 Anton Adamansky. - - Node.js binding + * Node.js binding - Release 1.0.1 2012-10-27 Anton Adamansky. - - Initial release based on Tokyo Cabinet v1.4.48 + * Initial release based on Tokyo Cabinet v1.4.48 - Release 1.0.0 diff --git a/tcejdb/ejdb.c b/tcejdb/ejdb.c index 75590bf..759a036 100644 --- a/tcejdb/ejdb.c +++ b/tcejdb/ejdb.c @@ -2542,10 +2542,9 @@ static char* _bsonitstrval(bson_iterator *it, int *vsz, TCLIST *tokens) { } ret = tcmemdup(nbuff, *vsz); } else if (btype == BSON_DOUBLE) { - *vsz = snprintf(nbuff, TCNUMBUFSIZ, "%lf", bson_iterator_double(it)); + *vsz = tcftoa(bson_iterator_double(it), nbuff, TCNUMBUFSIZ, 6); if (*vsz >= TCNUMBUFSIZ) { *vsz = TCNUMBUFSIZ - 1; - nbuff[TCNUMBUFSIZ - 1] = '\0'; } ret = tcmemdup(nbuff, *vsz); } diff --git a/tcejdb/tctdb.c b/tcejdb/tctdb.c index 29efb95..da4da3a 100644 --- a/tcejdb/tctdb.c +++ b/tcejdb/tctdb.c @@ -2239,8 +2239,8 @@ static double tctdbaddnumber(TCTDB *tdb, const void *pkbuf, int pksiz, double nu TCFREE(cbuf); } char numbuf[TDBCOLBUFSIZ]; - int len = snprintf(numbuf, TDBCOLBUFSIZ - 1, "%f", num); - if(len > TDBCOLBUFSIZ - 1){ + int len = tcftoa(num, numbuf, TDBCOLBUFSIZ, 6); + if(len >= TDBCOLBUFSIZ){ //truncation tctdbsetecode(tdb, TCEMISC, __FILE__, __LINE__, __func__); num = nan(""); } else { diff --git a/tcejdb/tcutil.c b/tcejdb/tcutil.c index b3bbbc6..52ec642 100644 --- a/tcejdb/tcutil.c +++ b/tcejdb/tcutil.c @@ -290,11 +290,13 @@ static void tcvxstrprintf(TCXSTR *xstr, const char *format, va_list ap){ break; case 'e': case 'E': case 'f': case 'g': case 'G': if(lnum >= 1){ - tlen = snprintf(tbuf, sizeof(tbuf), cbuf, va_arg(ap, long double)); + //tlen = snprintf(tbuf, sizeof(tbuf), cbuf, va_arg(ap, long double)); + tlen = tcftoa(va_arg(ap, long double), tbuf, sizeof(tbuf), 6); } else { - tlen = snprintf(tbuf, sizeof(tbuf), cbuf, va_arg(ap, double)); + //tlen = snprintf(tbuf, sizeof(tbuf), cbuf, va_arg(ap, double)); + tlen = tcftoa(va_arg(ap, double), tbuf, sizeof(tbuf), 6); } - if(tlen < 0 || tlen > sizeof(tbuf)){ + if(tlen < 0 || tlen >= sizeof(tbuf)){ tbuf[sizeof(tbuf)-1] = '*'; tlen = sizeof(tbuf); } @@ -5251,6 +5253,123 @@ double tcatof(const char *str){ } +//Basic code of `ftoa()' taken from scmRTOS https://sourceforge.net/projects/scmrtos +//Copyright (c) 2009-2012by Anton Gusev aka AHTOXA +#define FTOA_MAX_PRECISION (10) +static const double rounders[FTOA_MAX_PRECISION + 1] = { + 0.5, // 0 + 0.05, // 1 + 0.005, // 2 + 0.0005, // 3 + 0.00005, // 4 + 0.000005, // 5 + 0.0000005, // 6 + 0.00000005, // 7 + 0.000000005, // 8 + 0.0000000005, // 9 + 0.00000000005 // 10 +}; + +int tcftoa(long double f, char *buf, int max, int precision) { + +#define FTOA_SZSTEP(_step) if ((ret += (_step)) >= max) { \ + *ptr = 0; \ + return ret; \ + } + if (max <= 0) { + return 0; + } + char *ptr = buf; + char *p = ptr; + char c; + char *p1; + long intPart; + int ret = 0; + + // check precision bounds + if (precision > FTOA_MAX_PRECISION) + precision = FTOA_MAX_PRECISION; + + // sign stuff + if (f < 0) { + f = -f; + FTOA_SZSTEP(1) + *ptr++ = '-'; + } + if (precision == -1) { + if (f < 1.0) precision = 6; + else if (f < 10.0) precision = 5; + else if (f < 100.0) precision = 4; + else if (f < 1000.0) precision = 3; + else if (f < 10000.0) precision = 2; + else if (f < 100000.0) precision = 1; + else precision = 0; + } + if (precision) { + // round value according the precision + f += rounders[precision]; + } + // integer part... + intPart = f; + f -= intPart; + + if (!intPart) { + FTOA_SZSTEP(1) + *ptr++ = '0'; + } else { + // save start pointer + p = ptr; + while (intPart) { + if (++ret >= max) { //overflow condition + memmove(ptr, ptr + 1, p - ptr); + p--; + } + *p++ = '0' + intPart % 10; + intPart /= 10; + } + // save end pos + p1 = p; + // reverse result + while (p > ptr) { + c = *--p; + *p = *ptr; + *ptr++ = c; + } + if (ret >= max) { + ptr = p1; + *ptr = 0; + return ret; + } + // restore end pos + ptr = p1; + } + + // decimal part + if (precision) { + // place decimal point + if ((ret += 1) + 1 >= max) { //reserve one more after dot + *ptr = 0; + return ret; + } + *ptr++ = '.'; + // convert + while (precision--) { + f *= 10.0; + c = f; + FTOA_SZSTEP(1) + *ptr++ = '0' + c; + f -= c; + } + } + // terminating zero + *ptr = 0; + return ret; + +#undef FTOA_SZSTEP +} + + + /* Check whether a string matches a regular expression. */ bool tcregexmatch(const char *str, const char *regex){ assert(str && regex); diff --git a/tcejdb/tcutil.h b/tcejdb/tcutil.h index fa72f49..12b2cb5 100644 --- a/tcejdb/tcutil.h +++ b/tcejdb/tcutil.h @@ -2484,6 +2484,22 @@ int64_t tcatoix(const char *str); double tcatof(const char *str); +/** + * Fast conversion of a double number into a string. + * `cftoa' do not write into `buf' more than `max' bytes + * (including the terminating null byte ('\0')). + * + * If returned value >= `max' it indicates truncation occuried. + * + * @param f Number to convert + * @param buf Output buffer. + * @param max Maximum number of bytes to write into buffer including termination '\0' + * @param precision Number of signs after dot. + * @return + */ +int tcftoa(long double f, char *buf, int max, int precision); + + /* Check whether a string matches a regular expression. `str' specifies the target string. `regex' specifies the regular expression string. If it begins with `*', the trailing