diff options
author | Mike Pall <mike> | 2016-02-26 17:59:43 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2016-02-26 18:03:08 +0100 |
commit | 18f6aa97fd93df8e9964c2d22f20f16e6b71b72b (patch) | |
tree | fad1176f6c01dc1aaf36bafa0b73f22b8e1c37e4 /src/lj_strfmt.c | |
parent | 339a1fd69611e2fd084127ee11a36e57035639d1 (diff) | |
download | luajit-18f6aa97fd93df8e9964c2d22f20f16e6b71b72b.tar.gz luajit-18f6aa97fd93df8e9964c2d22f20f16e6b71b72b.tar.bz2 luajit-18f6aa97fd93df8e9964c2d22f20f16e6b71b72b.zip |
Use internal implementation for converting FP numbers to strings.
Contributed by Peter Cawley.
Diffstat (limited to 'src/lj_strfmt.c')
-rw-r--r-- | src/lj_strfmt.c | 108 |
1 files changed, 11 insertions, 97 deletions
diff --git a/src/lj_strfmt.c b/src/lj_strfmt.c index d54e796a..ba9e1ff8 100644 --- a/src/lj_strfmt.c +++ b/src/lj_strfmt.c | |||
@@ -18,7 +18,7 @@ | |||
18 | /* -- Format parser ------------------------------------------------------- */ | 18 | /* -- Format parser ------------------------------------------------------- */ |
19 | 19 | ||
20 | static const uint8_t strfmt_map[('x'-'A')+1] = { | 20 | static const uint8_t strfmt_map[('x'-'A')+1] = { |
21 | STRFMT_A,0,0,0,STRFMT_E,0,STRFMT_G,0,0,0,0,0,0, | 21 | STRFMT_A,0,0,0,STRFMT_E,STRFMT_F,STRFMT_G,0,0,0,0,0,0, |
22 | 0,0,0,0,0,0,0,0,0,0,STRFMT_X,0,0, | 22 | 0,0,0,0,0,0,0,0,0,0,STRFMT_X,0,0, |
23 | 0,0,0,0,0,0, | 23 | 0,0,0,0,0,0, |
24 | STRFMT_A,0,STRFMT_C,STRFMT_D,STRFMT_E,STRFMT_F,STRFMT_G,0,STRFMT_I,0,0,0,0, | 24 | STRFMT_A,0,STRFMT_C,STRFMT_D,STRFMT_E,STRFMT_F,STRFMT_G,0,STRFMT_I,0,0,0,0, |
@@ -89,24 +89,6 @@ retlit: | |||
89 | 89 | ||
90 | /* -- Raw conversions ----------------------------------------------------- */ | 90 | /* -- Raw conversions ----------------------------------------------------- */ |
91 | 91 | ||
92 | /* Write number to bufer. */ | ||
93 | char * LJ_FASTCALL lj_strfmt_wnum(char *p, cTValue *o) | ||
94 | { | ||
95 | if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */ | ||
96 | #if __BIONIC__ | ||
97 | if (tvismzero(o)) { *p++ = '-'; *p++ = '0'; return p; } | ||
98 | #endif | ||
99 | return p + lua_number2str(p, o->n); | ||
100 | } else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) { | ||
101 | *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; | ||
102 | } else if ((o->u32.hi & 0x80000000) == 0) { | ||
103 | *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; | ||
104 | } else { | ||
105 | *p++ = '-'; *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; | ||
106 | } | ||
107 | return p; | ||
108 | } | ||
109 | |||
110 | #define WINT_R(x, sh, sc) \ | 92 | #define WINT_R(x, sh, sc) \ |
111 | { uint32_t d = (x*(((1<<sh)+sc-1)/sc))>>sh; x -= d*sc; *p++ = (char)('0'+d); } | 93 | { uint32_t d = (x*(((1<<sh)+sc-1)/sc))>>sh; x -= d*sc; *p++ = (char)('0'+d); } |
112 | 94 | ||
@@ -168,21 +150,22 @@ char * LJ_FASTCALL lj_strfmt_wuleb128(char *p, uint32_t v) | |||
168 | return p; | 150 | return p; |
169 | } | 151 | } |
170 | 152 | ||
171 | /* Return string or write number to buffer and return pointer to start. */ | 153 | /* Return string or write number to tmp buffer and return pointer to start. */ |
172 | const char *lj_strfmt_wstrnum(char *buf, cTValue *o, MSize *lenp) | 154 | const char *lj_strfmt_wstrnum(lua_State *L, cTValue *o, MSize *lenp) |
173 | { | 155 | { |
156 | SBuf *sb; | ||
174 | if (tvisstr(o)) { | 157 | if (tvisstr(o)) { |
175 | *lenp = strV(o)->len; | 158 | *lenp = strV(o)->len; |
176 | return strVdata(o); | 159 | return strVdata(o); |
177 | } else if (tvisint(o)) { | 160 | } else if (tvisint(o)) { |
178 | *lenp = (MSize)(lj_strfmt_wint(buf, intV(o)) - buf); | 161 | sb = lj_strfmt_putint(lj_buf_tmp_(L), intV(o)); |
179 | return buf; | ||
180 | } else if (tvisnum(o)) { | 162 | } else if (tvisnum(o)) { |
181 | *lenp = (MSize)(lj_strfmt_wnum(buf, o) - buf); | 163 | sb = lj_strfmt_putfnum(lj_buf_tmp_(L), STRFMT_G14, o->n); |
182 | return buf; | ||
183 | } else { | 164 | } else { |
184 | return NULL; | 165 | return NULL; |
185 | } | 166 | } |
167 | *lenp = sbuflen(sb); | ||
168 | return sbufB(sb); | ||
186 | } | 169 | } |
187 | 170 | ||
188 | /* -- Unformatted conversions to buffer ----------------------------------- */ | 171 | /* -- Unformatted conversions to buffer ----------------------------------- */ |
@@ -198,8 +181,7 @@ SBuf * LJ_FASTCALL lj_strfmt_putint(SBuf *sb, int32_t k) | |||
198 | /* Add number to buffer. */ | 181 | /* Add number to buffer. */ |
199 | SBuf * LJ_FASTCALL lj_strfmt_putnum(SBuf *sb, cTValue *o) | 182 | SBuf * LJ_FASTCALL lj_strfmt_putnum(SBuf *sb, cTValue *o) |
200 | { | 183 | { |
201 | setsbufP(sb, lj_strfmt_wnum(lj_buf_more(sb, STRFMT_MAXBUF_NUM), o)); | 184 | return lj_strfmt_putfnum(sb, STRFMT_G14, o->n); |
202 | return sb; | ||
203 | } | 185 | } |
204 | #endif | 186 | #endif |
205 | 187 | ||
@@ -360,63 +342,6 @@ SBuf *lj_strfmt_putfnum_uint(SBuf *sb, SFormat sf, lua_Number n) | |||
360 | return lj_strfmt_putfxint(sb, sf, (uint64_t)k); | 342 | return lj_strfmt_putfxint(sb, sf, (uint64_t)k); |
361 | } | 343 | } |
362 | 344 | ||
363 | /* Max. sprintf buffer size needed. At least #string.format("%.99f", -1e308). */ | ||
364 | #define STRFMT_FMTNUMBUF 512 | ||
365 | |||
366 | /* Add formatted floating-point number to buffer. */ | ||
367 | SBuf *lj_strfmt_putfnum(SBuf *sb, SFormat sf, lua_Number n) | ||
368 | { | ||
369 | TValue tv; | ||
370 | tv.n = n; | ||
371 | if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) { | ||
372 | /* Canonicalize output of non-finite values. */ | ||
373 | MSize width = STRFMT_WIDTH(sf), len = 3; | ||
374 | int prefix = 0, ch = (sf & STRFMT_F_UPPER) ? 0x202020 : 0; | ||
375 | char *p; | ||
376 | if (((tv.u32.hi & 0x000fffff) | tv.u32.lo) != 0) { | ||
377 | ch ^= ('n' << 16) | ('a' << 8) | 'n'; | ||
378 | if ((sf & STRFMT_F_SPACE)) prefix = ' '; | ||
379 | } else { | ||
380 | ch ^= ('i' << 16) | ('n' << 8) | 'f'; | ||
381 | if ((tv.u32.hi & 0x80000000)) prefix = '-'; | ||
382 | else if ((sf & STRFMT_F_PLUS)) prefix = '+'; | ||
383 | else if ((sf & STRFMT_F_SPACE)) prefix = ' '; | ||
384 | } | ||
385 | if (prefix) len = 4; | ||
386 | p = lj_buf_more(sb, width > len ? width : len); | ||
387 | if (!(sf & STRFMT_F_LEFT)) while (width-- > len) *p++ = ' '; | ||
388 | if (prefix) *p++ = prefix; | ||
389 | *p++ = (char)(ch >> 16); *p++ = (char)(ch >> 8); *p++ = (char)ch; | ||
390 | if ((sf & STRFMT_F_LEFT)) while (width-- > len) *p++ = ' '; | ||
391 | setsbufP(sb, p); | ||
392 | } else { /* Delegate to sprintf() for now. */ | ||
393 | uint8_t width = (uint8_t)STRFMT_WIDTH(sf), prec = (uint8_t)STRFMT_PREC(sf); | ||
394 | char fmt[1+5+2+3+1+1], *p = fmt; | ||
395 | *p++ = '%'; | ||
396 | if ((sf & STRFMT_F_LEFT)) *p++ = '-'; | ||
397 | if ((sf & STRFMT_F_PLUS)) *p++ = '+'; | ||
398 | if ((sf & STRFMT_F_ZERO)) *p++ = '0'; | ||
399 | if ((sf & STRFMT_F_SPACE)) *p++ = ' '; | ||
400 | if ((sf & STRFMT_F_ALT)) *p++ = '#'; | ||
401 | if (width) { | ||
402 | uint8_t x = width / 10, y = width % 10; | ||
403 | if (x) *p++ = '0' + x; | ||
404 | *p++ = '0' + y; | ||
405 | } | ||
406 | if (prec != 255) { | ||
407 | uint8_t x = prec / 10, y = prec % 10; | ||
408 | *p++ = '.'; | ||
409 | if (x) *p++ = '0' + x; | ||
410 | *p++ = '0' + y; | ||
411 | } | ||
412 | *p++ = (0x67666561 >> (STRFMT_FP(sf)<<3)) ^ ((sf & STRFMT_F_UPPER)?0x20:0); | ||
413 | *p = '\0'; | ||
414 | p = lj_buf_more(sb, STRFMT_FMTNUMBUF); | ||
415 | setsbufP(sb, p + sprintf(p, fmt, n)); | ||
416 | } | ||
417 | return sb; | ||
418 | } | ||
419 | |||
420 | /* -- Conversions to strings ---------------------------------------------- */ | 345 | /* -- Conversions to strings ---------------------------------------------- */ |
421 | 346 | ||
422 | /* Convert integer to string. */ | 347 | /* Convert integer to string. */ |
@@ -427,14 +352,6 @@ GCstr * LJ_FASTCALL lj_strfmt_int(lua_State *L, int32_t k) | |||
427 | return lj_str_new(L, buf, len); | 352 | return lj_str_new(L, buf, len); |
428 | } | 353 | } |
429 | 354 | ||
430 | /* Convert number to string. */ | ||
431 | GCstr * LJ_FASTCALL lj_strfmt_num(lua_State *L, cTValue *o) | ||
432 | { | ||
433 | char buf[STRFMT_MAXBUF_NUM]; | ||
434 | MSize len = (MSize)(lj_strfmt_wnum(buf, o) - buf); | ||
435 | return lj_str_new(L, buf, len); | ||
436 | } | ||
437 | |||
438 | /* Convert integer or number to string. */ | 355 | /* Convert integer or number to string. */ |
439 | GCstr * LJ_FASTCALL lj_strfmt_number(lua_State *L, cTValue *o) | 356 | GCstr * LJ_FASTCALL lj_strfmt_number(lua_State *L, cTValue *o) |
440 | { | 357 | { |
@@ -510,12 +427,9 @@ const char *lj_strfmt_pushvf(lua_State *L, const char *fmt, va_list argp) | |||
510 | case STRFMT_UINT: | 427 | case STRFMT_UINT: |
511 | lj_strfmt_putfxint(sb, sf, va_arg(argp, uint32_t)); | 428 | lj_strfmt_putfxint(sb, sf, va_arg(argp, uint32_t)); |
512 | break; | 429 | break; |
513 | case STRFMT_NUM: { | 430 | case STRFMT_NUM: |
514 | TValue tv; | 431 | lj_strfmt_putfnum(sb, STRFMT_G14, va_arg(argp, lua_Number)); |
515 | tv.n = va_arg(argp, lua_Number); | ||
516 | setsbufP(sb, lj_strfmt_wnum(lj_buf_more(sb, STRFMT_MAXBUF_NUM), &tv)); | ||
517 | break; | 432 | break; |
518 | } | ||
519 | case STRFMT_STR: { | 433 | case STRFMT_STR: { |
520 | const char *s = va_arg(argp, char *); | 434 | const char *s = va_arg(argp, char *); |
521 | if (s == NULL) s = "(null)"; | 435 | if (s == NULL) s = "(null)"; |