seqlua

view seqlualib.c @ 53:664736a8fcbf

Included mode argument for seqlua_iterloop in README
author jbe
date Tue Aug 26 23:53:29 2014 +0200 (2014-08-26)
parents 3362ec36cb09
children 92ce3958aca7
line source
1 #include <lua.h>
2 #include <lauxlib.h>
3 #include "seqlualib.h"
4 #include <string.h>
6 #define SEQLUA_ITERTYPE_IPAIRS 1
7 #define SEQLUA_ITERTYPE_CALL 2
8 #define SEQLUA_ITERTYPE_INDEX 3
9 #define SEQLUA_ITERTYPE_RAW 4
11 void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int mode, int idx) {
12 int generated = 0;
13 seqlua_iterinit_repeat:
14 if (luaL_getmetafield(L, idx, "__ipairs")) {
15 if (!generated) lua_pushvalue(L, idx);
16 lua_call(L, 1, 3);
17 if (lua_type(L, -3) == LUA_TSTRING) {
18 const char *method = lua_tostring(L, -3);
19 if (!strcmp(method, "raw")) {
20 iter->itertype = SEQLUA_ITERTYPE_RAW;
21 } else if (!strcmp(method, "index")) {
22 iter->itertype = SEQLUA_ITERTYPE_INDEX;
23 } else if (!strcmp(method, "call")) {
24 iter->itertype = SEQLUA_ITERTYPE_CALL;
25 } else {
26 luaL_error(L, "Unexpected string returned by __ipairs metamethod");
27 }
28 iter->idx = lua_gettop(L) - 1;
29 } else {
30 iter->itertype = SEQLUA_ITERTYPE_IPAIRS;
31 }
32 } else {
33 if (lua_type(L, idx) == LUA_TFUNCTION) {
34 if (generated || mode == SEQLUA_MODE_CALL) {
35 iter->itertype = SEQLUA_ITERTYPE_CALL;
36 goto seqlua_iterinit_finish;
37 } else if (mode == SEQLUA_MODE_GENERATOR) {
38 lua_pushvalue(L, idx);
39 lua_call(L, 0, 1);
40 idx = lua_gettop(L);
41 goto seqlua_iterinit_repeat;
42 }
43 } else if (luaL_getmetafield(L, idx, "__index")) {
44 lua_pop(L, 1);
45 iter->itertype = SEQLUA_ITERTYPE_INDEX;
46 goto seqlua_iterinit_finish;
47 }
48 luaL_checktype(L, idx, LUA_TTABLE);
49 iter->itertype = SEQLUA_ITERTYPE_RAW;
50 seqlua_iterinit_finish:
51 // always occupy 3 stack indicies
52 if (!generated) lua_pushnil(L);
53 lua_pushnil(L);
54 lua_pushnil(L);
55 iter->idx = idx;
56 }
57 iter->L = L;
58 iter->i = 0;
59 }
61 int seqlua_iternext(seqlua_Iterator *iter) {
62 lua_State *L = iter->L;
63 lua_Integer i = ++iter->i;
64 switch (iter->itertype) {
65 case SEQLUA_ITERTYPE_IPAIRS:
66 lua_pushvalue(L, -3);
67 lua_pushvalue(L, -3);
68 lua_pushvalue(L, -3);
69 lua_call(L, 2, 2);
70 if (lua_isnil(L, -2)) {
71 lua_pop(L, 5);
72 return 0;
73 }
74 lua_remove(L, -3);
75 return 1;
76 case SEQLUA_ITERTYPE_CALL:
77 lua_pushvalue(L, iter->idx);
78 lua_call(L, 0, 1);
79 break;
80 case SEQLUA_ITERTYPE_INDEX:
81 lua_pushinteger(L, i);
82 lua_gettable(L, iter->idx);
83 break;
84 case SEQLUA_ITERTYPE_RAW:
85 lua_rawgeti(L, iter->idx, i);
86 break;
87 }
88 if (lua_isnil(L, -1)) {
89 lua_pop(L, 4);
90 return 0;
91 }
92 return 1;
93 }

Impressum / About Us