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 b2856ee2..0450f1f6 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)sbufP(sb); |
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 | ||