jbe@0: #include jbe@0: #include jbe@25: #include "seqlualib.h" jbe@35: #include jbe@8: jbe@32: static int seqlua_ipairsaux_raw(lua_State *L) { jbe@32: lua_Integer i; jbe@32: luaL_checktype(L, 1, LUA_TTABLE); jbe@32: i = luaL_checkinteger(L, 2) + 1; jbe@32: lua_pushinteger(L, i); jbe@32: lua_rawgeti(L, 1, i); // TODO: Lua 5.3 returns type jbe@32: return lua_isnil(L, -1) ? 1 : 2; jbe@32: } jbe@32: jbe@30: static int seqlua_ipairsaux_index(lua_State *L) { jbe@30: lua_Integer 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@32: return lua_isnil(L, -1) ? 1 : 2; jbe@0: } jbe@0: jbe@30: static int seqlua_ipairsaux_call(lua_State *L) { jbe@0: lua_pushinteger(L, luaL_checkinteger(L, 2) + 1); jbe@30: lua_insert(L, 1); // integer on stack index 1 jbe@30: lua_settop(L, 2); // function on stack index 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@30: if (luaL_getmetafield(L, 1, "__ipairs")) { jbe@30: lua_pushvalue(L, 1); 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: lua_pushcfunction(L, seqlua_ipairsaux_raw); jbe@35: } else if (!strcmp(method, "index")) { jbe@35: lua_pushcfunction(L, seqlua_ipairsaux_index); jbe@35: } else if (!strcmp(method, "call")) { jbe@35: lua_pushcfunction(L, seqlua_ipairsaux_call); jbe@35: } else { jbe@35: luaL_error(L, "Unexpected string returned by __ipairs metamethod"); jbe@35: } jbe@35: lua_pushvalue(L, -3); jbe@35: lua_pushinteger(L, 0); jbe@35: } jbe@0: } else { jbe@30: int t = lua_type(L, 1); jbe@30: if (t == LUA_TFUNCTION) { jbe@54: lua_pushcfunction(L, seqlua_ipairsaux_call); jbe@32: } else if (luaL_getmetafield(L, 1, "__index")) { jbe@32: lua_pushcfunction(L, seqlua_ipairsaux_index); jbe@54: } else { jbe@54: luaL_checktype(L, 1, LUA_TTABLE); jbe@54: lua_pushcfunction(L, seqlua_ipairsaux_raw); jbe@30: } jbe@30: lua_pushvalue(L, 1); jbe@30: lua_pushinteger(L, 0); jbe@0: } jbe@0: return 3; jbe@0: } jbe@0: jbe@25: static int seqlua_concat(lua_State *L) { jbe@25: const char *sep; jbe@25: size_t seplen; jbe@25: luaL_Buffer buf; jbe@25: seqlua_Iterator iter; jbe@25: sep = luaL_checklstring(L, 1, &seplen); jbe@25: luaL_checkany(L, 2); jbe@25: lua_settop(L, 3); jbe@25: luaL_buffinit(L, &buf); jbe@54: seqlua_iterloop(L, &iter, 2) { jbe@25: lua_replace(L, 3); jbe@25: if (seqlua_itercount(&iter) > 1) luaL_addlstring(&buf, sep, seplen); jbe@25: luaL_tolstring(L, 3, NULL); jbe@25: luaL_addvalue(&buf); jbe@25: } jbe@25: luaL_pushresult(&buf); jbe@25: return 1; jbe@25: } jbe@25: jbe@0: int luaopen_seqlua(lua_State *L) { jbe@0: lua_pushcfunction(L, seqlua_ipairs); jbe@0: lua_setglobal(L, "ipairs"); jbe@25: lua_getglobal(L, "string"); jbe@25: lua_pushcfunction(L, seqlua_concat); jbe@25: lua_setfield(L, -2, "concat"); jbe@25: return 0; jbe@0: }