jbe@0: #include jbe@0: #include jbe@0: #include "seqlualib.h" jbe@35: #include 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@54: void seqlua_iterinit(lua_State *L, seqlua_Iterator *iter, int idx) { jbe@30: if (luaL_getmetafield(L, idx, "__ipairs")) { jbe@54: lua_pushvalue(L, idx); jbe@30: lua_call(L, 1, 3); jbe@35: if (lua_type(L, -3) == LUA_TSTRING) { jbe@35: const char *method = lua_tostring(L, -3); jbe@35: if (!strcmp(method, "raw")) { jbe@35: iter->itertype = SEQLUA_ITERTYPE_RAW; jbe@35: } else if (!strcmp(method, "index")) { jbe@35: iter->itertype = SEQLUA_ITERTYPE_INDEX; jbe@35: } else if (!strcmp(method, "call")) { jbe@35: iter->itertype = SEQLUA_ITERTYPE_CALL; jbe@35: } else { jbe@35: luaL_error(L, "Unexpected string returned by __ipairs metamethod"); jbe@35: } jbe@35: iter->idx = lua_gettop(L) - 1; jbe@35: } else { jbe@35: iter->itertype = SEQLUA_ITERTYPE_IPAIRS; jbe@35: } jbe@30: } else { jbe@30: if (lua_type(L, idx) == LUA_TFUNCTION) { jbe@54: iter->itertype = SEQLUA_ITERTYPE_CALL; jbe@32: } else if (luaL_getmetafield(L, idx, "__index")) { jbe@30: lua_pop(L, 1); jbe@30: iter->itertype = SEQLUA_ITERTYPE_INDEX; jbe@54: } else { jbe@54: luaL_checktype(L, idx, LUA_TTABLE); jbe@54: iter->itertype = SEQLUA_ITERTYPE_RAW; jbe@30: } jbe@30: // always occupy 3 stack indicies jbe@54: 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@0: lua_pushinteger(L, i); jbe@8: lua_gettable(L, iter->idx); jbe@32: break; 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: