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