aboutsummaryrefslogtreecommitdiff
path: root/src/lj_strfmt.c
diff options
context:
space:
mode:
authorMike Pall <mike>2021-06-01 05:14:18 +0200
committerMike Pall <mike>2021-06-01 05:14:18 +0200
commitedd5cbadc5cdc7b5b66d5340ee97c5abe5a3892a (patch)
tree053c8bb18f0b9de559a4b712062fd99e96849be7 /src/lj_strfmt.c
parent50d6883e6027c4c2f9a5e495fee6b7fff1bd73c9 (diff)
downloadluajit-edd5cbadc5cdc7b5b66d5340ee97c5abe5a3892a.tar.gz
luajit-edd5cbadc5cdc7b5b66d5340ee97c5abe5a3892a.tar.bz2
luajit-edd5cbadc5cdc7b5b66d5340ee97c5abe5a3892a.zip
String buffers, part 2c: abstract out string.format.
Sponsored by fmad.io.
Diffstat (limited to 'src/lj_strfmt.c')
-rw-r--r--src/lj_strfmt.c117
1 files changed, 109 insertions, 8 deletions
diff --git a/src/lj_strfmt.c b/src/lj_strfmt.c
index bde3ec0e..a9541d41 100644
--- a/src/lj_strfmt.c
+++ b/src/lj_strfmt.c
@@ -9,11 +9,14 @@
9#define LUA_CORE 9#define LUA_CORE
10 10
11#include "lj_obj.h" 11#include "lj_obj.h"
12#include "lj_err.h"
12#include "lj_buf.h" 13#include "lj_buf.h"
13#include "lj_str.h" 14#include "lj_str.h"
15#include "lj_meta.h"
14#include "lj_state.h" 16#include "lj_state.h"
15#include "lj_char.h" 17#include "lj_char.h"
16#include "lj_strfmt.h" 18#include "lj_strfmt.h"
19#include "lj_lib.h"
17 20
18/* -- Format parser ------------------------------------------------------- */ 21/* -- Format parser ------------------------------------------------------- */
19 22
@@ -196,10 +199,8 @@ SBuf * LJ_FASTCALL lj_strfmt_putptr(SBuf *sb, const void *v)
196} 199}
197 200
198/* Add quoted string to buffer. */ 201/* Add quoted string to buffer. */
199SBuf * LJ_FASTCALL lj_strfmt_putquoted(SBuf *sb, GCstr *str) 202static SBuf *strfmt_putquotedlen(SBuf *sb, const char *s, MSize len)
200{ 203{
201 const char *s = strdata(str);
202 MSize len = str->len;
203 lj_buf_putb(sb, '"'); 204 lj_buf_putb(sb, '"');
204 while (len--) { 205 while (len--) {
205 uint32_t c = (uint32_t)(uint8_t)*s++; 206 uint32_t c = (uint32_t)(uint8_t)*s++;
@@ -225,6 +226,13 @@ SBuf * LJ_FASTCALL lj_strfmt_putquoted(SBuf *sb, GCstr *str)
225 return sb; 226 return sb;
226} 227}
227 228
229#if LJ_HASJIT
230SBuf * LJ_FASTCALL lj_strfmt_putquoted(SBuf *sb, GCstr *str)
231{
232 return strfmt_putquotedlen(sb, strdata(str), str->len);
233}
234#endif
235
228/* -- Formatted conversions to buffer ------------------------------------- */ 236/* -- Formatted conversions to buffer ------------------------------------- */
229 237
230/* Add formatted char to buffer. */ 238/* Add formatted char to buffer. */
@@ -240,18 +248,26 @@ SBuf *lj_strfmt_putfchar(SBuf *sb, SFormat sf, int32_t c)
240} 248}
241 249
242/* Add formatted string to buffer. */ 250/* Add formatted string to buffer. */
243SBuf *lj_strfmt_putfstr(SBuf *sb, SFormat sf, GCstr *str) 251static SBuf *strfmt_putfstrlen(SBuf *sb, SFormat sf, const char *s, MSize len)
244{ 252{
245 MSize len = str->len <= STRFMT_PREC(sf) ? str->len : STRFMT_PREC(sf);
246 MSize width = STRFMT_WIDTH(sf); 253 MSize width = STRFMT_WIDTH(sf);
247 char *w = lj_buf_more(sb, width > len ? width : len); 254 char *w;
248 if ((sf & STRFMT_F_LEFT)) w = lj_buf_wmem(w, strdata(str), len); 255 if (len > STRFMT_PREC(sf)) len = STRFMT_PREC(sf);
256 w = lj_buf_more(sb, width > len ? width : len);
257 if ((sf & STRFMT_F_LEFT)) w = lj_buf_wmem(w, s, len);
249 while (width-- > len) *w++ = ' '; 258 while (width-- > len) *w++ = ' ';
250 if (!(sf & STRFMT_F_LEFT)) w = lj_buf_wmem(w, strdata(str), len); 259 if (!(sf & STRFMT_F_LEFT)) w = lj_buf_wmem(w, s, len);
251 sb->w = w; 260 sb->w = w;
252 return sb; 261 return sb;
253} 262}
254 263
264#if LJ_HASJIT
265SBuf *lj_strfmt_putfstr(SBuf *sb, SFormat sf, GCstr *str)
266{
267 return strfmt_putfstrlen(sb, sf, strdata(str), str->len);
268}
269#endif
270
255/* Add formatted signed/unsigned integer to buffer. */ 271/* Add formatted signed/unsigned integer to buffer. */
256SBuf *lj_strfmt_putfxint(SBuf *sb, SFormat sf, uint64_t k) 272SBuf *lj_strfmt_putfxint(SBuf *sb, SFormat sf, uint64_t k)
257{ 273{
@@ -346,6 +362,91 @@ SBuf *lj_strfmt_putfnum_uint(SBuf *sb, SFormat sf, lua_Number n)
346 return lj_strfmt_putfxint(sb, sf, (uint64_t)k); 362 return lj_strfmt_putfxint(sb, sf, (uint64_t)k);
347} 363}
348 364
365/* Format stack arguments to buffer. */
366int lj_strfmt_putarg(lua_State *L, SBuf *sb, int arg, int retry)
367{
368 int narg = (int)(L->top - L->base);
369 GCstr *fmt = lj_lib_checkstr(L, arg);
370 FormatState fs;
371 SFormat sf;
372 lj_strfmt_init(&fs, strdata(fmt), fmt->len);
373 while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) {
374 if (sf == STRFMT_LIT) {
375 lj_buf_putmem(sb, fs.str, fs.len);
376 } else if (sf == STRFMT_ERR) {
377 lj_err_callerv(L, LJ_ERR_STRFMT,
378 strdata(lj_str_new(L, fs.str, fs.len)));
379 } else {
380 TValue *o = &L->base[arg++];
381 if (arg > narg)
382 lj_err_arg(L, arg, LJ_ERR_NOVAL);
383 switch (STRFMT_TYPE(sf)) {
384 case STRFMT_INT:
385 if (tvisint(o)) {
386 int32_t k = intV(o);
387 if (sf == STRFMT_INT)
388 lj_strfmt_putint(sb, k); /* Shortcut for plain %d. */
389 else
390 lj_strfmt_putfxint(sb, sf, k);
391 } else {
392 lj_strfmt_putfnum_int(sb, sf, lj_lib_checknum(L, arg));
393 }
394 break;
395 case STRFMT_UINT:
396 if (tvisint(o))
397 lj_strfmt_putfxint(sb, sf, intV(o));
398 else
399 lj_strfmt_putfnum_uint(sb, sf, lj_lib_checknum(L, arg));
400 break;
401 case STRFMT_NUM:
402 lj_strfmt_putfnum(sb, sf, lj_lib_checknum(L, arg));
403 break;
404 case STRFMT_STR: {
405 MSize len;
406 const char *s;
407 cTValue *mo;
408 if (LJ_UNLIKELY(!tvisstr(o)) && retry >= 0 &&
409 !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
410 /* Call __tostring metamethod once. */
411 copyTV(L, L->top++, mo);
412 copyTV(L, L->top++, o);
413 lua_call(L, 1, 1);
414 o = &L->base[arg-1]; /* Stack may have been reallocated. */
415 copyTV(L, o, --L->top); /* Replace inline for retry. */
416 if (retry < 2) { /* Global buffer may have been overwritten. */
417 retry = 1;
418 break;
419 }
420 }
421 if (LJ_LIKELY(tvisstr(o))) {
422 len = strV(o)->len;
423 s = strVdata(o);
424 } else {
425 GCstr *str = lj_strfmt_obj(L, o);
426 len = str->len;
427 s = strdata(str);
428 }
429 if ((sf & STRFMT_T_QUOTED))
430 strfmt_putquotedlen(sb, s, len); /* No formatting. */
431 else
432 strfmt_putfstrlen(sb, sf, s, len);
433 break;
434 }
435 case STRFMT_CHAR:
436 lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg));
437 break;
438 case STRFMT_PTR: /* No formatting. */
439 lj_strfmt_putptr(sb, lj_obj_ptr(G(L), o));
440 break;
441 default:
442 lj_assertL(0, "bad string format type");
443 break;
444 }
445 }
446 }
447 return retry;
448}
449
349/* -- Conversions to strings ---------------------------------------------- */ 450/* -- Conversions to strings ---------------------------------------------- */
350 451
351/* Convert integer to string. */ 452/* Convert integer to string. */