#include "table.hpp" #include "source.hpp" LuaDefine(table_equal, "c") { LuaArg t1, t2; LuaRet eql; LuaStack LS(L, t1, t2, eql); LS.checktable(t1); LS.checktable(t2); lua_pushnil(L); int total1 = 0; while (lua_next(L, t1.index()) != 0) { lua_pushvalue(L, -2); // k v1 k lua_rawget(L, t2.index()); // k v1 v2 if (!lua_equal(L, -1, -2)) { LS.set(eql, false); return LS.result(); } lua_pop(L, 2); total1 += 1; } int total2 = 0; lua_pushnil(L); while (lua_next(L, t2.index()) != 0) { lua_pop(L, 1); total2 += 1; } LS.set(eql, total1 == total2); return LS.result(); } LuaDefine(table_findremove, "c") { luaL_checktype(L, -2, LUA_TTABLE); int src = 1; int dst = 1; while (true) { lua_pushinteger(L, src); lua_rawget(L, -3); if (lua_equal(L, -1, -2)) { src++; lua_pop(L, 1); } else if (lua_isnil(L, -1)) { lua_pop(L, 1); int removed = src - dst; while (src > dst) { lua_pushinteger(L, dst); lua_pushnil(L); lua_rawset(L, -4); dst++; } lua_pop(L, 2); lua_pushinteger(L, removed); return 1; } else { if (src > dst) { lua_pushinteger(L, dst); lua_insert(L, lua_gettop(L) - 1); lua_rawset(L, -4); } else { lua_pop(L, 1); } src++; dst++; } } } LuaDefine(table_push, "c") { luaL_checktype(L, -2, LUA_TTABLE); int len = lua_objlen(L, -2); lua_pushinteger(L, len+1); lua_pushvalue(L, -2); lua_rawset(L, -4); lua_pop(L, 2); return 0; } LuaDefine(table_find, "c") { luaL_checktype(L, -2, LUA_TTABLE); for (int i = 1; ; i++) { lua_pushinteger(L, i); lua_rawget(L, -3); if (lua_equal(L, -1, -2)) { lua_pop(L, 3); lua_pushinteger(L, i); return 1; } else if (lua_isnil(L, -1)) { lua_pop(L, 3); lua_pushnil(L); return 1; } else { lua_pop(L, 1); } } } LuaDefine(table_empty, "c") { luaL_checktype(L, -1, LUA_TTABLE); lua_pushnil(L); if (lua_next(L, -2) != 0) { lua_pop(L, 3); lua_pushboolean(L, 0); return 1; } else { lua_pop(L, 1); lua_pushboolean(L, 1); return 1; } } LuaDefine(table_count, "c") { luaL_checktype(L, -1, LUA_TTABLE); lua_pushnil(L); lua_Integer total = 0; while (lua_next(L, -2) != 0) { total += 1; lua_pop(L, 1); } lua_pop(L, 1); lua_pushinteger(L, total); return 1; } LuaDefine(table_clear, "c") { LuaArg tab; LuaStack LS(L, tab); LS.checktable(tab); lua_pushnil(L); while (lua_next(L, tab.index()) != 0) { lua_pop(L, 1); // Pop the old value. lua_pushvalue(L, -1); // Clone the key lua_pushnil(L); // Push the new value. lua_settable(L, tab.index()); } return LS.result(); } LuaDefine(queue_create, "c") { LuaRet queue; LuaStack LS(L, queue); LS.newtable(queue); LS.setfield(queue, "head", 1000000); LS.setfield(queue, "tail", 1000000); return LS.result(); } LuaDefine(queue_push, "c") { LuaArg queue, elt; lua_Integer head; LuaStack LS(L, queue, elt); LS.getfield(head, queue, "head"); LS.rawset(queue, head, elt); LS.setfield(queue, "head", head+1); return LS.result(); } LuaDefine(queue_pop, "c") { LuaArg queue; LuaRet elt; lua_Integer head, tail; LuaStack LS(L, queue, elt); LS.getfield(tail, queue, "tail"); LS.getfield(head, queue, "head"); if (head == tail) { LS.set(elt, LuaNil); } else { LS.rawget(elt, queue, tail); LS.rawset(queue, tail, LuaNil); LS.setfield(queue, "tail", tail + 1); } return LS.result(); } LuaDefine(queue_size, "c") { LuaArg queue; LuaRet size; lua_Number head, tail; LuaStack LS(L, queue, size); LS.getfield(head, queue, "head"); LS.getfield(tail, queue, "tail"); LS.set(size, head - tail); return LS.result(); } LuaDefine(queue_nth, "c") { LuaArg queue, n; LuaRet elt; lua_Integer nth, head, tail; LuaStack LS(L, queue, n, elt); nth = LS.ckinteger(n) - 1; LS.getfield(head, queue, "head"); LS.getfield(tail, queue, "tail"); if ((nth < 0) || (nth + tail >= head)) { luaL_error(L, "index out of range"); } LS.rawget(elt, queue, tail + nth); return LS.result(); } LuaDefine(table_getregistry, "f") { LuaArg key; LuaRet result; LuaStack LS(L, key, result); LS.rawget(result, LuaRegistry, key); return LS.result(); }