2 Copyright 2015 Jo-Philipp Wich <jow@openwrt.org>
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
21 #include <json-c/json.h>
27 #define LUCI_JSONC "luci.jsonc"
28 #define LUCI_JSONC_PARSER "luci.jsonc.parser"
31 struct json_object *obj;
32 struct json_tokener *tok;
33 enum json_tokener_error err;
36 static void _json_to_lua(lua_State *L, struct json_object *obj);
37 static struct json_object * _lua_to_json(lua_State *L, int index);
39 static int json_new(lua_State *L)
42 struct json_tokener *tok = json_tokener_new();
47 s = lua_newuserdata(L, sizeof(*s));
51 json_tokener_free(tok);
57 s->err = json_tokener_continue;
59 luaL_getmetatable(L, LUCI_JSONC_PARSER);
60 lua_setmetatable(L, -2);
65 static int json_parse(lua_State *L)
68 const char *json = luaL_checklstring(L, 1, &len);
69 struct json_state s = {
70 .tok = json_tokener_new()
76 s.obj = json_tokener_parse_ex(s.tok, json, len);
77 s.err = json_tokener_get_error(s.tok);
81 _json_to_lua(L, s.obj);
82 json_object_put(s.obj);
89 if (s.err == json_tokener_continue)
90 s.err = json_tokener_error_parse_eof;
93 lua_pushstring(L, json_tokener_error_desc(s.err));
95 json_tokener_free(s.tok);
99 static int json_stringify(lua_State *L)
101 struct json_object *obj = _lua_to_json(L, 1);
102 bool pretty = lua_toboolean(L, 2);
106 flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
108 lua_pushstring(L, json_object_to_json_string_ext(obj, flags));
109 json_object_put(obj);
114 static int json_parse_chunk(lua_State *L)
117 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
118 const char *chunk = luaL_checklstring(L, 2, &len);
120 s->obj = json_tokener_parse_ex(s->tok, chunk, len);
121 s->err = json_tokener_get_error(s->tok);
125 lua_pushboolean(L, true);
128 else if (s->err == json_tokener_continue)
130 lua_pushboolean(L, false);
135 lua_pushstring(L, json_tokener_error_desc(s->err));
139 static void _json_to_lua(lua_State *L, struct json_object *obj)
143 switch (json_object_get_type(obj))
145 case json_type_object:
147 json_object_object_foreach(obj, key, val)
149 _json_to_lua(L, val);
150 lua_setfield(L, -2, key);
154 case json_type_array:
156 for (n = 0; n < json_object_array_length(obj); n++)
158 _json_to_lua(L, json_object_array_get_idx(obj, n));
159 lua_rawseti(L, -2, n + 1);
163 case json_type_boolean:
164 lua_pushboolean(L, json_object_get_boolean(obj));
168 lua_pushinteger(L, json_object_get_int(obj));
171 case json_type_double:
172 lua_pushnumber(L, json_object_get_double(obj));
175 case json_type_string:
176 lua_pushstring(L, json_object_get_string(obj));
185 static int json_parse_get(lua_State *L)
187 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
189 if (!s->obj || s->err)
192 _json_to_lua(L, s->obj);
197 static int _lua_test_array(lua_State *L, int index)
204 /* check for non-integer keys */
205 while (lua_next(L, index))
207 if (lua_type(L, -2) != LUA_TNUMBER)
210 idx = lua_tonumber(L, -2);
212 if (idx != (lua_Number)(lua_Integer)idx)
229 /* check for holes */
230 //for (i = 1; i <= max; i++)
232 // lua_rawgeti(L, index, i);
234 // if (lua_isnil(L, -1))
246 static struct json_object * _lua_to_json(lua_State *L, int index)
249 struct json_object *obj;
253 switch (lua_type(L, index))
256 max = _lua_test_array(L, index);
260 obj = json_object_new_array();
265 for (i = 1; i <= max; i++)
267 lua_rawgeti(L, index, i);
269 json_object_array_put_idx(obj, i - 1,
270 _lua_to_json(L, lua_gettop(L)));
278 obj = json_object_new_object();
285 while (lua_next(L, index))
287 lua_pushvalue(L, -2);
288 key = lua_tostring(L, -1);
291 json_object_object_add(obj, key,
292 _lua_to_json(L, lua_gettop(L) - 1));
303 return json_object_new_boolean(lua_toboolean(L, index));
306 nd = lua_tonumber(L, index);
307 ni = lua_tointeger(L, index);
310 return json_object_new_int(nd);
312 return json_object_new_double(nd);
315 return json_object_new_string(lua_tostring(L, index));
321 static int json_parse_set(lua_State *L)
323 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
326 s->obj = _lua_to_json(L, 2);
331 static int json_parse_sink_closure(lua_State *L)
333 bool finished = lua_toboolean(L, lua_upvalueindex(2));
336 // no more data available
339 // we were finished parsing
340 lua_pushboolean(L, true);
346 lua_pushstring(L, "Incomplete JSON data");
355 lua_pushstring(L, "Unexpected data after complete JSON object");
360 // luci.jsonc.parser.chunk()
361 lua_pushcfunction(L, json_parse_chunk);
362 // parser object from closure
363 lua_pushvalue(L, lua_upvalueindex(1));
368 if (lua_isnil(L, -2))
370 // an error occurred, leave (nil, errmsg) on the stack and return it
373 else if (lua_toboolean(L, -2))
375 // finished reading, set finished=true and return nil to prevent further input
377 lua_pushboolean(L, true);
378 lua_replace(L, lua_upvalueindex(2));
384 // not finished reading, return true
386 lua_pushboolean(L, true);
393 static int json_parse_sink(lua_State *L)
395 luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
396 lua_pushboolean(L, false);
397 lua_pushcclosure(L, json_parse_sink_closure, 2);
401 static int json_tostring(lua_State *L)
403 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
404 bool pretty = lua_toboolean(L, 2);
408 flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
410 lua_pushstring(L, json_object_to_json_string_ext(s->obj, flags));
414 static int json_gc(lua_State *L)
416 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
419 json_object_put(s->obj);
422 json_tokener_free(s->tok);
428 static const luaL_reg jsonc_methods[] = {
430 { "parse", json_parse },
431 { "stringify", json_stringify },
436 static const luaL_reg jsonc_parser_methods[] = {
437 { "parse", json_parse_chunk },
438 { "get", json_parse_get },
439 { "set", json_parse_set },
440 { "sink", json_parse_sink },
441 { "stringify", json_tostring },
444 { "__tostring", json_tostring },
450 int luaopen_luci_jsonc(lua_State *L)
452 luaL_register(L, LUCI_JSONC, jsonc_methods);
454 luaL_newmetatable(L, LUCI_JSONC_PARSER);
455 luaL_register(L, NULL, jsonc_parser_methods);
456 lua_pushvalue(L, -1);
457 lua_setfield(L, -2, "__index");