aboutsummaryrefslogtreecommitdiff
path: root/src/lj_strfmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_strfmt.c')
-rw-r--r--src/lj_strfmt.c221
1 files changed, 185 insertions, 36 deletions
diff --git a/src/lj_strfmt.c b/src/lj_strfmt.c
index e8fe2538..b44350e7 100644
--- a/src/lj_strfmt.c
+++ b/src/lj_strfmt.c
@@ -10,6 +10,7 @@
10 10
11#include "lj_obj.h" 11#include "lj_obj.h"
12#include "lj_buf.h" 12#include "lj_buf.h"
13#include "lj_str.h"
13#include "lj_state.h" 14#include "lj_state.h"
14#include "lj_char.h" 15#include "lj_char.h"
15#include "lj_strfmt.h" 16#include "lj_strfmt.h"
@@ -86,35 +87,124 @@ retlit:
86 return fs->len ? STRFMT_LIT : STRFMT_EOF; 87 return fs->len ? STRFMT_LIT : STRFMT_EOF;
87} 88}
88 89
89/* -- Formatted conversions to buffer ------------------------------------- */ 90/* -- Raw conversions ----------------------------------------------------- */
90 91
91/* Add formatted char to buffer. */ 92/* Write number to bufer. */
92SBuf *lj_strfmt_putchar(SBuf *sb, SFormat sf, int32_t c) 93char * LJ_FASTCALL lj_strfmt_wnum(char *p, cTValue *o)
93{ 94{
94 MSize width = STRFMT_WIDTH(sf); 95 if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */
95 char *p = lj_buf_more(sb, width > 1 ? width : 1); 96#if __BIONIC__
96 if ((sf & STRFMT_F_LEFT)) *p++ = (char)c; 97 if (tvismzero(o)) { *p++ = '-'; *p++ = '0'; return p; }
97 while (width-- > 1) *p++ = ' '; 98#endif
98 if (!(sf & STRFMT_F_LEFT)) *p++ = (char)c; 99 return p + lua_number2str(p, o->n);
99 setsbufP(sb, p); 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) \
111 { uint32_t d = (x*(((1<<sh)+sc-1)/sc))>>sh; x -= d*sc; *p++ = (char)('0'+d); }
112
113/* Write integer to buffer. */
114char * LJ_FASTCALL lj_strfmt_wint(char *p, int32_t k)
115{
116 uint32_t u = (uint32_t)k;
117 if (k < 0) { u = (uint32_t)-k; *p++ = '-'; }
118 if (u < 10000) {
119 if (u < 10) goto dig1; if (u < 100) goto dig2; if (u < 1000) goto dig3;
120 } else {
121 uint32_t v = u / 10000; u -= v * 10000;
122 if (v < 10000) {
123 if (v < 10) goto dig5; if (v < 100) goto dig6; if (v < 1000) goto dig7;
124 } else {
125 uint32_t w = v / 10000; v -= w * 10000;
126 if (w >= 10) WINT_R(w, 10, 10)
127 *p++ = (char)('0'+w);
128 }
129 WINT_R(v, 23, 1000)
130 dig7: WINT_R(v, 12, 100)
131 dig6: WINT_R(v, 10, 10)
132 dig5: *p++ = (char)('0'+v);
133 }
134 WINT_R(u, 23, 1000)
135 dig3: WINT_R(u, 12, 100)
136 dig2: WINT_R(u, 10, 10)
137 dig1: *p++ = (char)('0'+u);
138 return p;
139}
140#undef WINT_R
141
142/* Write pointer to buffer. */
143char * LJ_FASTCALL lj_strfmt_wptr(char *p, const void *v)
144{
145 ptrdiff_t x = (ptrdiff_t)v;
146 MSize i, n = STRFMT_MAXBUF_PTR;
147 if (x == 0) {
148 *p++ = 'N'; *p++ = 'U'; *p++ = 'L'; *p++ = 'L';
149 return p;
150 }
151#if LJ_64
152 /* Shorten output for 64 bit pointers. */
153 n = 2+2*4+((x >> 32) ? 2+2*(lj_fls((uint32_t)(x >> 32))>>3) : 0);
154#endif
155 p[0] = '0';
156 p[1] = 'x';
157 for (i = n-1; i >= 2; i--, x >>= 4)
158 p[i] = "0123456789abcdef"[(x & 15)];
159 return p+n;
160}
161
162/* Write ULEB128 to buffer. */
163char * LJ_FASTCALL lj_strfmt_wuleb128(char *p, uint32_t v)
164{
165 for (; v >= 0x80; v >>= 7)
166 *p++ = (char)((v & 0x7f) | 0x80);
167 *p++ = (char)v;
168 return p;
169}
170
171/* Return string or write number to buffer and return pointer to start. */
172const char *lj_strfmt_wstrnum(char *buf, cTValue *o, MSize *lenp)
173{
174 if (tvisstr(o)) {
175 *lenp = strV(o)->len;
176 return strVdata(o);
177 } else if (tvisint(o)) {
178 *lenp = (MSize)(lj_strfmt_wint(buf, intV(o)) - buf);
179 return buf;
180 } else if (tvisnum(o)) {
181 *lenp = (MSize)(lj_strfmt_wnum(buf, o) - buf);
182 return buf;
183 } else {
184 return NULL;
185 }
186}
187
188/* -- Unformatted conversions to buffer ----------------------------------- */
189
190/* Add integer to buffer. */
191SBuf * LJ_FASTCALL lj_strfmt_putint(SBuf *sb, int32_t k)
192{
193 setsbufP(sb, lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT), k));
100 return sb; 194 return sb;
101} 195}
102 196
103/* Add formatted string to buffer. */ 197#if LJ_HASJIT
104SBuf *lj_strfmt_putstr(SBuf *sb, SFormat sf, GCstr *str) 198/* Add number to buffer. */
199SBuf * LJ_FASTCALL lj_strfmt_putnum(SBuf *sb, cTValue *o)
105{ 200{
106 MSize len = str->len <= STRFMT_PREC(sf) ? str->len : STRFMT_PREC(sf); 201 setsbufP(sb, lj_strfmt_wnum(lj_buf_more(sb, STRFMT_MAXBUF_NUM), o));
107 MSize width = STRFMT_WIDTH(sf);
108 char *p = lj_buf_more(sb, width > len ? width : len);
109 if ((sf & STRFMT_F_LEFT)) p = lj_buf_wmem(p, strdata(str), len);
110 while (width-- > len) *p++ = ' ';
111 if (!(sf & STRFMT_F_LEFT)) p = lj_buf_wmem(p, strdata(str), len);
112 setsbufP(sb, p);
113 return sb; 202 return sb;
114} 203}
204#endif
115 205
116/* Add quoted string to buffer (no formatting). */ 206/* Add quoted string to buffer. */
117SBuf *lj_strfmt_putquoted(SBuf *sb, GCstr *str) 207SBuf * LJ_FASTCALL lj_strfmt_putquoted(SBuf *sb, GCstr *str)
118{ 208{
119 const char *s = strdata(str); 209 const char *s = strdata(str);
120 MSize len = str->len; 210 MSize len = str->len;
@@ -143,10 +233,37 @@ SBuf *lj_strfmt_putquoted(SBuf *sb, GCstr *str)
143 return sb; 233 return sb;
144} 234}
145 235
236/* -- Formatted conversions to buffer ------------------------------------- */
237
238/* Add formatted char to buffer. */
239SBuf *lj_strfmt_putfchar(SBuf *sb, SFormat sf, int32_t c)
240{
241 MSize width = STRFMT_WIDTH(sf);
242 char *p = lj_buf_more(sb, width > 1 ? width : 1);
243 if ((sf & STRFMT_F_LEFT)) *p++ = (char)c;
244 while (width-- > 1) *p++ = ' ';
245 if (!(sf & STRFMT_F_LEFT)) *p++ = (char)c;
246 setsbufP(sb, p);
247 return sb;
248}
249
250/* Add formatted string to buffer. */
251SBuf *lj_strfmt_putfstr(SBuf *sb, SFormat sf, GCstr *str)
252{
253 MSize len = str->len <= STRFMT_PREC(sf) ? str->len : STRFMT_PREC(sf);
254 MSize width = STRFMT_WIDTH(sf);
255 char *p = lj_buf_more(sb, width > len ? width : len);
256 if ((sf & STRFMT_F_LEFT)) p = lj_buf_wmem(p, strdata(str), len);
257 while (width-- > len) *p++ = ' ';
258 if (!(sf & STRFMT_F_LEFT)) p = lj_buf_wmem(p, strdata(str), len);
259 setsbufP(sb, p);
260 return sb;
261}
262
146/* Add formatted signed/unsigned integer to buffer. */ 263/* Add formatted signed/unsigned integer to buffer. */
147SBuf *lj_strfmt_putxint(SBuf *sb, SFormat sf, uint64_t k) 264SBuf *lj_strfmt_putfxint(SBuf *sb, SFormat sf, uint64_t k)
148{ 265{
149 char buf[1+22], *q = buf + sizeof(buf), *p; 266 char buf[STRFMT_MAXBUF_XINT], *q = buf + sizeof(buf), *p;
150#ifdef LUA_USE_ASSERT 267#ifdef LUA_USE_ASSERT
151 char *ps; 268 char *ps;
152#endif 269#endif
@@ -217,31 +334,31 @@ SBuf *lj_strfmt_putxint(SBuf *sb, SFormat sf, uint64_t k)
217} 334}
218 335
219/* Add number formatted as signed integer to buffer. */ 336/* Add number formatted as signed integer to buffer. */
220SBuf *lj_strfmt_putnum_int(SBuf *sb, SFormat sf, lua_Number n) 337SBuf *lj_strfmt_putfnum_int(SBuf *sb, SFormat sf, lua_Number n)
221{ 338{
222 int64_t k = (int64_t)n; 339 int64_t k = (int64_t)n;
223 if (checki32(k) && sf == STRFMT_INT) 340 if (checki32(k) && sf == STRFMT_INT)
224 return lj_buf_putint(sb, k); /* Shortcut for plain %d. */ 341 return lj_strfmt_putint(sb, k); /* Shortcut for plain %d. */
225 else 342 else
226 return lj_strfmt_putxint(sb, sf, (uint64_t)k); 343 return lj_strfmt_putfxint(sb, sf, (uint64_t)k);
227} 344}
228 345
229/* Add number formatted as unsigned integer to buffer. */ 346/* Add number formatted as unsigned integer to buffer. */
230SBuf *lj_strfmt_putnum_uint(SBuf *sb, SFormat sf, lua_Number n) 347SBuf *lj_strfmt_putfnum_uint(SBuf *sb, SFormat sf, lua_Number n)
231{ 348{
232 int64_t k; 349 int64_t k;
233 if (n >= 9223372036854775808.0) 350 if (n >= 9223372036854775808.0)
234 k = (int64_t)(n - 18446744073709551616.0); 351 k = (int64_t)(n - 18446744073709551616.0);
235 else 352 else
236 k = (int64_t)n; 353 k = (int64_t)n;
237 return lj_strfmt_putxint(sb, sf, (uint64_t)k); 354 return lj_strfmt_putfxint(sb, sf, (uint64_t)k);
238} 355}
239 356
240/* Max. sprintf buffer size needed. At least #string.format("%.99f", -1e308). */ 357/* Max. sprintf buffer size needed. At least #string.format("%.99f", -1e308). */
241#define STRFMT_FMTNUMBUF 512 358#define STRFMT_FMTNUMBUF 512
242 359
243/* Add formatted floating-point number to buffer. */ 360/* Add formatted floating-point number to buffer. */
244SBuf *lj_strfmt_putnum(SBuf *sb, SFormat sf, lua_Number n) 361SBuf *lj_strfmt_putfnum(SBuf *sb, SFormat sf, lua_Number n)
245{ 362{
246 TValue tv; 363 TValue tv;
247 tv.n = n; 364 tv.n = n;
@@ -296,13 +413,45 @@ SBuf *lj_strfmt_putnum(SBuf *sb, SFormat sf, lua_Number n)
296 413
297/* -- Conversions to strings ---------------------------------------------- */ 414/* -- Conversions to strings ---------------------------------------------- */
298 415
416/* Convert integer to string. */
417GCstr * LJ_FASTCALL lj_strfmt_int(lua_State *L, int32_t k)
418{
419 char buf[STRFMT_MAXBUF_INT];
420 MSize len = (MSize)(lj_strfmt_wint(buf, k) - buf);
421 return lj_str_new(L, buf, len);
422}
423
424/* Convert number to string. */
425GCstr * LJ_FASTCALL lj_strfmt_num(lua_State *L, cTValue *o)
426{
427 char buf[STRFMT_MAXBUF_NUM];
428 MSize len = (MSize)(lj_strfmt_wnum(buf, o) - buf);
429 return lj_str_new(L, buf, len);
430}
431
432/* Convert integer or number to string. */
433GCstr * LJ_FASTCALL lj_strfmt_number(lua_State *L, cTValue *o)
434{
435 return tvisint(o) ? lj_strfmt_int(L, intV(o)) : lj_strfmt_num(L, o);
436}
437
438#if LJ_HASJIT
439/* Convert char value to string. */
440GCstr * LJ_FASTCALL lj_strfmt_char(lua_State *L, int c)
441{
442 char buf[1];
443 buf[0] = c;
444 return lj_str_new(L, buf, 1);
445}
446#endif
447
299/* Raw conversion of object to string. */ 448/* Raw conversion of object to string. */
300GCstr *lj_strfmt_obj(lua_State *L, cTValue *o) 449GCstr *lj_strfmt_obj(lua_State *L, cTValue *o)
301{ 450{
302 if (tvisstr(o)) { 451 if (tvisstr(o)) {
303 return strV(o); 452 return strV(o);
304 } else if (tvisnumber(o)) { 453 } else if (tvisnumber(o)) {
305 return lj_str_fromnumber(L, o); 454 return lj_strfmt_number(L, o);
306 } else if (tvisnil(o)) { 455 } else if (tvisnil(o)) {
307 return lj_str_newlit(L, "nil"); 456 return lj_str_newlit(L, "nil");
308 } else if (tvisfalse(o)) { 457 } else if (tvisfalse(o)) {
@@ -315,9 +464,9 @@ GCstr *lj_strfmt_obj(lua_State *L, cTValue *o)
315 *p++ = ':'; *p++ = ' '; 464 *p++ = ':'; *p++ = ' ';
316 if (tvisfunc(o) && isffunc(funcV(o))) { 465 if (tvisfunc(o) && isffunc(funcV(o))) {
317 p = lj_buf_wmem(p, "builtin#", 8); 466 p = lj_buf_wmem(p, "builtin#", 8);
318 p = lj_str_bufint(p, funcV(o)->c.ffid); 467 p = lj_strfmt_wint(p, funcV(o)->c.ffid);
319 } else { 468 } else {
320 p = lj_str_bufptr(p, lj_obj_ptr(o)); 469 p = lj_strfmt_wptr(p, lj_obj_ptr(o));
321 } 470 }
322 return lj_str_new(L, buf, (size_t)(p - buf)); 471 return lj_str_new(L, buf, (size_t)(p - buf));
323 } 472 }
@@ -350,15 +499,15 @@ const char *lj_strfmt_pushvf(lua_State *L, const char *fmt, va_list argp)
350 lj_buf_putmem(sb, fs.str, fs.len); 499 lj_buf_putmem(sb, fs.str, fs.len);
351 break; 500 break;
352 case STRFMT_INT: 501 case STRFMT_INT:
353 lj_strfmt_putxint(sb, sf, va_arg(argp, int32_t)); 502 lj_strfmt_putfxint(sb, sf, va_arg(argp, int32_t));
354 break; 503 break;
355 case STRFMT_UINT: 504 case STRFMT_UINT:
356 lj_strfmt_putxint(sb, sf, va_arg(argp, uint32_t)); 505 lj_strfmt_putfxint(sb, sf, va_arg(argp, uint32_t));
357 break; 506 break;
358 case STRFMT_NUM: { 507 case STRFMT_NUM: {
359 TValue tv; 508 TValue tv;
360 tv.n = va_arg(argp, lua_Number); 509 tv.n = va_arg(argp, lua_Number);
361 setsbufP(sb, lj_str_bufnum(lj_buf_more(sb, LJ_STR_NUMBUF), &tv)); 510 setsbufP(sb, lj_strfmt_wnum(lj_buf_more(sb, STRFMT_MAXBUF_NUM), &tv));
362 break; 511 break;
363 } 512 }
364 case STRFMT_STR: { 513 case STRFMT_STR: {
@@ -371,8 +520,8 @@ const char *lj_strfmt_pushvf(lua_State *L, const char *fmt, va_list argp)
371 lj_buf_putb(sb, va_arg(argp, int)); 520 lj_buf_putb(sb, va_arg(argp, int));
372 break; 521 break;
373 case STRFMT_PTR: 522 case STRFMT_PTR:
374 setsbufP(sb, lj_str_bufptr(lj_buf_more(sb, LJ_STR_PTRBUF), 523 setsbufP(sb, lj_strfmt_wptr(lj_buf_more(sb, STRFMT_MAXBUF_PTR),
375 va_arg(argp, void *))); 524 va_arg(argp, void *)));
376 break; 525 break;
377 case STRFMT_ERR: 526 case STRFMT_ERR:
378 default: 527 default: