diff --git a/src/Makefile.dep b/src/Makefile.dep index 6747e599..074d0908 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -58,7 +58,7 @@ lj_bcwrite.o: lj_bcwrite.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_gc.h lj_buf.h lj_str.h lj_bc.h lj_ctype.h lj_dispatch.h lj_jit.h \ lj_ir.h lj_bcdump.h lj_lex.h lj_err.h lj_errmsg.h lj_vm.h lj_buf.o: lj_buf.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ - lj_err.h lj_errmsg.h lj_buf.h lj_str.h + lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_carith.o: lj_carith.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_meta.h lj_ir.h lj_ctype.h \ lj_cconv.h lj_cdata.h lj_carith.h lj_strscan.h diff --git a/src/lib_table.c b/src/lib_table.c index 5619f9ad..011b9fdf 100644 --- a/src/lib_table.c +++ b/src/lib_table.c @@ -133,31 +133,19 @@ LJLIB_CF(table_concat) { GCtab *t = lj_lib_checktab(L, 1); GCstr *sep = lj_lib_optstr(L, 2); - MSize seplen = sep ? sep->len : 0; int32_t i = lj_lib_optint(L, 3, 1); int32_t e = L->base+3 < L->top ? lj_lib_checkint(L, 4) : (int32_t)lj_tab_len(t); - if (i <= e) { - char buf[LJ_STR_NUMBERBUF]; - SBuf *sb = &G(L)->tmpbuf; - setsbufL(sb, L); - lj_buf_reset(sb); - for (;;) { - cTValue *o = lj_tab_getint(t, i); - MSize len; - const char *p = lj_str_buftv(buf, o, &len); - if (!p) - lj_err_callerv(L, LJ_ERR_TABCAT, lj_typename(o), i); - lj_buf_putmem(sb, p, len); - if (i++ == e) break; - if (seplen) - lj_buf_putmem(sb, strdata(sep), seplen); - } - setstrV(L, L->top-1, lj_buf_str(L, sb)); - lj_gc_check(L); - } else { - setstrV(L, L->top-1, &G(L)->strempty); + SBuf *sb = lj_buf_tmp_(L); + SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e); + if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */ + int32_t idx = (int32_t)(intptr_t)sbufP(sb); + cTValue *o = lj_tab_getint(t, idx); + lj_err_callerv(L, LJ_ERR_TABCAT, + lj_obj_itypename[o ? itypemap(o) : ~LJ_TNIL], idx); } + setstrV(L, L->top-1, lj_buf_str(L, sbx)); + lj_gc_check(L); return 1; } diff --git a/src/lj_buf.c b/src/lj_buf.c index 55a885a9..c60cc51f 100644 --- a/src/lj_buf.c +++ b/src/lj_buf.c @@ -13,6 +13,7 @@ #include "lj_err.h" #include "lj_buf.h" #include "lj_str.h" +#include "lj_tab.h" LJ_NOINLINE void LJ_FASTCALL lj_buf_grow(SBuf *sb, char *en) { @@ -168,6 +169,38 @@ SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep) return sb; } +SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e) +{ + MSize seplen = sep ? sep->len : 0; + if (i <= e) { + for (;;) { + cTValue *o = lj_tab_getint(t, i); + char *p; + if (!o) { + badtype: /* Error: bad element type. */ + setsbufP(sb, (intptr_t)i); /* Store failing index. */ + return NULL; + } else if (tvisstr(o)) { + MSize len = strV(o)->len; + p = lj_buf_wmem(lj_buf_more(sb, len + seplen), strVdata(o), len); + } else if (tvisint(o)) { + p = lj_str_bufint(lj_buf_more(sb, LJ_STR_INTBUF + seplen), intV(o)); + } else if (tvisnum(o)) { + p = lj_str_bufnum(lj_buf_more(sb, LJ_STR_NUMBUF + seplen), o); + } else { + goto badtype; + } + if (i++ == e) { + setsbufP(sb, p); + break; + } + if (seplen) p = lj_buf_wmem(p, strdata(sep), seplen); + setsbufP(sb, p); + } + } + return sb; +} + GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb) { return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb)); diff --git a/src/lj_buf.h b/src/lj_buf.h index 4d764938..6931a693 100644 --- a/src/lj_buf.h +++ b/src/lj_buf.h @@ -36,6 +36,8 @@ LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s); LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s); LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s); LJ_FUNC SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep); +LJ_FUNC SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, + int32_t i, int32_t e); LJ_FUNCA GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb); LJ_FUNC GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2); LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp);