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));
113 static int json_parse_chunk(lua_State *L)
116 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
117 const char *chunk = luaL_checklstring(L, 2, &len);
119 s->obj = json_tokener_parse_ex(s->tok, chunk, len);
120 s->err = json_tokener_get_error(s->tok);
124 lua_pushboolean(L, true);
127 else if (s->err == json_tokener_continue)
129 lua_pushboolean(L, false);
134 lua_pushstring(L, json_tokener_error_desc(s->err));
138 static void _json_to_lua(lua_State *L, struct json_object *obj)
142 switch (json_object_get_type(obj))
144 case json_type_object:
146 json_object_object_foreach(obj, key, val)
148 _json_to_lua(L, val);
149 lua_setfield(L, -2, key);
153 case json_type_array:
155 for (n = 0; n < json_object_array_length(obj); n++)
157 _json_to_lua(L, json_object_array_get_idx(obj, n));
158 lua_rawseti(L, -2, n + 1);
162 case json_type_boolean:
163 lua_pushboolean(L, json_object_get_boolean(obj));
167 lua_pushinteger(L, json_object_get_int(obj));
170 case json_type_double:
171 lua_pushnumber(L, json_object_get_double(obj));
174 case json_type_string:
175 lua_pushstring(L, json_object_get_string(obj));
184 static int json_parse_get(lua_State *L)
186 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
188 if (!s->obj || s->err)
191 _json_to_lua(L, s->obj);
196 static int _lua_test_array(lua_State *L, int index)
203 /* check for non-integer keys */
204 while (lua_next(L, index))
206 if (lua_type(L, -2) != LUA_TNUMBER)
209 idx = lua_tonumber(L, -2);
211 if (idx != (lua_Number)(lua_Integer)idx)
228 /* check for holes */
229 //for (i = 1; i <= max; i++)
231 // lua_rawgeti(L, index, i);
233 // if (lua_isnil(L, -1))
245 static struct json_object * _lua_to_json(lua_State *L, int index)
248 struct json_object *obj;
252 switch (lua_type(L, index))
255 max = _lua_test_array(L, index);
259 obj = json_object_new_array();
264 for (i = 1; i <= max; i++)
266 lua_rawgeti(L, index, i);
268 json_object_array_put_idx(obj, i - 1,
269 _lua_to_json(L, lua_gettop(L)));
277 obj = json_object_new_object();
284 while (lua_next(L, index))
286 lua_pushvalue(L, -2);
287 key = lua_tostring(L, -1);
289 json_object_object_add(obj, key,
290 _lua_to_json(L, lua_gettop(L) - 1));
301 return json_object_new_boolean(lua_toboolean(L, index));
304 nd = lua_tonumber(L, index);
305 ni = lua_tointeger(L, index);
308 return json_object_new_int(nd);
310 return json_object_new_double(nd);
313 return json_object_new_string(lua_tostring(L, index));
319 static int json_parse_set(lua_State *L)
321 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
324 s->obj = _lua_to_json(L, 2);
329 static int json_tostring(lua_State *L)
331 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
332 bool pretty = lua_toboolean(L, 2);
336 flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
338 lua_pushstring(L, json_object_to_json_string_ext(s->obj, flags));
342 static int json_gc(lua_State *L)
344 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
347 json_object_put(s->obj);
350 json_tokener_free(s->tok);
356 static const luaL_reg jsonc_methods[] = {
358 { "parse", json_parse },
359 { "stringify", json_stringify },
364 static const luaL_reg jsonc_parser_methods[] = {
365 { "parse", json_parse_chunk },
366 { "get", json_parse_get },
367 { "set", json_parse_set },
368 { "stringify", json_tostring },
371 { "__tostring", json_tostring },
377 int luaopen_luci_jsonc(lua_State *L)
379 luaL_register(L, LUCI_JSONC, jsonc_methods);
381 luaL_newmetatable(L, LUCI_JSONC_PARSER);
382 luaL_register(L, NULL, jsonc_parser_methods);
383 lua_pushvalue(L, -1);
384 lua_setfield(L, -2, "__index");