I miserably fail to convert nested Lua table into C json object. I'm using LuaTableToJson (see code here after) where "index" is the parameter index to retrieve and PopOneArg the routine to process a value depending on its type.
When having a nested table I would like to call LuaTableToJson recursively, but with index=-1 it does not work.
Question: could please someone point on working sample to retreive nested table passed as argument from Lua to C. Alternatively could someone explain the stack structure when passing nested table from Lua to C.
Thank you
Note: for C->Lua I have a solution.
STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
int idx;
json_object *tableJ= json_object_new_object();
const char *key;
char number[3];
lua_pushnil(luaState); // 1st key
for (idx=1; lua_next(luaState, index) != 0; idx++) {
// uses 'key' (at index -2) and 'value' (at index -1)
if (lua_type(luaState,-2) == LUA_TSTRING) key= lua_tostring(luaState, -2);
else {
snprintf(number, sizeof(number),"%d", idx);
key=number;
}
json_object *argJ= PopOneArg(luaState, -1);
json_object_object_add(tableJ, key, argJ);
lua_pop(luaState, 1); // removes 'value'; keeps 'key' for next iteration
}
// Query is empty free empty json object
if (idx == 1) {
json_object_put(tableJ);
return NULL;
}
return tableJ;
}
STATIC json_object *PopOneArg (lua_State* luaState, int idx) {
json_object *value=NULL;
int luaType = lua_type(luaState, idx);
switch(luaType) {
case LUA_TNUMBER: {
lua_Number number= lua_tonumber(luaState, idx);;
int nombre = (int)number; // evil trick to determine wether n fits in an integer. (stolen from ltcl.c)
if (number == nombre) {
value= json_object_new_int((int)number);
} else {
value= json_object_new_double(number);
}
break;
}
case LUA_TBOOLEAN:
value= json_object_new_boolean(lua_toboolean(luaState, idx));
break;
case LUA_TSTRING:
value= json_object_new_string(lua_tostring(luaState, idx));
break;
case LUA_TTABLE: {
if (idx > 0) {
value= LuaTableToJson(luaState, idx);
} else {
value= json_object_new_string("UNSUPPORTED_Lua_Nested_Table");
}
break;
}
case LUA_TNIL:
value=json_object_new_string("nil") ;
break;
default:
AFB_NOTICE ("PopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType));
value=NULL;
}
return value;
}
static json_object *LuaPopArgs (lua_State* luaState, int start) {
json_object *responseJ;
int stop = lua_gettop(luaState);
if(stop-start <0) return NULL;
// start at 2 because we are using a function array lib
if (start == stop) {
responseJ=PopOneArg (luaState, start);
} else {
// loop on remaining return arguments
responseJ= json_object_new_array();
for (int idx=start; idx <= stop; idx++) {
json_object *argJ=PopOneArg (luaState, idx);
if (!argJ) goto OnErrorExit;
json_object_array_add(responseJ, argJ);
}
}
return responseJ;
OnErrorExit:
return NULL;
}