jbe@0: #include jbe@0: #include jbe@0: #include "seqlualib.h" jbe@0: jbe@30: #define SEQLUA_ITERTYPE_IPAIRS 1 jbe@30: #define SEQLUA_ITERTYPE_CALL 2 jbe@30: #define SEQLUA_ITERTYPE_INDEX 3 jbe@30: #define SEQLUA_ITERTYPE_RAW 4 jbe@0: jbe@0: void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx) { jbe@30: if (luaL_getmetafield(L, idx, "__ipairs")) { jbe@30: lua_pushvalue(L, idx); jbe@30: lua_call(L, 1, 3); jbe@30: iter->itertype = SEQLUA_ITERTYPE_IPAIRS; jbe@30: } else { jbe@30: if (lua_type(L, idx) == LUA_TFUNCTION) { jbe@30: iter->itertype = SEQLUA_ITERTYPE_CALL; jbe@30: } else if ( jbe@30: luaL_getmetafield(L, idx, "__index") || jbe@30: luaL_getmetafield(L, idx, "__len") jbe@30: ) { jbe@30: lua_pop(L, 1); jbe@31: iter->len = luaL_len(L, idx); jbe@30: iter->itertype = SEQLUA_ITERTYPE_INDEX; jbe@30: } else { jbe@30: luaL_checktype(L, idx, LUA_TTABLE); jbe@30: iter->itertype = SEQLUA_ITERTYPE_RAW; jbe@30: } jbe@30: // always occupy 3 stack indicies jbe@30: lua_pushnil(L); jbe@30: lua_pushnil(L); jbe@30: lua_pushnil(L); jbe@30: iter->idx = idx; jbe@30: } jbe@0: iter->L = L; jbe@0: iter->i = 0; jbe@0: } jbe@0: jbe@0: int seqlua_iternext(seqlua_Iterator *iter) { jbe@0: lua_State *L = iter->L; jbe@0: lua_Integer i = ++iter->i; jbe@0: switch (iter->itertype) { jbe@30: case SEQLUA_ITERTYPE_IPAIRS: jbe@30: lua_pushvalue(L, -3); jbe@30: lua_pushvalue(L, -3); jbe@30: lua_pushvalue(L, -3); jbe@30: lua_call(L, 2, 2); jbe@30: if (lua_isnil(L, -2)) { jbe@30: lua_pop(L, 5); jbe@30: return 0; jbe@30: } jbe@30: lua_remove(L, -3); jbe@30: return 1; jbe@30: case SEQLUA_ITERTYPE_CALL: jbe@8: lua_pushvalue(L, iter->idx); jbe@0: lua_call(L, 0, 1); jbe@0: break; jbe@30: case SEQLUA_ITERTYPE_INDEX: jbe@30: if (i > iter->len) { jbe@30: lua_pop(L, 3); jbe@30: return 0; jbe@30: } jbe@0: lua_pushinteger(L, i); jbe@8: lua_gettable(L, iter->idx); jbe@30: return 1; jbe@0: case SEQLUA_ITERTYPE_RAW: jbe@8: lua_rawgeti(L, iter->idx, i); jbe@8: break; jbe@0: } jbe@0: if (lua_isnil(L, -1)) { jbe@30: lua_pop(L, 4); jbe@0: return 0; jbe@0: } jbe@0: return 1; jbe@0: } jbe@0: