2

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)

http://pastebin.com/Y4540Wss

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.)

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
Chrismit
  • 1,488
  • 14
  • 23

1 Answers1

1

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.

Tom Blodget
  • 20,260
  • 3
  • 39
  • 72
  • 1
    Use `lua_getglobal` instead of `lua_getfield`. – lhf Jun 20 '13 at 21:19
  • @lhf Okay, thanks. And I see that LUA_ENVIRONINDEX has been removed as of Lua 5.2. – Tom Blodget Jun 20 '13 at 21:28
  • Still doesn't work. It may be the difference, but one of the tables' keys is actually another table. Everything works fine when I don't have a table with a table key. I'm not sure how to recapitulate this within lua2c, since the table may not have a reference like f = {}; a[f] = {}. It's done like a[{}] = {}, so I have to use luaL_ref to get the table's key on the stack. – Chrismit Jun 20 '13 at 22:12