diff options
Diffstat (limited to 'src/lib_table.c')
-rw-r--r-- | src/lib_table.c | 137 |
1 files changed, 65 insertions, 72 deletions
diff --git a/src/lib_table.c b/src/lib_table.c index 8d53a6cd..5619f9ad 100644 --- a/src/lib_table.c +++ b/src/lib_table.c | |||
@@ -16,6 +16,8 @@ | |||
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" | ||
20 | #include "lj_str.h" | ||
19 | #include "lj_tab.h" | 21 | #include "lj_tab.h" |
20 | #include "lj_lib.h" | 22 | #include "lj_lib.h" |
21 | 23 | ||
@@ -23,50 +25,34 @@ | |||
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,59 @@ 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 | */ | ||
143 | 131 | ||
144 | LJLIB_CF(table_concat) | 132 | LJLIB_CF(table_concat) |
145 | { | 133 | { |
146 | luaL_Buffer b; | ||
147 | GCtab *t = lj_lib_checktab(L, 1); | 134 | GCtab *t = lj_lib_checktab(L, 1); |
148 | GCstr *sep = lj_lib_optstr(L, 2); | 135 | GCstr *sep = lj_lib_optstr(L, 2); |
149 | MSize seplen = sep ? sep->len : 0; | 136 | MSize seplen = sep ? sep->len : 0; |
150 | int32_t i = lj_lib_optint(L, 3, 1); | 137 | int32_t i = lj_lib_optint(L, 3, 1); |
151 | int32_t e = L->base+3 < L->top ? lj_lib_checkint(L, 4) : | 138 | int32_t e = L->base+3 < L->top ? lj_lib_checkint(L, 4) : |
152 | (int32_t)lj_tab_len(t); | 139 | (int32_t)lj_tab_len(t); |
153 | luaL_buffinit(L, &b); | ||
154 | if (i <= e) { | 140 | if (i <= e) { |
141 | char buf[LJ_STR_NUMBERBUF]; | ||
142 | SBuf *sb = &G(L)->tmpbuf; | ||
143 | setsbufL(sb, L); | ||
144 | lj_buf_reset(sb); | ||
155 | for (;;) { | 145 | for (;;) { |
156 | cTValue *o; | 146 | cTValue *o = lj_tab_getint(t, i); |
157 | lua_rawgeti(L, 1, i); | 147 | MSize len; |
158 | o = L->top-1; | 148 | const char *p = lj_str_buftv(buf, o, &len); |
159 | if (!(tvisstr(o) || tvisnumber(o))) | 149 | if (!p) |
160 | lj_err_callerv(L, LJ_ERR_TABCAT, lj_typename(o), i); | 150 | lj_err_callerv(L, LJ_ERR_TABCAT, lj_typename(o), i); |
161 | luaL_addvalue(&b); | 151 | lj_buf_putmem(sb, p, len); |
162 | if (i++ == e) break; | 152 | if (i++ == e) break; |
163 | if (seplen) | 153 | if (seplen) |
164 | luaL_addlstring(&b, strdata(sep), seplen); | 154 | lj_buf_putmem(sb, strdata(sep), seplen); |
165 | } | 155 | } |
156 | setstrV(L, L->top-1, lj_buf_str(L, sb)); | ||
157 | lj_gc_check(L); | ||
158 | } else { | ||
159 | setstrV(L, L->top-1, &G(L)->strempty); | ||
166 | } | 160 | } |
167 | luaL_pushresult(&b); | ||
168 | return 1; | 161 | return 1; |
169 | } | 162 | } |
170 | 163 | ||