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@8
|
5 #define SEQLUA_ITERTYPE_CALL 1
|
jbe@8
|
6 #define SEQLUA_ITERTYPE_FUNC 2
|
jbe@8
|
7 #define SEQLUA_ITERTYPE_META 3
|
jbe@8
|
8 #define SEQLUA_ITERTYPE_RAW 4
|
jbe@0
|
9
|
jbe@0
|
10 void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx) {
|
jbe@0
|
11 luaL_checkany(L, idx); // provides better error message
|
jbe@0
|
12 iter->L = L;
|
jbe@0
|
13 if (luaL_getmetafield(L, idx, "__call")) {
|
jbe@0
|
14 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
|
jbe@8
|
15 iter->idx = lua_gettop(L);
|
jbe@8
|
16 iter->callargidx = idx;
|
jbe@8
|
17 iter->itertype = SEQLUA_ITERTYPE_CALL;
|
jbe@0
|
18 } else if (lua_type(L, idx) == LUA_TFUNCTION) {
|
jbe@8
|
19 lua_pushnil(L); // dummy value
|
jbe@8
|
20 iter->idx = idx;
|
jbe@0
|
21 iter->itertype = SEQLUA_ITERTYPE_FUNC;
|
jbe@0
|
22 } else {
|
jbe@8
|
23 iter->idx = idx;
|
jbe@0
|
24 if (luaL_getmetafield(L, idx, "__index")) {
|
jbe@0
|
25 iter->itertype = SEQLUA_ITERTYPE_META;
|
jbe@8
|
26 // leave __index as dummy value
|
jbe@0
|
27 } else {
|
jbe@8
|
28 lua_pushnil(L); // dummy value
|
jbe@0
|
29 luaL_checktype(L, idx, LUA_TTABLE);
|
jbe@0
|
30 iter->itertype = SEQLUA_ITERTYPE_RAW;
|
jbe@0
|
31 }
|
jbe@0
|
32 }
|
jbe@0
|
33 iter->i = 0;
|
jbe@0
|
34 }
|
jbe@0
|
35
|
jbe@0
|
36 int seqlua_iternext(seqlua_Iterator *iter) {
|
jbe@0
|
37 lua_State *L = iter->L;
|
jbe@0
|
38 lua_Integer i = ++iter->i;
|
jbe@0
|
39 switch (iter->itertype) {
|
jbe@8
|
40 case SEQLUA_ITERTYPE_CALL:
|
jbe@8
|
41 lua_pushvalue(L, iter->idx);
|
jbe@8
|
42 lua_pushvalue(L, iter->callargidx);
|
jbe@8
|
43 lua_call(L, 1, 1);
|
jbe@8
|
44 break;
|
jbe@0
|
45 case SEQLUA_ITERTYPE_FUNC:
|
jbe@8
|
46 lua_pushvalue(L, iter->idx);
|
jbe@0
|
47 lua_call(L, 0, 1);
|
jbe@0
|
48 break;
|
jbe@0
|
49 case SEQLUA_ITERTYPE_META:
|
jbe@0
|
50 lua_pushinteger(L, i);
|
jbe@8
|
51 lua_gettable(L, iter->idx);
|
jbe@0
|
52 break;
|
jbe@0
|
53 case SEQLUA_ITERTYPE_RAW:
|
jbe@8
|
54 lua_rawgeti(L, iter->idx, i);
|
jbe@8
|
55 break;
|
jbe@0
|
56 }
|
jbe@0
|
57 if (lua_isnil(L, -1)) {
|
jbe@8
|
58 lua_pop(L, 2); // remove nil and dummy value
|
jbe@0
|
59 return 0;
|
jbe@0
|
60 }
|
jbe@0
|
61 return 1;
|
jbe@0
|
62 }
|
jbe@0
|
63
|
jbe@0
|
64 static int seqlua_iterclosureaux_raw(lua_State *L) {
|
jbe@0
|
65 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
|
jbe@0
|
66 lua_rawgeti(L, lua_upvalueindex(1), i);
|
jbe@0
|
67 if (lua_isnil(L, -1)) return 1;
|
jbe@0
|
68 lua_pushinteger(L, i);
|
jbe@0
|
69 lua_replace(L, lua_upvalueindex(2));
|
jbe@0
|
70 return 1;
|
jbe@0
|
71 }
|
jbe@0
|
72
|
jbe@0
|
73 static int seqlua_iterclosureaux_meta(lua_State *L) {
|
jbe@0
|
74 lua_Integer i = lua_tointeger(L, lua_upvalueindex(2)) + 1;
|
jbe@0
|
75 lua_pushinteger(L, i);
|
jbe@0
|
76 lua_gettable(L, lua_upvalueindex(1));
|
jbe@0
|
77 if (lua_isnil(L, -1)) return 1;
|
jbe@0
|
78 lua_pushinteger(L, i);
|
jbe@0
|
79 lua_replace(L, lua_upvalueindex(2));
|
jbe@0
|
80 return 1;
|
jbe@0
|
81 }
|
jbe@0
|
82
|
jbe@8
|
83 static int seqlua_iterclosureaux_call(lua_State *L) {
|
jbe@8
|
84 lua_pushvalue(L, lua_upvalueindex(1));
|
jbe@8
|
85 lua_pushvalue(L, lua_upvalueindex(2));
|
jbe@8
|
86 lua_call(L, 1, 1);
|
jbe@8
|
87 return 1;
|
jbe@8
|
88 }
|
jbe@8
|
89
|
jbe@0
|
90 void seqlua_iterclosure(lua_State *L, int idx) {
|
jbe@8
|
91 luaL_checkany(L, idx); // provides better error message
|
jbe@0
|
92 if (lua_type(L, idx) == LUA_TFUNCTION) {
|
jbe@0
|
93 // do nothing
|
jbe@0
|
94 } else if (luaL_getmetafield(L, idx, "__call")) {
|
jbe@0
|
95 if (lua_type(L, -1) != LUA_TFUNCTION) luaL_error(L, "__call is not a function");
|
jbe@8
|
96 lua_pushvalue(L, idx);
|
jbe@8
|
97 lua_pushcclosure(L, seqlua_iterclosureaux_call, 2);
|
jbe@0
|
98 lua_replace(L, idx);
|
jbe@0
|
99 } else if (luaL_getmetafield(L, idx, "__index")) {
|
jbe@0
|
100 lua_pop(L, 1);
|
jbe@0
|
101 lua_pushvalue(L, idx);
|
jbe@0
|
102 lua_pushinteger(L, 0);
|
jbe@0
|
103 lua_pushcclosure(L, seqlua_iterclosureaux_raw, 2);
|
jbe@0
|
104 lua_replace(L, idx);
|
jbe@0
|
105 } else {
|
jbe@0
|
106 luaL_checktype(L, idx, LUA_TTABLE);
|
jbe@0
|
107 lua_pushvalue(L, idx);
|
jbe@0
|
108 lua_pushinteger(L, 0);
|
jbe@0
|
109 lua_pushcclosure(L, seqlua_iterclosureaux_meta, 2);
|
jbe@0
|
110 lua_replace(L, idx);
|
jbe@0
|
111 }
|
jbe@0
|
112 }
|
jbe@0
|
113
|