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.
22 #include <json-c/json.h>
28 #define LUCI_JSONC "luci.jsonc"
29 #define LUCI_JSONC_PARSER "luci.jsonc.parser"
38 struct json_object *obj;
39 struct json_tokener *tok;
40 enum json_tokener_error err;
43 static void _json_to_lua(lua_State *L, struct json_object *obj);
44 static struct json_object * _lua_to_json(lua_State *L, int index);
45 static struct json_object * _lua_to_json_rec(lua_State *L, int index, struct seen **seen);
47 static int json_new(lua_State *L)
50 struct json_tokener *tok = json_tokener_new();
55 s = lua_newuserdata(L, sizeof(*s));
59 json_tokener_free(tok);
65 s->err = json_tokener_continue;
67 luaL_getmetatable(L, LUCI_JSONC_PARSER);
68 lua_setmetatable(L, -2);
73 static int json_parse(lua_State *L)
76 const char *json = luaL_checklstring(L, 1, &len);
77 struct json_state s = {
78 .tok = json_tokener_new()
84 s.obj = json_tokener_parse_ex(s.tok, json, len);
85 s.err = json_tokener_get_error(s.tok);
89 _json_to_lua(L, s.obj);
90 json_object_put(s.obj);
97 if (s.err == json_tokener_continue)
98 s.err = json_tokener_error_parse_eof;
101 lua_pushstring(L, json_tokener_error_desc(s.err));
103 json_tokener_free(s.tok);
104 return (1 + !!s.err);
107 static int json_stringify(lua_State *L)
109 struct json_object *obj = _lua_to_json(L, 1);
110 bool pretty = lua_toboolean(L, 2);
114 flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
116 lua_pushstring(L, json_object_to_json_string_ext(obj, flags));
117 json_object_put(obj);
122 static int json_parse_chunk(lua_State *L)
125 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
126 const char *chunk = luaL_checklstring(L, 2, &len);
128 s->obj = json_tokener_parse_ex(s->tok, chunk, len);
129 s->err = json_tokener_get_error(s->tok);
133 lua_pushboolean(L, true);
136 else if (s->err == json_tokener_continue)
138 lua_pushboolean(L, false);
143 lua_pushstring(L, json_tokener_error_desc(s->err));
147 static void _json_to_lua(lua_State *L, struct json_object *obj)
152 switch (json_object_get_type(obj))
154 case json_type_object:
156 json_object_object_foreach(obj, key, val)
158 _json_to_lua(L, val);
159 lua_setfield(L, -2, key);
163 case json_type_array:
165 for (n = 0; n < json_object_array_length(obj); n++)
167 _json_to_lua(L, json_object_array_get_idx(obj, n));
168 lua_rawseti(L, -2, n + 1);
172 case json_type_boolean:
173 lua_pushboolean(L, json_object_get_boolean(obj));
177 v = json_object_get_int64(obj);
178 if (sizeof(lua_Integer) > sizeof(int32_t) ||
179 (v >= INT32_MIN && v <= INT32_MAX))
180 lua_pushinteger(L, (lua_Integer)v);
182 lua_pushnumber(L, (lua_Number)v);
185 case json_type_double:
186 lua_pushnumber(L, json_object_get_double(obj));
189 case json_type_string:
190 lua_pushstring(L, json_object_get_string(obj));
199 static int json_parse_get(lua_State *L)
201 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
203 if (!s->obj || s->err)
206 _json_to_lua(L, s->obj);
211 static int _lua_test_array(lua_State *L, int index)
216 if (!lua_checkstack(L, 2))
221 /* check for non-integer keys */
222 while (lua_next(L, index))
224 if (lua_type(L, -2) != LUA_TNUMBER)
227 idx = lua_tonumber(L, -2);
229 if (idx != (lua_Number)(lua_Integer)idx)
246 /* check for holes */
247 //for (i = 1; i <= max; i++)
249 // lua_rawgeti(L, index, i);
251 // if (lua_isnil(L, -1))
264 static bool visited(struct seen **sp, const void *ptr) {
265 struct seen *s = *sp;
268 if (s->len >= s->size)
271 s = realloc(*sp, sizeof(struct seen) + sizeof(void *) * i);
286 for (i = 0; i < s->len; i++)
287 if (s->ptrs[i] == ptr)
290 s->ptrs[s->len++] = ptr;
294 static struct json_object * _lua_to_json_rec(lua_State *L, int index,
298 struct json_object *obj;
303 index = lua_gettop(L) + index + 1;
305 switch (lua_type(L, index))
308 if (visited(seen, lua_topointer(L, index)))
311 max = _lua_test_array(L, index);
315 obj = json_object_new_array();
320 if (!lua_checkstack(L, 1))
323 for (i = 1; i <= max; i++)
325 lua_rawgeti(L, index, i);
327 json_object_array_put_idx(obj, i - 1,
328 _lua_to_json_rec(L, -1, seen));
336 obj = json_object_new_object();
341 if (!lua_checkstack(L, 3))
346 while (lua_next(L, index))
348 lua_pushvalue(L, -2);
349 key = lua_tostring(L, -1);
352 json_object_object_add(obj, key,
353 _lua_to_json_rec(L, -2, seen));
364 return json_object_new_boolean(lua_toboolean(L, index));
367 nd = lua_tonumber(L, index);
368 ni = lua_tointeger(L, index);
371 return json_object_new_int(nd);
373 return json_object_new_double(nd);
376 return json_object_new_string(lua_tostring(L, index));
382 static struct json_object * _lua_to_json(lua_State *L, int index)
384 struct seen *s = calloc(sizeof(struct seen) + sizeof(void *) * 10, 1);
385 struct json_object *rv;
392 rv = _lua_to_json_rec(L, index, &s);
399 static int json_parse_set(lua_State *L)
401 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
404 s->obj = _lua_to_json(L, 2);
409 static int json_parse_sink_closure(lua_State *L)
411 bool finished = lua_toboolean(L, lua_upvalueindex(2));
414 // no more data available
417 // we were finished parsing
418 lua_pushboolean(L, true);
424 lua_pushstring(L, "Incomplete JSON data");
433 lua_pushstring(L, "Unexpected data after complete JSON object");
438 // luci.jsonc.parser.chunk()
439 lua_pushcfunction(L, json_parse_chunk);
440 // parser object from closure
441 lua_pushvalue(L, lua_upvalueindex(1));
446 if (lua_isnil(L, -2))
448 // an error occurred, leave (nil, errmsg) on the stack and return it
451 else if (lua_toboolean(L, -2))
453 // finished reading, set finished=true and return nil to prevent further input
455 lua_pushboolean(L, true);
456 lua_replace(L, lua_upvalueindex(2));
462 // not finished reading, return true
464 lua_pushboolean(L, true);
471 static int json_parse_sink(lua_State *L)
473 luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
474 lua_pushboolean(L, false);
475 lua_pushcclosure(L, json_parse_sink_closure, 2);
479 static int json_tostring(lua_State *L)
481 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
482 bool pretty = lua_toboolean(L, 2);
486 flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
488 lua_pushstring(L, json_object_to_json_string_ext(s->obj, flags));
492 static int json_gc(lua_State *L)
494 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
497 json_object_put(s->obj);
500 json_tokener_free(s->tok);
506 static const luaL_reg jsonc_methods[] = {
508 { "parse", json_parse },
509 { "stringify", json_stringify },
514 static const luaL_reg jsonc_parser_methods[] = {
515 { "parse", json_parse_chunk },
516 { "get", json_parse_get },
517 { "set", json_parse_set },
518 { "sink", json_parse_sink },
519 { "stringify", json_tostring },
522 { "__tostring", json_tostring },
528 int luaopen_luci_jsonc(lua_State *L)
530 luaL_register(L, LUCI_JSONC, jsonc_methods);
532 luaL_newmetatable(L, LUCI_JSONC_PARSER);
533 luaL_register(L, NULL, jsonc_parser_methods);
534 lua_pushvalue(L, -1);
535 lua_setfield(L, -2, "__index");