aboutsummaryrefslogtreecommitdiff
path: root/src/lib_string.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/lib_string.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/lib_string.c')
-rw-r--r--src/lib_string.c85
1 files changed, 5 insertions, 80 deletions
diff --git a/src/lib_string.c b/src/lib_string.c
index 4a3ff3729..75d855d6b 100644
--- a/src/lib_string.c
+++ b/src/lib_string.c
@@ -640,89 +640,14 @@ LJLIB_CF(string_gsub)
640 640
641/* ------------------------------------------------------------------------ */ 641/* ------------------------------------------------------------------------ */
642 642
643/* Emulate tostring() inline. */
644static GCstr *string_fmt_tostring(lua_State *L, int arg, int retry)
645{
646 TValue *o = L->base+arg-1;
647 cTValue *mo;
648 lj_assertL(o < L->top, "bad usage"); /* Caller already checks for existence. */
649 if (LJ_LIKELY(tvisstr(o)))
650 return strV(o);
651 if (retry != 2 && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
652 copyTV(L, L->top++, mo);
653 copyTV(L, L->top++, o);
654 lua_call(L, 1, 1);
655 copyTV(L, L->base+arg-1, --L->top);
656 return NULL; /* Buffer may be overwritten, retry. */
657 }
658 return lj_strfmt_obj(L, o);
659}
660
661LJLIB_CF(string_format) LJLIB_REC(.) 643LJLIB_CF(string_format) LJLIB_REC(.)
662{ 644{
663 int arg, top = (int)(L->top - L->base);
664 GCstr *fmt;
665 SBuf *sb;
666 FormatState fs;
667 SFormat sf;
668 int retry = 0; 645 int retry = 0;
669again: 646 SBuf *sb;
670 arg = 1; 647 do {
671 sb = lj_buf_tmp_(L); 648 sb = lj_buf_tmp_(L);
672 fmt = lj_lib_checkstr(L, arg); 649 retry = lj_strfmt_putarg(L, sb, 1, -retry);
673 lj_strfmt_init(&fs, strdata(fmt), fmt->len); 650 } while (retry > 0);
674 while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) {
675 if (sf == STRFMT_LIT) {
676 lj_buf_putmem(sb, fs.str, fs.len);
677 } else if (sf == STRFMT_ERR) {
678 lj_err_callerv(L, LJ_ERR_STRFMT, strdata(lj_str_new(L, fs.str, fs.len)));
679 } else {
680 if (++arg > top)
681 luaL_argerror(L, arg, lj_obj_typename[0]);
682 switch (STRFMT_TYPE(sf)) {
683 case STRFMT_INT:
684 if (tvisint(L->base+arg-1)) {
685 int32_t k = intV(L->base+arg-1);
686 if (sf == STRFMT_INT)
687 lj_strfmt_putint(sb, k); /* Shortcut for plain %d. */
688 else
689 lj_strfmt_putfxint(sb, sf, k);
690 } else {
691 lj_strfmt_putfnum_int(sb, sf, lj_lib_checknum(L, arg));
692 }
693 break;
694 case STRFMT_UINT:
695 if (tvisint(L->base+arg-1))
696 lj_strfmt_putfxint(sb, sf, intV(L->base+arg-1));
697 else
698 lj_strfmt_putfnum_uint(sb, sf, lj_lib_checknum(L, arg));
699 break;
700 case STRFMT_NUM:
701 lj_strfmt_putfnum(sb, sf, lj_lib_checknum(L, arg));
702 break;
703 case STRFMT_STR: {
704 GCstr *str = string_fmt_tostring(L, arg, retry);
705 if (str == NULL)
706 retry = 1;
707 else if ((sf & STRFMT_T_QUOTED))
708 lj_strfmt_putquoted(sb, str); /* No formatting. */
709 else
710 lj_strfmt_putfstr(sb, sf, str);
711 break;
712 }
713 case STRFMT_CHAR:
714 lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg));
715 break;
716 case STRFMT_PTR: /* No formatting. */
717 lj_strfmt_putptr(sb, lj_obj_ptr(G(L), L->base+arg-1));
718 break;
719 default:
720 lj_assertL(0, "bad string format type");
721 break;
722 }
723 }
724 }
725 if (retry++ == 1) goto again;
726 setstrV(L, L->top-1, lj_buf_str(L, sb)); 651 setstrV(L, L->top-1, lj_buf_str(L, sb));
727 lj_gc_check(L); 652 lj_gc_check(L);
728 return 1; 653 return 1;