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_tostring(lua_State *L)
333 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
334 bool pretty = lua_toboolean(L, 2);
338 flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
340 lua_pushstring(L, json_object_to_json_string_ext(s->obj, flags));
344 static int json_gc(lua_State *L)
346 struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER);
349 json_object_put(s->obj);
352 json_tokener_free(s->tok);
358 static const luaL_reg jsonc_methods[] = {
360 { "parse", json_parse },
361 { "stringify", json_stringify },
366 static const luaL_reg jsonc_parser_methods[] = {
367 { "parse", json_parse_chunk },
368 { "get", json_parse_get },
369 { "set", json_parse_set },
370 { "stringify", json_tostring },
373 { "__tostring", json_tostring },
379 int luaopen_luci_jsonc(lua_State *L)
381 luaL_register(L, LUCI_JSONC, jsonc_methods);
383 luaL_newmetatable(L, LUCI_JSONC_PARSER);
384 luaL_register(L, NULL, jsonc_parser_methods);
385 lua_pushvalue(L, -1);
386 lua_setfield(L, -2, "__index");