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);
290 json_object_object_add(obj, key,
291 _lua_to_json(L, lua_gettop(L) - 1));
302 return json_object_new_boolean(lua_toboolean(L, index));
305 nd = lua_tonumber(L, index);
306 ni = lua_tointeger(L, index);
309 return json_object_new_int(nd);
311 return json_object_new_double(nd);
314 return json_object_new_string(lua_tostring(L, index));
320 static int json_parse_set(lua_State *L)
322 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
325 s->obj = _lua_to_json(L, 2);
330 static int json_tostring(lua_State *L)
332 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
333 bool pretty = lua_toboolean(L, 2);
337 flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
339 lua_pushstring(L, json_object_to_json_string_ext(s->obj, flags));
343 static int json_gc(lua_State *L)
345 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
348 json_object_put(s->obj);
351 json_tokener_free(s->tok);
357 static const luaL_reg jsonc_methods[] = {
359 { "parse", json_parse },
360 { "stringify", json_stringify },
365 static const luaL_reg jsonc_parser_methods[] = {
366 { "parse", json_parse_chunk },
367 { "get", json_parse_get },
368 { "set", json_parse_set },
369 { "stringify", json_tostring },
372 { "__tostring", json_tostring },
378 int luaopen_luci_jsonc(lua_State *L)
380 luaL_register(L, LUCI_JSONC, jsonc_methods);
382 luaL_newmetatable(L, LUCI_JSONC_PARSER);
383 luaL_register(L, NULL, jsonc_parser_methods);
384 lua_pushvalue(L, -1);
385 lua_setfield(L, -2, "__index");