lua-jsonc: new package
This package replaces luci-lib-jsonc, and also provides utility functions for use from other C libraries.
This commit is contained in:
parent
309dacfa31
commit
d14cedea14
|
@ -0,0 +1,28 @@
|
|||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=lua-jsonc
|
||||
PKG_VERSION:=1
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/lua-jsonc
|
||||
SECTION:=libs
|
||||
CATEGORY:=Libraries
|
||||
TITLE:=JSON parsing and formatting library
|
||||
DEPENDS:=+liblua +libjson-c
|
||||
endef
|
||||
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Package/lua-jsonc/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib
|
||||
$(CP) $(PKG_INSTALL_DIR)/usr/lib/* $(1)/usr/lib/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,lua-jsonc))
|
|
@ -0,0 +1,16 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(lua-jsonc C)
|
||||
|
||||
add_library(lua-jsonc SHARED lua-jsonc.c)
|
||||
set_property(TARGET lua-jsonc PROPERTY COMPILE_FLAGS "-Wall -std=c99")
|
||||
target_link_libraries(lua-jsonc json-c lua)
|
||||
|
||||
install(TARGETS lua-jsonc
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/lua-jsonc.h DESTINATION include)
|
||||
install(DIRECTORY DESTINATION lib/lua)
|
||||
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ../liblua-jsonc.so \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib/lua/jsonc.so)")
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
Copyright 2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Copyright 2018 Matthias Schiffer <mschiffer@universe-factory.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "lua-jsonc.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
|
||||
void lua_jsonc_push_json(lua_State *L, struct json_object *obj) {
|
||||
int64_t i;
|
||||
|
||||
switch (json_object_get_type(obj)) {
|
||||
case json_type_object:
|
||||
lua_newtable(L);
|
||||
json_object_object_foreach(obj, key, val) {
|
||||
lua_jsonc_push_json(L, val);
|
||||
lua_setfield(L, -2, key);
|
||||
}
|
||||
break;
|
||||
|
||||
case json_type_array:
|
||||
lua_newtable(L);
|
||||
for (size_t n = 0; n < json_object_array_length(obj); n++) {
|
||||
lua_jsonc_push_json(L, json_object_array_get_idx(obj, n));
|
||||
lua_rawseti(L, -2, n + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case json_type_boolean:
|
||||
lua_pushboolean(L, json_object_get_boolean(obj));
|
||||
break;
|
||||
|
||||
case json_type_int:
|
||||
i = json_object_get_int64(obj);
|
||||
if (i == (int64_t)(lua_Integer)i)
|
||||
lua_pushinteger(L, i);
|
||||
else
|
||||
lua_pushnumber(L, i);
|
||||
break;
|
||||
|
||||
case json_type_double:
|
||||
lua_pushnumber(L, json_object_get_double(obj));
|
||||
break;
|
||||
|
||||
case json_type_string:
|
||||
lua_pushstring(L, json_object_get_string(obj));
|
||||
break;
|
||||
|
||||
case json_type_null:
|
||||
lua_pushnil(L);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int lua_jsonc_lua_test_array(lua_State *L, int index) {
|
||||
int max = 0;
|
||||
|
||||
lua_pushnil(L);
|
||||
|
||||
/* check for non-integer keys */
|
||||
while (lua_next(L, index)) {
|
||||
if (lua_type(L, -2) != LUA_TNUMBER)
|
||||
goto out;
|
||||
|
||||
lua_Number idx = lua_tonumber(L, -2);
|
||||
|
||||
if (idx != (lua_Number)(lua_Integer)idx)
|
||||
goto out;
|
||||
|
||||
/* We only allow INT_MAX-1 keys to avoid overflows */
|
||||
if (idx <= 0 || idx >= INT_MAX)
|
||||
goto out;
|
||||
|
||||
if (idx > max)
|
||||
max = idx;
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/* check for holes */
|
||||
for (int i = 1; i <= max; i++) {
|
||||
lua_rawgeti(L, index, i);
|
||||
int isnil = lua_isnil(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (isnil)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return max;
|
||||
|
||||
out:
|
||||
lua_pop(L, 2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct json_object * lua_jsonc_tojson(lua_State *L, int index) {
|
||||
lua_Number nd, ni;
|
||||
struct json_object *obj;
|
||||
const char *key;
|
||||
int i, max;
|
||||
|
||||
switch (lua_type(L, index)) {
|
||||
case LUA_TTABLE:
|
||||
max = lua_jsonc_lua_test_array(L, index);
|
||||
|
||||
if (max >= 0) {
|
||||
obj = json_object_new_array();
|
||||
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
for (i = 1; i <= max; i++) {
|
||||
lua_rawgeti(L, index, i);
|
||||
|
||||
json_object_array_put_idx(
|
||||
obj, i - 1, lua_jsonc_tojson(L, lua_gettop(L))
|
||||
);
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
obj = json_object_new_object();
|
||||
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
lua_pushnil(L);
|
||||
|
||||
while (lua_next(L, index)) {
|
||||
lua_pushvalue(L, -2);
|
||||
key = lua_tostring(L, -1);
|
||||
|
||||
if (key)
|
||||
json_object_object_add(
|
||||
obj, key, lua_jsonc_tojson(L, lua_gettop(L) - 1)
|
||||
);
|
||||
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
||||
case LUA_TNIL:
|
||||
return NULL;
|
||||
|
||||
case LUA_TBOOLEAN:
|
||||
return json_object_new_boolean(lua_toboolean(L, index));
|
||||
|
||||
case LUA_TNUMBER:
|
||||
nd = lua_tonumber(L, index);
|
||||
ni = lua_tointeger(L, index);
|
||||
|
||||
if (nd == ni)
|
||||
return json_object_new_int(nd);
|
||||
|
||||
return json_object_new_double(nd);
|
||||
|
||||
case LUA_TSTRING:
|
||||
return json_object_new_string(lua_tostring(L, index));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int lua_jsonc_load(lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
|
||||
struct json_object *obj = json_object_from_file(filename);
|
||||
lua_jsonc_push_json(L, obj);
|
||||
json_object_put(obj);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_jsonc_parse(lua_State *L) {
|
||||
const char *input = luaL_checkstring(L, 1);
|
||||
|
||||
struct json_object *obj = json_tokener_parse(input);
|
||||
lua_jsonc_push_json(L, obj);
|
||||
json_object_put(obj);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_jsonc_stringify(lua_State *L) {
|
||||
struct json_object *obj = lua_jsonc_tojson(L, 1);
|
||||
int pretty = lua_toboolean(L, 2);
|
||||
int flags = 0;
|
||||
|
||||
if (pretty)
|
||||
flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED;
|
||||
|
||||
lua_pushstring(L, json_object_to_json_string_ext(obj, flags));
|
||||
json_object_put(obj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_reg R[] = {
|
||||
{ "load", lua_jsonc_load },
|
||||
{ "parse", lua_jsonc_parse },
|
||||
{ "stringify", lua_jsonc_stringify },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
int luaopen_jsonc(lua_State *L) {
|
||||
luaL_register(L, "jsonc", R);
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef LUA_JSONC_H_
|
||||
#define LUA_JSONC_H_
|
||||
|
||||
#include <json-c/json.h>
|
||||
#include <lua.h>
|
||||
|
||||
void lua_jsonc_push_json(lua_State *L, struct json_object *obj);
|
||||
struct json_object * lua_jsonc_tojson(lua_State *L, int index);
|
||||
|
||||
#endif /* LUA_JSONC_H_ */
|
Loading…
Reference in New Issue