rev |
line source |
jbe@0
|
1 #include <lua.h>
|
jbe@0
|
2 #include <lauxlib.h>
|
jbe@0
|
3 #include "seqlualib.h"
|
jbe@0
|
4
|
jbe@30
|
5 #define SEQLUA_ITERTYPE_IPAIRS 1
|
jbe@30
|
6 #define SEQLUA_ITERTYPE_CALL 2
|
jbe@30
|
7 #define SEQLUA_ITERTYPE_INDEX 3
|
jbe@30
|
8 #define SEQLUA_ITERTYPE_RAW 4
|
jbe@0
|
9
|
jbe@0
|
10 void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx) {
|
jbe@30
|
11 if (luaL_getmetafield(L, idx, "__ipairs")) {
|
jbe@30
|
12 lua_pushvalue(L, idx);
|
jbe@30
|
13 lua_call(L, 1, 3);
|
jbe@30
|
14 iter->itertype = SEQLUA_ITERTYPE_IPAIRS;
|
jbe@30
|
15 } else {
|
jbe@30
|
16 if (lua_type(L, idx) == LUA_TFUNCTION) {
|
jbe@30
|
17 iter->itertype = SEQLUA_ITERTYPE_CALL;
|
jbe@30
|
18 } else if (
|
jbe@30
|
19 luaL_getmetafield(L, idx, "__index") ||
|
jbe@30
|
20 luaL_getmetafield(L, idx, "__len")
|
jbe@30
|
21 ) {
|
jbe@30
|
22 lua_pop(L, 1);
|
jbe@31
|
23 iter->len = luaL_len(L, idx);
|
jbe@30
|
24 iter->itertype = SEQLUA_ITERTYPE_INDEX;
|
jbe@30
|
25 } else {
|
jbe@30
|
26 luaL_checktype(L, idx, LUA_TTABLE);
|
jbe@30
|
27 iter->itertype = SEQLUA_ITERTYPE_RAW;
|
jbe@30
|
28 }
|
jbe@30
|
29 // always occupy 3 stack indicies
|
jbe@30
|
30 lua_pushnil(L);
|
jbe@30
|
31 lua_pushnil(L);
|
jbe@30
|
32 lua_pushnil(L);
|
jbe@30
|
33 iter->idx = idx;
|
jbe@30
|
34 }
|
jbe@0
|
35 iter->L = L;
|
jbe@0
|
36 iter->i = 0;
|
jbe@0
|
37 }
|
jbe@0
|
38
|
jbe@0
|
39 int seqlua_iternext(seqlua_Iterator *iter) {
|
jbe@0
|
40 lua_State *L = iter->L;
|
jbe@0
|
41 lua_Integer i = ++iter->i;
|
jbe@0
|
42 switch (iter->itertype) {
|
jbe@30
|
43 case SEQLUA_ITERTYPE_IPAIRS:
|
jbe@30
|
44 lua_pushvalue(L, -3);
|
jbe@30
|
45 lua_pushvalue(L, -3);
|
jbe@30
|
46 lua_pushvalue(L, -3);
|
jbe@30
|
47 lua_call(L, 2, 2);
|
jbe@30
|
48 if (lua_isnil(L, -2)) {
|
jbe@30
|
49 lua_pop(L, 5);
|
jbe@30
|
50 return 0;
|
jbe@30
|
51 }
|
jbe@30
|
52 lua_remove(L, -3);
|
jbe@30
|
53 return 1;
|
jbe@30
|
54 case SEQLUA_ITERTYPE_CALL:
|
jbe@8
|
55 lua_pushvalue(L, iter->idx);
|
jbe@0
|
56 lua_call(L, 0, 1);
|
jbe@0
|
57 break;
|
jbe@30
|
58 case SEQLUA_ITERTYPE_INDEX:
|
jbe@30
|
59 if (i > iter->len) {
|
jbe@30
|
60 lua_pop(L, 3);
|
jbe@30
|
61 return 0;
|
jbe@30
|
62 }
|
jbe@0
|
63 lua_pushinteger(L, i);
|
jbe@8
|
64 lua_gettable(L, iter->idx);
|
jbe@30
|
65 return 1;
|
jbe@0
|
66 case SEQLUA_ITERTYPE_RAW:
|
jbe@8
|
67 lua_rawgeti(L, iter->idx, i);
|
jbe@8
|
68 break;
|
jbe@0
|
69 }
|
jbe@0
|
70 if (lua_isnil(L, -1)) {
|
jbe@30
|
71 lua_pop(L, 4);
|
jbe@0
|
72 return 0;
|
jbe@0
|
73 }
|
jbe@0
|
74 return 1;
|
jbe@0
|
75 }
|
jbe@0
|
76
|