diff options
Diffstat (limited to 'src/lib_table.c')
| -rw-r--r-- | src/lib_table.c | 187 |
1 files changed, 107 insertions, 80 deletions
diff --git a/src/lib_table.c b/src/lib_table.c index 93f07ff0..f6f82d31 100644 --- a/src/lib_table.c +++ b/src/lib_table.c | |||
| @@ -16,57 +16,43 @@ | |||
| 16 | #include "lj_obj.h" | 16 | #include "lj_obj.h" |
| 17 | #include "lj_gc.h" | 17 | #include "lj_gc.h" |
| 18 | #include "lj_err.h" | 18 | #include "lj_err.h" |
| 19 | #include "lj_buf.h" | ||
| 19 | #include "lj_tab.h" | 20 | #include "lj_tab.h" |
| 21 | #include "lj_ff.h" | ||
| 20 | #include "lj_lib.h" | 22 | #include "lj_lib.h" |
| 21 | 23 | ||
| 22 | /* ------------------------------------------------------------------------ */ | 24 | /* ------------------------------------------------------------------------ */ |
| 23 | 25 | ||
| 24 | #define LJLIB_MODULE_table | 26 | #define LJLIB_MODULE_table |
| 25 | 27 | ||
| 26 | LJLIB_CF(table_foreachi) | 28 | LJLIB_LUA(table_foreachi) /* |
| 27 | { | 29 | function(t, f) |
| 28 | GCtab *t = lj_lib_checktab(L, 1); | 30 | CHECK_tab(t) |
| 29 | GCfunc *func = lj_lib_checkfunc(L, 2); | 31 | CHECK_func(f) |
| 30 | MSize i, n = lj_tab_len(t); | 32 | for i=1,#t do |
| 31 | for (i = 1; i <= n; i++) { | 33 | local r = f(i, t[i]) |
| 32 | cTValue *val; | 34 | if r ~= nil then return r end |
| 33 | setfuncV(L, L->top, func); | 35 | end |
| 34 | setintV(L->top+1, i); | 36 | end |
| 35 | val = lj_tab_getint(t, (int32_t)i); | 37 | */ |
| 36 | if (val) { copyTV(L, L->top+2, val); } else { setnilV(L->top+2); } | ||
| 37 | L->top += 3; | ||
| 38 | lua_call(L, 2, 1); | ||
| 39 | if (!tvisnil(L->top-1)) | ||
| 40 | return 1; | ||
| 41 | L->top--; | ||
| 42 | } | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | 38 | ||
| 46 | LJLIB_CF(table_foreach) | 39 | LJLIB_LUA(table_foreach) /* |
| 47 | { | 40 | function(t, f) |
| 48 | GCtab *t = lj_lib_checktab(L, 1); | 41 | CHECK_tab(t) |
| 49 | GCfunc *func = lj_lib_checkfunc(L, 2); | 42 | CHECK_func(f) |
| 50 | L->top = L->base+3; | 43 | for k, v in PAIRS(t) do |
| 51 | setnilV(L->top-1); | 44 | local r = f(k, v) |
| 52 | while (lj_tab_next(L, t, L->top-1)) { | 45 | if r ~= nil then return r end |
| 53 | copyTV(L, L->top+2, L->top); | 46 | end |
| 54 | copyTV(L, L->top+1, L->top-1); | 47 | end |
| 55 | setfuncV(L, L->top, func); | 48 | */ |
| 56 | L->top += 3; | ||
| 57 | lua_call(L, 2, 1); | ||
| 58 | if (!tvisnil(L->top-1)) | ||
| 59 | return 1; | ||
| 60 | L->top--; | ||
| 61 | } | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | 49 | ||
| 65 | LJLIB_ASM(table_getn) LJLIB_REC(.) | 50 | LJLIB_LUA(table_getn) /* |
| 66 | { | 51 | function(t) |
| 67 | lj_lib_checktab(L, 1); | 52 | CHECK_tab(t) |
| 68 | return FFH_UNREACHABLE; | 53 | return #t |
| 69 | } | 54 | end |
| 55 | */ | ||
| 70 | 56 | ||
| 71 | LJLIB_CF(table_maxn) | 57 | LJLIB_CF(table_maxn) |
| 72 | { | 58 | { |
| @@ -119,52 +105,67 @@ LJLIB_CF(table_insert) LJLIB_REC(.) | |||
| 119 | return 0; | 105 | return 0; |
| 120 | } | 106 | } |
| 121 | 107 | ||
| 122 | LJLIB_CF(table_remove) LJLIB_REC(.) | 108 | LJLIB_LUA(table_remove) /* |
| 123 | { | 109 | function(t, pos) |
| 124 | GCtab *t = lj_lib_checktab(L, 1); | 110 | CHECK_tab(t) |
| 125 | int32_t e = (int32_t)lj_tab_len(t); | 111 | local len = #t |
| 126 | int32_t pos = lj_lib_optint(L, 2, e); | 112 | if pos == nil then |
| 127 | if (!(1 <= pos && pos <= e)) /* Nothing to remove? */ | 113 | if len ~= 0 then |
| 128 | return 0; | 114 | local old = t[len] |
| 129 | lua_rawgeti(L, 1, pos); /* Get previous value. */ | 115 | t[len] = nil |
| 130 | /* NOBARRIER: This just moves existing elements around. */ | 116 | return old |
| 131 | for (; pos < e; pos++) { | 117 | end |
| 132 | cTValue *src = lj_tab_getint(t, pos+1); | 118 | else |
| 133 | TValue *dst = lj_tab_setint(L, t, pos); | 119 | CHECK_int(pos) |
| 134 | if (src) { | 120 | if pos >= 1 and pos <= len then |
| 135 | copyTV(L, dst, src); | 121 | local old = t[pos] |
| 136 | } else { | 122 | for i=pos+1,len do |
| 137 | setnilV(dst); | 123 | t[i-1] = t[i] |
| 138 | } | 124 | end |
| 139 | } | 125 | t[len] = nil |
| 140 | setnilV(lj_tab_setint(L, t, e)); /* Remove (last) value. */ | 126 | return old |
| 141 | return 1; /* Return previous value. */ | 127 | end |
| 142 | } | 128 | end |
| 129 | end | ||
| 130 | */ | ||
| 131 | |||
| 132 | LJLIB_LUA(table_move) /* | ||
| 133 | function(a1, f, e, t, a2) | ||
| 134 | CHECK_tab(a1) | ||
| 135 | CHECK_int(f) | ||
| 136 | CHECK_int(e) | ||
| 137 | CHECK_int(t) | ||
| 138 | if a2 == nil then a2 = a1 end | ||
| 139 | CHECK_tab(a2) | ||
| 140 | if e >= f then | ||
| 141 | local d = t - f | ||
| 142 | if t > e or t <= f or a2 ~= a1 then | ||
| 143 | for i=f,e do a2[i+d] = a1[i] end | ||
| 144 | else | ||
| 145 | for i=e,f,-1 do a2[i+d] = a1[i] end | ||
| 146 | end | ||
| 147 | end | ||
| 148 | return a2 | ||
| 149 | end | ||
| 150 | */ | ||
| 143 | 151 | ||
| 144 | LJLIB_CF(table_concat) | 152 | LJLIB_CF(table_concat) LJLIB_REC(.) |
| 145 | { | 153 | { |
| 146 | luaL_Buffer b; | ||
| 147 | GCtab *t = lj_lib_checktab(L, 1); | 154 | GCtab *t = lj_lib_checktab(L, 1); |
| 148 | GCstr *sep = lj_lib_optstr(L, 2); | 155 | GCstr *sep = lj_lib_optstr(L, 2); |
| 149 | MSize seplen = sep ? sep->len : 0; | ||
| 150 | int32_t i = lj_lib_optint(L, 3, 1); | 156 | int32_t i = lj_lib_optint(L, 3, 1); |
| 151 | int32_t e = (L->base+3 < L->top && !tvisnil(L->base+3)) ? | 157 | int32_t e = (L->base+3 < L->top && !tvisnil(L->base+3)) ? |
| 152 | lj_lib_checkint(L, 4) : (int32_t)lj_tab_len(t); | 158 | lj_lib_checkint(L, 4) : (int32_t)lj_tab_len(t); |
| 153 | luaL_buffinit(L, &b); | 159 | SBuf *sb = lj_buf_tmp_(L); |
| 154 | if (i <= e) { | 160 | SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e); |
| 155 | for (;;) { | 161 | if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */ |
| 156 | cTValue *o; | 162 | int32_t idx = (int32_t)(intptr_t)sb->w; |
| 157 | lua_rawgeti(L, 1, i); | 163 | cTValue *o = lj_tab_getint(t, idx); |
| 158 | o = L->top-1; | 164 | lj_err_callerv(L, LJ_ERR_TABCAT, |
| 159 | if (!(tvisstr(o) || tvisnumber(o))) | 165 | lj_obj_itypename[o ? itypemap(o) : ~LJ_TNIL], idx); |
| 160 | lj_err_callerv(L, LJ_ERR_TABCAT, lj_typename(o), i); | ||
| 161 | luaL_addvalue(&b); | ||
| 162 | if (i++ == e) break; | ||
| 163 | if (seplen) | ||
| 164 | luaL_addlstring(&b, strdata(sep), seplen); | ||
| 165 | } | ||
| 166 | } | 166 | } |
| 167 | luaL_pushresult(&b); | 167 | setstrV(L, L->top-1, lj_buf_str(L, sbx)); |
| 168 | lj_gc_check(L); | ||
| 168 | return 1; | 169 | return 1; |
| 169 | } | 170 | } |
| 170 | 171 | ||
| @@ -284,6 +285,30 @@ LJLIB_CF(table_pack) | |||
| 284 | } | 285 | } |
| 285 | #endif | 286 | #endif |
| 286 | 287 | ||
| 288 | LJLIB_NOREG LJLIB_CF(table_new) LJLIB_REC(.) | ||
| 289 | { | ||
| 290 | int32_t a = lj_lib_checkint(L, 1); | ||
| 291 | int32_t h = lj_lib_checkint(L, 2); | ||
| 292 | lua_createtable(L, a, h); | ||
| 293 | return 1; | ||
| 294 | } | ||
| 295 | |||
| 296 | LJLIB_NOREG LJLIB_CF(table_clear) LJLIB_REC(.) | ||
| 297 | { | ||
| 298 | lj_tab_clear(lj_lib_checktab(L, 1)); | ||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | static int luaopen_table_new(lua_State *L) | ||
| 303 | { | ||
| 304 | return lj_lib_postreg(L, lj_cf_table_new, FF_table_new, "new"); | ||
| 305 | } | ||
| 306 | |||
| 307 | static int luaopen_table_clear(lua_State *L) | ||
| 308 | { | ||
| 309 | return lj_lib_postreg(L, lj_cf_table_clear, FF_table_clear, "clear"); | ||
| 310 | } | ||
| 311 | |||
| 287 | /* ------------------------------------------------------------------------ */ | 312 | /* ------------------------------------------------------------------------ */ |
| 288 | 313 | ||
| 289 | #include "lj_libdef.h" | 314 | #include "lj_libdef.h" |
| @@ -295,6 +320,8 @@ LUALIB_API int luaopen_table(lua_State *L) | |||
| 295 | lua_getglobal(L, "unpack"); | 320 | lua_getglobal(L, "unpack"); |
| 296 | lua_setfield(L, -2, "unpack"); | 321 | lua_setfield(L, -2, "unpack"); |
| 297 | #endif | 322 | #endif |
| 323 | lj_lib_prereg(L, LUA_TABLIBNAME ".new", luaopen_table_new, tabV(L->top-1)); | ||
| 324 | lj_lib_prereg(L, LUA_TABLIBNAME ".clear", luaopen_table_clear, tabV(L->top-1)); | ||
| 298 | return 1; | 325 | return 1; |
| 299 | } | 326 | } |
| 300 | 327 | ||
