jbe@0: #include jbe@0: #include jbe@8: jbe@0: static int seqlua_ipairsaux_raw(lua_State *L) { jbe@0: lua_Integer i; jbe@0: luaL_checktype(L, 1, LUA_TTABLE); jbe@0: i = luaL_checkinteger(L, 2) + 1; jbe@0: lua_pushinteger(L, i); jbe@0: lua_rawgeti(L, 1, i); // TODO: Lua 5.3 returns type jbe@0: return lua_isnil(L, -1) ? 1 : 2; jbe@0: } jbe@0: jbe@0: static int seqlua_ipairsaux_meta(lua_State *L) { jbe@0: lua_Integer i; jbe@0: i = luaL_checkinteger(L, 2) + 1; jbe@0: lua_pushinteger(L, i); jbe@0: lua_pushinteger(L, i); jbe@0: lua_gettable(L, 1); // TODO: Lua 5.3 returns type jbe@0: return lua_isnil(L, -1) ? 1 : 2; jbe@0: } jbe@0: jbe@0: static int seqlua_ipairsaux_func(lua_State *L) { jbe@0: lua_pushinteger(L, luaL_checkinteger(L, 2) + 1); jbe@0: lua_insert(L, 1); jbe@0: lua_settop(L, 2); jbe@0: lua_call(L, 0, LUA_MULTRET); jbe@0: if (lua_isnoneornil(L, 2)) { jbe@0: lua_settop(L, 0); jbe@0: lua_pushnil(L); jbe@0: return 1; jbe@0: } else { jbe@0: return lua_gettop(L); jbe@0: } jbe@0: } jbe@0: jbe@0: static int seqlua_ipairs(lua_State *L) { jbe@8: luaL_checkany(L, 1); // provides better error message jbe@23: if ( jbe@23: lua_type(L, 1) == LUA_TFUNCTION || jbe@23: (luaL_getmetafield(L, 1, "__call") && (lua_pop(L, 1), 1)) jbe@23: ) { jbe@0: lua_pushcfunction(L, seqlua_ipairsaux_func); jbe@0: } else if (luaL_getmetafield(L, 1, "__index")) { jbe@0: lua_pushcfunction(L, seqlua_ipairsaux_meta); jbe@0: } else { jbe@0: luaL_checktype(L, 1, LUA_TTABLE); jbe@0: lua_pushcfunction(L, seqlua_ipairsaux_raw); jbe@0: } jbe@0: lua_pushvalue(L, 1); jbe@0: lua_pushinteger(L, 0); jbe@0: return 3; jbe@0: } jbe@0: jbe@0: int luaopen_seqlua(lua_State *L) { jbe@0: lua_pushcfunction(L, seqlua_ipairs); jbe@0: lua_setglobal(L, "ipairs"); jbe@0: return 1; jbe@0: }