Reputation: 1518
I'm attempting to move a table to another table using the lua C api. For instance, I have a table with this structure:
a[b][c][d][e] = value
I want to move table d this to be under a[b], which I could accomplish in Lua like:
a[b][d] = a[b][c][d]
a[b][c][d] = nil
My current approach is to load on the stack the a[b][c][d] table, so the stack looks like:
Index Value
-1 d table
-2 c table
-3 b table
-4 a table
Then load a[b] onto the stack, so it looks like:
Index Value
-1 b table
-2 a table
-3 d table
-4 c table
-5 b table
-6 a table
Then put d's key onto the stack, and insert d's key and table b under table d, so the stack is:
Index Value
-1 d table
-2 d key
-3 b table
-4 a table
-5 c table
-6 b table
-7 a table
Then I use lua_settable(L, -3), to do b[d] = d.
This approach works for non-table keys, but fails for keys which are tables. So it will fail for something like:
a[b][c][{}][d] = value
a[b] = a[b][c][{}][d]
Note, I know in the above it will fail in the lua given above because the key would be a new lua table, I just wanted to illustrate it.
I've tried going down the table parents (so doing a[b] = b, lua_setglobal(L, a)) without any luck either. Does anyone know where I'm going wrong here?
Edit: A small code snippet on how I push keys/values onto the stack. The goal here is to move a table from one table structure to another (or as I call it in the code, reparent it)
Solution:
The issue was the table has some metatable function which prevented changes to the table (in essence, the person making the script had a config table where the structure was important, thus causing this issue.)
Upvotes: 2
Views: 955
Reputation: 20802
If I understand your description correctly, this Lua code does what you want:
local ab = a[b]
ab[d], ab[c][d] = ab[c][d], nil
As for implementing that in the Lua C API, lua2c is helpful with this machine translation:
enum { lc_nformalargs = 0 };
const int lc_nactualargs = lua_gettop(L);
const int lc_nextra = (lc_nactualargs - lc_nformalargs);
/* local ab = a[b] */
lua_getfield(L,LUA_ENVIRONINDEX,"a");
lua_getfield(L,LUA_ENVIRONINDEX,"b");
lua_gettable(L,-2);
lua_remove(L,-2);
assert(lua_gettop(L) - lc_nextra == 1);
/* ab[d], ab[c][d] = ab[c][d], nil */
lua_getfield(L,LUA_ENVIRONINDEX,"c");
lua_gettable(L,(1 + lc_nextra));
lua_getfield(L,LUA_ENVIRONINDEX,"d");
lua_gettable(L,-2);
lua_remove(L,-2);
lua_pushnil(L);
lua_getfield(L,LUA_ENVIRONINDEX,"c");
lua_gettable(L,(1 + lc_nextra));
lua_insert(L,-2);
lua_getfield(L,LUA_ENVIRONINDEX,"d");
lua_insert(L,-2);
lua_settable(L,-3);
lua_pop(L,1);
lua_getfield(L,LUA_ENVIRONINDEX,"d");
lua_insert(L,-2);
lua_settable(L,(1 + lc_nextra));
assert(lua_gettop(L) - lc_nextra == 1);
return 0;
I have yet to develop a readable way of writing stack operations.
Upvotes: 1