diff options
-rw-r--r-- | libraries/json.c | 141 |
1 files changed, 79 insertions, 62 deletions
diff --git a/libraries/json.c b/libraries/json.c index f725728..14b006f 100644 --- a/libraries/json.c +++ b/libraries/json.c @@ -1,34 +1,40 @@ #include "cJSON.h" #include "cJSON.c" +typedef struct json_t { + int allocated; + cJSON* json; +} json_t; + static cJSON* lua_tocjson(lua_State* L, int index) { - return *(cJSON*)lua_touserdata(L, index); + json_t* value = luaL_testudata(L, index, "cjson"); + return value ? value->json : NULL; } // Lua binidngs. -static void f_cjson_push(lua_State* L, cJSON* json, int value) { - if (json) { - switch (json->type) { - case cJSON_Array: - case cJSON_Object: { - cJSON** value = lua_newuserdata(L, sizeof(cJSON*)); - luaL_setmetatable(L, value ? "cjson_value" : "cjson_object"); - *value = *json; - } break; - case cJSON_Number: lua_pushnumber(L, cJSON_GetNumberValue(json)); break; - case cJSON_True: lua_pushboolean(L, 1); break; - case cJSON_False: lua_pushboolean(L, 0); break; - case cJSON_String: lua_pushstring(L, cJSON_GetStringValue(json)); break; - default: lua_pushnil(L); break; - } - } else - lua_pushnil(L); +static int f_cjson_push(lua_State* L, cJSON* json, int allocated) { + if (json) { + switch (json->type) { + case cJSON_Array: + case cJSON_Object: { + json_t* value = lua_newuserdata(L, sizeof(json_t)); + luaL_setmetatable(L, "cjson"); + value->json = json; + value->allocated = allocated; + } break; + case cJSON_Number: lua_pushnumber(L, cJSON_GetNumberValue(json)); break; + case cJSON_True: lua_pushboolean(L, 1); break; + case cJSON_False: lua_pushboolean(L, 0); break; + case cJSON_String: lua_pushstring(L, cJSON_GetStringValue(json)); break; + default: lua_pushnil(L); break; + } + } else + lua_pushnil(L); + return 1; } static cJSON* f_cjson_parse(lua_State* L, int index) { switch (lua_type(L, index)) { - case LUA_TUSERDATA: - return lua_tocjson(L, index); case LUA_TTABLE: lua_len(L, index); int length = lua_tointeger(L, -1); @@ -56,19 +62,24 @@ static cJSON* f_cjson_parse(lua_State* L, int index) { } break; case LUA_TBOOLEN: return lua_toboolean(L, index) ? cJSON_CreateTrue() : cJSON_CreateFalse(); - case LUA_TSTRING: return cJSON_CreateString(lua_tostring(L, index)); break; - case LUA_TINTEGER: return cJSON_CreateNumber(lua_tointeger(L, index)); break; - case LUA_TNUMBER: return cJSON_CreateNumber(lua_tonumber(L, index)); break; - default: return cJSON_CreateNull(); break; + case LUA_TSTRING: return cJSON_CreateString(lua_tostring(L, index)); + case LUA_TINTEGER: return cJSON_CreateNumber(lua_tointeger(L, index)); + case LUA_TNUMBER: return cJSON_CreateNumber(lua_tonumber(L, index)); + case LUA_TUSERDATA: { + cJSON* json = lua_tocjson(L, index); + return json ? json : cJSON_CreateNull(); + } break; + default: return cJSON_CreateNull(); } } -static int f_cjson_object_gc(lua_State* L) { - cJSON* json = lua_tocjson(L, 1); - cJSON_Delete(json); +static int f_cjson_gc(lua_State* L) { + json_t* value = lua_touserdata(L, 1); + if (value->allocated) + cJSON_Delete(value->json); } -static int f_cjson_object_index(lua_State* L) { +static int f_cjson_index(lua_State* L) { cJSON* json = lua_tocjson(L, 1); switch (json->type) { case cJSON_Object: f_cjson_push(L, cJSON_GetObjectItem(json, luaL_checkstring(L, 2)), 1); break; @@ -78,7 +89,7 @@ static int f_cjson_object_index(lua_State* L) { return 1; } -static int f_cjson_object_len(lua_State* L) { +static int f_cjson_len(lua_State* L) { cJSON* json = lua_tocjson(L, 1); switch (json->type) { case cJSON_Array: lua_pushinteger(L, cJSON_GetArraySize(json->length)); break; @@ -87,56 +98,62 @@ static int f_cjson_object_len(lua_State* L) { return 1; } +static int f_cjson_newindex(lua_State* L) { + cJSON* json = lua_tocjson(L, 1); + + switch (json->type) { + case cJSON_Array: { + int index = luaL_checkinteger(L, 2); + cJSON* value = f_cjson_parse(L, 3); + cJSON_ReplaceItemInArray(json, index, value); + } break; + case cJSON_Object: { + const char* key = luaL_checkstring(L, 2); + cJSON* value = f_cjson_parse(L, 3); + cJSON_AddItemToObject(json, key, value); + } break; + default: return luaL_error(L, "assignment operation invalid"); + } + return 0; +} -static const luaL_Reg cjson_value[] = { - { "__index", f_cjson_object_index }, - { "__newindex", f_cjson_object_newindex }, - { "__pairs", f_cjson_object_pairs }, - { "__len", f_cjson_object_len }, - { NULL, NULL } -}; -static const luaL_Reg cjson_object[] = { - { "__gc", f_cjson_object_gc }, - { "__index", f_cjson_object_index }, - { "__newindex", f_cjson_object_newindex }, - { "__pairs", f_cjson_object_pairs }, - { "__len", f_cjson_object_len }, - { NULL, NULL } +static const luaL_Reg cjson_value[] = { + { "__gc", f_cjson_gc }, + { "__index", f_cjson_index }, + { "__newindex", f_cjson_newindex }, + { "__pairs", f_cjson_pairs }, + { "__len", f_cjson_len }, + { NULL, NULL } }; static int f_cjson_encode(lua_State* L) { - cJSON* json = lua_tocjson(L, 1); - char* str = cJSON_PrintUnformatted(json); - lua_pushstring(L, str); - free(str); - return 1; + cJSON* json = lua_tocjson(L, 1); + char* str = cJSON_PrintUnformatted(json); + lua_pushstring(L, str); + free(str); + return 1; } static int f_cjson_decode(lua_State* L) { - size_t len; - const char* str = luaL_checklstring(L, 1, &len); - cJSON* value = cJSON_ParseWithLength(str, len); - cJSON** data = lua_newuserdata(L, sizeof(cJSON*)); - luaL_setmetatable(L, "cjson_object"); - *data = value; - return 1; + size_t len; + const char* str = luaL_checklstring(L, 1, &len); + return f_cjson_push(L, cJSON_ParseWithLength(str, len), 1); } + #ifndef CJSON_STANDALONE int luaopen_lite_xl_cjson(lua_State* L, void* XL) { lite_xl_plugin_init(XL); #else int luaopen_cjson(lua_State* L) { #endif - luaL_newmetatable(L, "cjson_object"); - luaL_setfuncs(L, cjson_object, 0); - luaL_newmetatable(L, "cjson_value"); - luaL_setfuncs(L, cjson_value, 0); - lua_newtable(L); - luaL_setfuncs(L, cjson_lib, 0); - return 1; + luaL_newmetatable(L, "cjson"); + luaL_setfuncs(L, cjson_value, 0); + lua_newtable(L); + luaL_setfuncs(L, cjson_lib, 0); + return 1; } |