diff options
Diffstat (limited to 'src/lib_table.c')
-rw-r--r-- | src/lib_table.c | 140 |
1 files changed, 60 insertions, 80 deletions
diff --git a/src/lib_table.c b/src/lib_table.c index 542ed1f8..d7df8399 100644 --- a/src/lib_table.c +++ b/src/lib_table.c | |||
@@ -16,6 +16,7 @@ | |||
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" |
20 | #include "lj_lib.h" | 21 | #include "lj_lib.h" |
21 | 22 | ||
@@ -23,50 +24,34 @@ | |||
23 | 24 | ||
24 | #define LJLIB_MODULE_table | 25 | #define LJLIB_MODULE_table |
25 | 26 | ||
26 | LJLIB_CF(table_foreachi) | 27 | LJLIB_LUA(table_foreachi) /* |
27 | { | 28 | function(t, f) |
28 | GCtab *t = lj_lib_checktab(L, 1); | 29 | CHECK_tab(t) |
29 | GCfunc *func = lj_lib_checkfunc(L, 2); | 30 | CHECK_func(f) |
30 | MSize i, n = lj_tab_len(t); | 31 | for i=1,#t do |
31 | for (i = 1; i <= n; i++) { | 32 | local r = f(i, t[i]) |
32 | cTValue *val; | 33 | if r ~= nil then return r end |
33 | setfuncV(L, L->top, func); | 34 | end |
34 | setintV(L->top+1, i); | 35 | end |
35 | val = lj_tab_getint(t, (int32_t)i); | 36 | */ |
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 | 37 | ||
46 | LJLIB_CF(table_foreach) | 38 | LJLIB_LUA(table_foreach) /* |
47 | { | 39 | function(t, f) |
48 | GCtab *t = lj_lib_checktab(L, 1); | 40 | CHECK_tab(t) |
49 | GCfunc *func = lj_lib_checkfunc(L, 2); | 41 | CHECK_func(f) |
50 | L->top = L->base+3; | 42 | for k, v in PAIRS(t) do |
51 | setnilV(L->top-1); | 43 | local r = f(k, v) |
52 | while (lj_tab_next(L, t, L->top-1)) { | 44 | if r ~= nil then return r end |
53 | copyTV(L, L->top+2, L->top); | 45 | end |
54 | copyTV(L, L->top+1, L->top-1); | 46 | end |
55 | setfuncV(L, L->top, func); | 47 | */ |
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 | 48 | ||
65 | LJLIB_ASM(table_getn) LJLIB_REC(.) | 49 | LJLIB_LUA(table_getn) /* |
66 | { | 50 | function(t) |
67 | lj_lib_checktab(L, 1); | 51 | CHECK_tab(t) |
68 | return FFH_UNREACHABLE; | 52 | return #t |
69 | } | 53 | end |
54 | */ | ||
70 | 55 | ||
71 | LJLIB_CF(table_maxn) | 56 | LJLIB_CF(table_maxn) |
72 | { | 57 | { |
@@ -119,52 +104,47 @@ LJLIB_CF(table_insert) LJLIB_REC(.) | |||
119 | return 0; | 104 | return 0; |
120 | } | 105 | } |
121 | 106 | ||
122 | LJLIB_CF(table_remove) LJLIB_REC(.) | 107 | LJLIB_LUA(table_remove) /* |
123 | { | 108 | function(t, pos) |
124 | GCtab *t = lj_lib_checktab(L, 1); | 109 | CHECK_tab(t) |
125 | int32_t e = (int32_t)lj_tab_len(t); | 110 | local len = #t |
126 | int32_t pos = lj_lib_optint(L, 2, e); | 111 | if pos == nil then |
127 | if (!(1 <= pos && pos <= e)) /* Nothing to remove? */ | 112 | if len ~= 0 then |
128 | return 0; | 113 | local old = t[len] |
129 | lua_rawgeti(L, 1, pos); /* Get previous value. */ | 114 | t[len] = nil |
130 | /* NOBARRIER: This just moves existing elements around. */ | 115 | return old |
131 | for (; pos < e; pos++) { | 116 | end |
132 | cTValue *src = lj_tab_getint(t, pos+1); | 117 | else |
133 | TValue *dst = lj_tab_setint(L, t, pos); | 118 | CHECK_int(pos) |
134 | if (src) { | 119 | if pos >= 1 and pos <= len then |
135 | copyTV(L, dst, src); | 120 | local old = t[pos] |
136 | } else { | 121 | for i=pos+1,len do |
137 | setnilV(dst); | 122 | t[i-1] = t[i] |
138 | } | 123 | end |
139 | } | 124 | t[len] = nil |
140 | setnilV(lj_tab_setint(L, t, e)); /* Remove (last) value. */ | 125 | return old |
141 | return 1; /* Return previous value. */ | 126 | end |
142 | } | 127 | end |
128 | end | ||
129 | */ | ||
143 | 130 | ||
144 | LJLIB_CF(table_concat) | 131 | LJLIB_CF(table_concat) LJLIB_REC(.) |
145 | { | 132 | { |
146 | luaL_Buffer b; | ||
147 | GCtab *t = lj_lib_checktab(L, 1); | 133 | GCtab *t = lj_lib_checktab(L, 1); |
148 | GCstr *sep = lj_lib_optstr(L, 2); | 134 | GCstr *sep = lj_lib_optstr(L, 2); |
149 | MSize seplen = sep ? sep->len : 0; | ||
150 | int32_t i = lj_lib_optint(L, 3, 1); | 135 | int32_t i = lj_lib_optint(L, 3, 1); |
151 | int32_t e = (L->base+3 < L->top && !tvisnil(L->base+3)) ? | 136 | int32_t e = (L->base+3 < L->top && !tvisnil(L->base+3)) ? |
152 | lj_lib_checkint(L, 4) : (int32_t)lj_tab_len(t); | 137 | lj_lib_checkint(L, 4) : (int32_t)lj_tab_len(t); |
153 | luaL_buffinit(L, &b); | 138 | SBuf *sb = lj_buf_tmp_(L); |
154 | if (i <= e) { | 139 | SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e); |
155 | for (;;) { | 140 | if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */ |
156 | cTValue *o; | 141 | int32_t idx = (int32_t)(intptr_t)sbufP(sb); |
157 | lua_rawgeti(L, 1, i); | 142 | cTValue *o = lj_tab_getint(t, idx); |
158 | o = L->top-1; | 143 | lj_err_callerv(L, LJ_ERR_TABCAT, |
159 | if (!(tvisstr(o) || tvisnumber(o))) | 144 | 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 | } | 145 | } |
167 | luaL_pushresult(&b); | 146 | setstrV(L, L->top-1, lj_buf_str(L, sbx)); |
147 | lj_gc_check(L); | ||
168 | return 1; | 148 | return 1; |
169 | } | 149 | } |
170 | 150 | ||