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"
37 struct json_object *obj;
38 struct json_tokener *tok;
39 enum json_tokener_error err;
42 static void _json_to_lua(lua_State *L, struct json_object *obj);
43 static struct json_object * _lua_to_json(lua_State *L, int index);
44 static struct json_object * _lua_to_json_rec(lua_State *L, int index, struct seen **seen);
46 static int json_new(lua_State *L)
49 struct json_tokener *tok = json_tokener_new();
54 s = lua_newuserdata(L, sizeof(*s));
58 json_tokener_free(tok);
64 s->err = json_tokener_continue;
66 luaL_getmetatable(L, LUCI_JSONC_PARSER);
67 lua_setmetatable(L, -2);
72 static int json_parse(lua_State *L)
75 const char *json = luaL_checklstring(L, 1, &len);
76 struct json_state s = {
77 .tok = json_tokener_new()
83 s.obj = json_tokener_parse_ex(s.tok, json, len);
84 s.err = json_tokener_get_error(s.tok);
88 _json_to_lua(L, s.obj);
89 json_object_put(s.obj);
96 if (s.err == json_tokener_continue)
97 s.err = json_tokener_error_parse_eof;
100 lua_pushstring(L, json_tokener_error_desc(s.err));
102 json_tokener_free(s.tok);
103 return (1 + !!s.err);
106 static int json_stringify(lua_State *L)
108 struct json_object *obj = _lua_to_json(L, 1);
109 bool pretty = lua_toboolean(L, 2);
113 flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
115 lua_pushstring(L, json_object_to_json_string_ext(obj, flags));
116 json_object_put(obj);
121 static int json_parse_chunk(lua_State *L)
124 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
125 const char *chunk = luaL_checklstring(L, 2, &len);
127 s->obj = json_tokener_parse_ex(s->tok, chunk, len);
128 s->err = json_tokener_get_error(s->tok);
132 lua_pushboolean(L, true);
135 else if (s->err == json_tokener_continue)
137 lua_pushboolean(L, false);
142 lua_pushstring(L, json_tokener_error_desc(s->err));
146 static void _json_to_lua(lua_State *L, struct json_object *obj)
150 switch (json_object_get_type(obj))
152 case json_type_object:
154 json_object_object_foreach(obj, key, val)
156 _json_to_lua(L, val);
157 lua_setfield(L, -2, key);
161 case json_type_array:
163 for (n = 0; n < json_object_array_length(obj); n++)
165 _json_to_lua(L, json_object_array_get_idx(obj, n));
166 lua_rawseti(L, -2, n + 1);
170 case json_type_boolean:
171 lua_pushboolean(L, json_object_get_boolean(obj));
175 lua_pushinteger(L, json_object_get_int(obj));
178 case json_type_double:
179 lua_pushnumber(L, json_object_get_double(obj));
182 case json_type_string:
183 lua_pushstring(L, json_object_get_string(obj));
192 static int json_parse_get(lua_State *L)
194 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
196 if (!s->obj || s->err)
199 _json_to_lua(L, s->obj);
204 static int _lua_test_array(lua_State *L, int index)
209 if (!lua_checkstack(L, 2))
214 /* check for non-integer keys */
215 while (lua_next(L, index))
217 if (lua_type(L, -2) != LUA_TNUMBER)
220 idx = lua_tonumber(L, -2);
222 if (idx != (lua_Number)(lua_Integer)idx)
239 /* check for holes */
240 //for (i = 1; i <= max; i++)
242 // lua_rawgeti(L, index, i);
244 // if (lua_isnil(L, -1))
257 static bool visited(struct seen **sp, const void *ptr) {
258 struct seen *s = *sp;
261 if (s->len >= s->size)
264 s = realloc(*sp, sizeof(struct seen) + sizeof(void *) * i);
279 for (i = 0; i < s->len; i++)
280 if (s->ptrs[i] == ptr)
283 s->ptrs[s->len++] = ptr;
287 static struct json_object * _lua_to_json_rec(lua_State *L, int index,
291 struct json_object *obj;
296 index = lua_gettop(L) + index + 1;
298 switch (lua_type(L, index))
301 if (visited(seen, lua_topointer(L, index)))
304 max = _lua_test_array(L, index);
308 obj = json_object_new_array();
313 if (!lua_checkstack(L, 1))
316 for (i = 1; i <= max; i++)
318 lua_rawgeti(L, index, i);
320 json_object_array_put_idx(obj, i - 1,
321 _lua_to_json_rec(L, -1, seen));
329 obj = json_object_new_object();
334 if (!lua_checkstack(L, 3))
339 while (lua_next(L, index))
341 lua_pushvalue(L, -2);
342 key = lua_tostring(L, -1);
345 json_object_object_add(obj, key,
346 _lua_to_json_rec(L, -2, seen));
357 return json_object_new_boolean(lua_toboolean(L, index));
360 nd = lua_tonumber(L, index);
361 ni = lua_tointeger(L, index);
364 return json_object_new_int(nd);
366 return json_object_new_double(nd);
369 return json_object_new_string(lua_tostring(L, index));
375 static struct json_object * _lua_to_json(lua_State *L, int index)
377 struct seen *s = calloc(sizeof(struct seen) + sizeof(void *) * 10, 1);
378 struct json_object *rv;
385 rv = _lua_to_json_rec(L, index, &s);
392 static int json_parse_set(lua_State *L)
394 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
397 s->obj = _lua_to_json(L, 2);
402 static int json_parse_sink_closure(lua_State *L)
404 bool finished = lua_toboolean(L, lua_upvalueindex(2));
407 // no more data available
410 // we were finished parsing
411 lua_pushboolean(L, true);
417 lua_pushstring(L, "Incomplete JSON data");
426 lua_pushstring(L, "Unexpected data after complete JSON object");
431 // luci.jsonc.parser.chunk()
432 lua_pushcfunction(L, json_parse_chunk);
433 // parser object from closure
434 lua_pushvalue(L, lua_upvalueindex(1));
439 if (lua_isnil(L, -2))
441 // an error occurred, leave (nil, errmsg) on the stack and return it
444 else if (lua_toboolean(L, -2))
446 // finished reading, set finished=true and return nil to prevent further input
448 lua_pushboolean(L, true);
449 lua_replace(L, lua_upvalueindex(2));
455 // not finished reading, return true
457 lua_pushboolean(L, true);
464 static int json_parse_sink(lua_State *L)
466 luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
467 lua_pushboolean(L, false);
468 lua_pushcclosure(L, json_parse_sink_closure, 2);
472 static int json_tostring(lua_State *L)
474 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
475 bool pretty = lua_toboolean(L, 2);
479 flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
481 lua_pushstring(L, json_object_to_json_string_ext(s->obj, flags));
485 static int json_gc(lua_State *L)
487 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
490 json_object_put(s->obj);
493 json_tokener_free(s->tok);
499 static const luaL_reg jsonc_methods[] = {
501 { "parse", json_parse },
502 { "stringify", json_stringify },
507 static const luaL_reg jsonc_parser_methods[] = {
508 { "parse", json_parse_chunk },
509 { "get", json_parse_get },
510 { "set", json_parse_set },
511 { "sink", json_parse_sink },
512 { "stringify", json_tostring },
515 { "__tostring", json_tostring },
521 int luaopen_luci_jsonc(lua_State *L)
523 luaL_register(L, LUCI_JSONC, jsonc_methods);
525 luaL_newmetatable(L, LUCI_JSONC_PARSER);
526 luaL_register(L, NULL, jsonc_parser_methods);
527 lua_pushvalue(L, -1);
528 lua_setfield(L, -2, "__index");