# HG changeset patch # User jbe # Date 1406493772 -7200 # Node ID a1507b499fa52bbfc93fee42c0a212d44326c387 # Parent 214e11b729078aac3c4c963fe3bf8b611161e044 Implemented ipairs metamethod for sparse JSON arrays diff -r 214e11b72907 -r a1507b499fa5 libraries/json/json.c --- a/libraries/json/json.c Sun Jul 27 22:10:28 2014 +0200 +++ b/libraries/json/json.c Sun Jul 27 22:42:52 2014 +0200 @@ -7,6 +7,7 @@ #define JSON_UPVAL_SHADOWTBL lua_upvalueindex(2) #define JSON_UPVAL_TYPES lua_upvalueindex(3) #define JSON_UPVAL_METATABLE lua_upvalueindex(4) +#define JSON_UPVAL_IPAIRS_ITERFUNC lua_upvalueindex(5) #define JSON_STATE_VALUE 0 #define JSON_STATE_OBJECT_KEY 1 @@ -354,6 +355,28 @@ return 1; } +static int json_ipairs_iterfunc(lua_State *L) { + int idx; + lua_settop(L, 2); + idx = lua_tointeger(L, 2) + 1; + lua_pushvalue(L, 1); + lua_rawget(L, JSON_UPVAL_SHADOWTBL); + if (lua_isnil(L, -1)) return luaL_error(L, "Shadow table not found"); + lua_rawgeti(L, -1, idx); + if (lua_isnil(L, -1)) return 0; + lua_pushinteger(L, idx); + if (lua_rawequal(L, -2, JSON_UPVAL_NULLMARK)) lua_pushnil(L); + else lua_pushvalue(L, -2); + return 2; +} + +static int json_ipairs(lua_State *L) { + lua_pushvalue(L, JSON_UPVAL_IPAIRS_ITERFUNC); + lua_pushvalue(L, 1); + lua_pushinteger(L, 0); + return 3; +} + static const struct luaL_Reg json_module_functions[] = { {"object", json_object}, {"array", json_array}, @@ -369,6 +392,7 @@ {"__len", json_len}, {"__index", json_index}, {"__newindex", json_newindex}, + {"__ipairs", json_ipairs}, {NULL, NULL} }; @@ -392,7 +416,15 @@ lua_pushvalue(L, 3); lua_pushvalue(L, 4); lua_pushvalue(L, 5); - luaL_setfuncs(L, json_metatable_functions, 4); - luaL_setfuncs(L, json_module_functions, 4); + lua_pushcclosure(L, json_ipairs_iterfunc, 4); // 6: iteration function for ipairs + lua_pushvalue(L, 5); + lua_pushvalue(L, 2); + lua_pushvalue(L, 3); + lua_pushvalue(L, 4); + lua_pushvalue(L, 5); + lua_pushvalue(L, 6); + luaL_setfuncs(L, json_metatable_functions, 5); + lua_pop(L, 1); + luaL_setfuncs(L, json_module_functions, 5); return 1; }