main/lua-cjson: add support for lua5.3 and explicit object/array typing

This commit is contained in:
Timo Teräs 2015-12-08 07:57:07 +00:00
parent 7525cfa637
commit 0b6c443bd5
3 changed files with 500 additions and 5 deletions

View File

@ -0,0 +1,128 @@
From f50a2225b137700b7454c7b8da1266bb2329ddf1 Mon Sep 17 00:00:00 2001
From: Cloud Wu <cloudwu@gmail.com>
Date: Thu, 5 Mar 2015 17:42:42 +0800
Subject: [PATCH 1/3] Support lua 5.3 integer representation
---
lua_cjson.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/lua_cjson.c b/lua_cjson.c
index c14a1c5..40b4bdf 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -81,6 +81,7 @@ typedef enum {
T_ARR_END,
T_STRING,
T_NUMBER,
+ T_INTEGER,
T_BOOLEAN,
T_NULL,
T_COLON,
@@ -98,6 +99,7 @@ static const char *json_token_type_name[] = {
"T_ARR_END",
"T_STRING",
"T_NUMBER",
+ "T_INTEGER",
"T_BOOLEAN",
"T_NULL",
"T_COLON",
@@ -143,6 +145,7 @@ typedef struct {
union {
const char *string;
double number;
+ lua_Integer integer;
int boolean;
} value;
int string_len;
@@ -1002,13 +1005,18 @@ static int json_is_invalid_number(json_parse_t *json)
static void json_next_number_token(json_parse_t *json, json_token_t *token)
{
char *endptr;
-
- token->type = T_NUMBER;
- token->value.number = fpconv_strtod(json->ptr, &endptr);
- if (json->ptr == endptr)
+ token->value.integer = strtoll(json->ptr, &endptr, 0);
+ if (json->ptr == endptr) {
json_set_token_error(token, json, "invalid number");
- else
- json->ptr = endptr; /* Skip the processed number */
+ return;
+ }
+ if (*endptr == '.' || *endptr == 'e' || *endptr == 'E') {
+ token->type = T_NUMBER;
+ token->value.number = fpconv_strtod(json->ptr, &endptr);
+ } else {
+ token->type = T_INTEGER;
+ }
+ json->ptr = endptr; /* Skip the processed number */
return;
}
@@ -1237,6 +1245,9 @@ static void json_process_value(lua_State *l, json_parse_t *json,
case T_NUMBER:
lua_pushnumber(l, token->value.number);
break;;
+ case T_INTEGER:
+ lua_pushinteger(l, token->value.integer);
+ break;;
case T_BOOLEAN:
lua_pushboolean(l, token->value.boolean);
break;;
From e02072ce28a5621725cbce23e32bbe3e38f0dcb3 Mon Sep 17 00:00:00 2001
From: Cloud Wu <cloudwu@gmail.com>
Date: Tue, 1 Sep 2015 23:17:21 +0800
Subject: [PATCH 2/3] encode integer for lua 5.3
---
lua_cjson.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/lua_cjson.c b/lua_cjson.c
index 40b4bdf..da80f0d 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -589,8 +589,17 @@ static void json_append_array(lua_State *l, json_config_t *cfg, int current_dept
static void json_append_number(lua_State *l, json_config_t *cfg,
strbuf_t *json, int lindex)
{
- double num = lua_tonumber(l, lindex);
int len;
+#if LUA_VERSION_NUM >= 503
+ if (lua_isinteger(l, lindex)) {
+ lua_Integer num = lua_tointeger(l, lindex);
+ strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE); /* max length of int64 is 19 */
+ len = lua_integer2str(strbuf_empty_ptr(json), num);
+ strbuf_extend_length(json, len);
+ return;
+ }
+#endif
+ double num = lua_tonumber(l, lindex);
if (cfg->encode_invalid_numbers == 0) {
/* Prevent encoding invalid numbers */
From f5ee43d284d24c100bb11ecf286a04999bca6514 Mon Sep 17 00:00:00 2001
From: Cloud Wu <cloudwu@gmail.com>
Date: Tue, 1 Dec 2015 22:21:19 +0800
Subject: [PATCH 3/3] Compatible with lua 5.3.2
---
lua_cjson.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lua_cjson.c b/lua_cjson.c
index da80f0d..2e918d7 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -594,7 +594,7 @@ static void json_append_number(lua_State *l, json_config_t *cfg,
if (lua_isinteger(l, lindex)) {
lua_Integer num = lua_tointeger(l, lindex);
strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE); /* max length of int64 is 19 */
- len = lua_integer2str(strbuf_empty_ptr(json), num);
+ len = sprintf(strbuf_empty_ptr(json), LUA_INTEGER_FMT, num);
strbuf_extend_length(json, len);
return;
}

View File

@ -0,0 +1,358 @@
From 42064f63d05edf0769814734ada8ab1ce3435931 Mon Sep 17 00:00:00 2001
From: Brian Maher <brian@brimworks.com>
Date: Mon, 1 Jun 2015 12:37:01 -0700
Subject: [PATCH 1/3] Allow empty array to be encoded with a metatable
containing __is_cjson_array=true.
---
lua_cjson.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/lua_cjson.c b/lua_cjson.c
index c14a1c5..283e3af 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -494,9 +494,25 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
int max;
int items;
- max = 0;
+ max = -1;
items = 0;
+ if ( lua_getmetatable(l, -1) ) {
+ int is_array, has_is_array;
+
+ lua_pushliteral(l, "__is_cjson_array");
+ lua_rawget(l, -2);
+ has_is_array = lua_isboolean(l, -1);
+ is_array = has_is_array && lua_toboolean(l, -1);
+ lua_pop(l, 2);
+
+ if ( has_is_array && ! is_array ) {
+ return -1;
+ } else {
+ max = 0;
+ }
+ }
+
lua_pushnil(l);
/* table, startkey */
while (lua_next(l, -2) != 0) {
@@ -685,7 +701,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg,
current_depth++;
json_check_encode_depth(l, cfg, current_depth, json);
len = lua_array_length(l, cfg, json);
- if (len > 0)
+ if (len >= 0)
json_append_array(l, cfg, current_depth, json, len);
else
json_append_object(l, cfg, current_depth, json);
@@ -1204,6 +1220,16 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json)
/* Handle empty arrays */
if (token.type == T_ARR_END) {
+ // Mark as array:
+ luaL_getmetatable(l, "cjson.array");
+ if ( lua_isnil(l, -1) ) {
+ lua_pop(l, 1);
+ luaL_newmetatable(l, "cjson.array");
+ lua_pushboolean(l, 1);
+ lua_setfield(l, -2, "__is_cjson_array");
+ }
+ lua_setmetatable(l, -2);
+
json_decode_ascend(json);
return;
}
--
2.6.3
From 514c4b4761ac0552182acbf25039930ddca70070 Mon Sep 17 00:00:00 2001
From: Brian Maher <brian@brimworks.com>
Date: Thu, 3 Sep 2015 12:33:33 -0700
Subject: [PATCH 2/3] Replace __is_cjson_array with check for __name="array"
and replace lightuserdata NULL with __name="null" meatable. This will allow
better interchange with other modules that need to define "array" and "null"
types. Note that you can also define custom implementations of "array" and
"null" if you have access to the registry.
---
lua_cjson.c | 65 ++++++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 43 insertions(+), 22 deletions(-)
diff --git a/lua_cjson.c b/lua_cjson.c
index 283e3af..2140743 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -497,20 +497,13 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
max = -1;
items = 0;
- if ( lua_getmetatable(l, -1) ) {
- int is_array, has_is_array;
-
- lua_pushliteral(l, "__is_cjson_array");
+ if (lua_getmetatable(l, -1)) {
+ lua_pushliteral(l, "__name");
lua_rawget(l, -2);
- has_is_array = lua_isboolean(l, -1);
- is_array = has_is_array && lua_toboolean(l, -1);
- lua_pop(l, 2);
-
- if ( has_is_array && ! is_array ) {
- return -1;
- } else {
+ if (lua_isstring(l, -1) && strcmp("array", lua_tostring(l, -1)) == 0) {
max = 0;
}
+ lua_pop(l, 2);
}
lua_pushnil(l);
@@ -698,6 +691,16 @@ static void json_append_data(lua_State *l, json_config_t *cfg,
strbuf_append_mem(json, "false", 5);
break;
case LUA_TTABLE:
+ if (lua_getmetatable(l, -1)) {
+ lua_pushliteral(l, "__name");
+ lua_rawget(l, -2);
+ if (lua_isstring(l, -1) && strcmp("null", lua_tostring(l, -1)) == 0) {
+ strbuf_append_mem(json, "null", 4);
+ lua_pop(l, 2);
+ break;
+ }
+ lua_pop(l, 2);
+ }
current_depth++;
json_check_encode_depth(l, cfg, current_depth, json);
len = lua_array_length(l, cfg, json);
@@ -1221,13 +1224,7 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json)
/* Handle empty arrays */
if (token.type == T_ARR_END) {
// Mark as array:
- luaL_getmetatable(l, "cjson.array");
- if ( lua_isnil(l, -1) ) {
- lua_pop(l, 1);
- luaL_newmetatable(l, "cjson.array");
- lua_pushboolean(l, 1);
- lua_setfield(l, -2, "__is_cjson_array");
- }
+ luaL_getmetatable(l, "array");
lua_setmetatable(l, -2);
json_decode_ascend(json);
@@ -1274,9 +1271,9 @@ static void json_process_value(lua_State *l, json_parse_t *json,
break;;
case T_NULL:
/* In Lua, setting "t[k] = nil" will delete k from the table.
- * Hence a NULL pointer lightuserdata object is used instead */
- lua_pushlightuserdata(l, NULL);
- break;;
+ * Hence a NULL userdata object is used instead */
+ luaL_getmetatable(l, "null");
+ break;
default:
json_throw_parse_error(l, json, "value", token);
}
@@ -1372,6 +1369,12 @@ static int json_protect_conversion(lua_State *l)
return luaL_error(l, "Memory allocation error in CJSON protected call");
}
+static int json_null_tostring(lua_State *l)
+{
+ lua_pushliteral(l, "null");
+ return 1;
+}
+
/* Return cjson module table */
static int lua_cjson_new(lua_State *l)
{
@@ -1392,6 +1395,24 @@ static int lua_cjson_new(lua_State *l)
/* Initialise number conversions */
fpconv_init();
+ /* Initialize "null" */
+ if ( luaL_newmetatable(l, "null") ) {
+ lua_createtable(l, 0, 2);
+ lua_pushliteral(l, "null");
+ lua_setfield(l, -2, "__name");
+ lua_pushcfunction(l, json_null_tostring);
+ lua_setfield(l, -2, "__tostring");
+ lua_setmetatable(l, -2);
+ }
+ lua_pop(l, 1);
+
+ /* Initialize "array" metatable */
+ if ( luaL_newmetatable(l, "array") ) {
+ lua_pushliteral(l, "array");
+ lua_setfield(l, -2, "__name");
+ }
+ lua_pop(l, 1);
+
/* cjson module table */
lua_newtable(l);
@@ -1400,7 +1421,7 @@ static int lua_cjson_new(lua_State *l)
luaL_setfuncs(l, reg, 1);
/* Set cjson.null */
- lua_pushlightuserdata(l, NULL);
+ luaL_getmetatable(l, "null");
lua_setfield(l, -2, "null");
/* Set module name / version fields */
--
2.6.3
From 438a71d35417453e2207f64f706d02f199525c7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Tue, 8 Dec 2015 09:16:18 +0200
Subject: [PATCH 3/3] fix empty array default encoding, and add meta __name for
objects
---
lua_cjson.c | 52 +++++++++++++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 19 deletions(-)
diff --git a/lua_cjson.c b/lua_cjson.c
index 2140743..25952ec 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -493,17 +493,20 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
double k;
int max;
int items;
+ int is_array = 0;
+ const char *mt_name;
- max = -1;
+ max = 0;
items = 0;
if (lua_getmetatable(l, -1)) {
lua_pushliteral(l, "__name");
lua_rawget(l, -2);
- if (lua_isstring(l, -1) && strcmp("array", lua_tostring(l, -1)) == 0) {
- max = 0;
- }
+ mt_name = lua_isstring(l, -1) ? lua_tostring(l, -1) : "";
lua_pop(l, 2);
+ if (strcmp("object", mt_name) == 0)
+ return -1;
+ is_array = strcmp("array", mt_name) == 0;
}
lua_pushnil(l);
@@ -521,6 +524,10 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
continue;
}
}
+ if (is_array) {
+ lua_pop(l, 1);
+ continue;
+ }
/* Must not be an array (non integer key) */
lua_pop(l, 2);
@@ -537,6 +544,10 @@ static int lua_array_length(lua_State *l, json_config_t *cfg, strbuf_t *json)
return -1;
}
+ /* Backwards compatibility - encode untyped zero length table as object */
+ if (!is_array && max == 0)
+ return -1;
+
return max;
}
@@ -1166,6 +1177,8 @@ static void json_parse_object_context(lua_State *l, json_parse_t *json)
json_decode_descend(l, json, 3);
lua_newtable(l);
+ luaL_getmetatable(l, "cjson.object");
+ lua_setmetatable(l, -2);
json_next_token(json, &token);
@@ -1218,15 +1231,13 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json)
json_decode_descend(l, json, 2);
lua_newtable(l);
+ luaL_getmetatable(l, "cjson.array");
+ lua_setmetatable(l, -2);
json_next_token(json, &token);
/* Handle empty arrays */
if (token.type == T_ARR_END) {
- // Mark as array:
- luaL_getmetatable(l, "array");
- lua_setmetatable(l, -2);
-
json_decode_ascend(json);
return;
}
@@ -1272,7 +1283,7 @@ static void json_process_value(lua_State *l, json_parse_t *json,
case T_NULL:
/* In Lua, setting "t[k] = nil" will delete k from the table.
* Hence a NULL userdata object is used instead */
- luaL_getmetatable(l, "null");
+ luaL_getmetatable(l, "cjson.null");
break;
default:
json_throw_parse_error(l, json, "value", token);
@@ -1395,8 +1406,11 @@ static int lua_cjson_new(lua_State *l)
/* Initialise number conversions */
fpconv_init();
+ /* cjson module table */
+ lua_newtable(l);
+
/* Initialize "null" */
- if ( luaL_newmetatable(l, "null") ) {
+ if ( luaL_newmetatable(l, "cjson.null") ) {
lua_createtable(l, 0, 2);
lua_pushliteral(l, "null");
lua_setfield(l, -2, "__name");
@@ -1404,26 +1418,26 @@ static int lua_cjson_new(lua_State *l)
lua_setfield(l, -2, "__tostring");
lua_setmetatable(l, -2);
}
- lua_pop(l, 1);
+ lua_setfield(l, -2, "null");
/* Initialize "array" metatable */
- if ( luaL_newmetatable(l, "array") ) {
+ if ( luaL_newmetatable(l, "cjson.array") ) {
lua_pushliteral(l, "array");
lua_setfield(l, -2, "__name");
}
- lua_pop(l, 1);
+ lua_setfield(l, -2, "array");
- /* cjson module table */
- lua_newtable(l);
+ /* Initialize "object" metatable */
+ if ( luaL_newmetatable(l, "cjson.object") ) {
+ lua_pushliteral(l, "object");
+ lua_setfield(l, -2, "__name");
+ }
+ lua_setfield(l, -2, "object");
/* Register functions with config data as upvalue */
json_create_config(l);
luaL_setfuncs(l, reg, 1);
- /* Set cjson.null */
- luaL_getmetatable(l, "null");
- lua_setfield(l, -2, "null");
-
/* Set module name / version fields */
lua_pushliteral(l, CJSON_MODNAME);
lua_setfield(l, -2, "_NAME");
--
2.6.3

View File

@ -3,7 +3,7 @@
_luaversions="5.1 5.2 5.3"
pkgname=lua-cjson
pkgver=2.1.0
pkgrel=5
pkgrel=6
pkgdesc="fast JSON parsing and encoding support for Lua"
url="http://www.kyne.com.au/~mark/software/lua-cjson.php"
arch="all"
@ -17,7 +17,10 @@ for _i in $_luaversions; do
subpackages="$subpackages lua$_i-cjson:split_${_i/./_}"
done
source="http://www.kyne.com.au/~mark/software/download/lua-cjson-$pkgver.tar.gz
0001-Use-pkg-config-to-detect-cflags-or-fallback-to-LUA_I.patch"
0001-Use-pkg-config-to-detect-cflags-or-fallback-to-LUA_I.patch
0002-lua53-integers.patch
0003-empty-array-metadata.patch
"
_sdir="$srcdir"/lua-cjson-$pkgver
@ -70,8 +73,14 @@ for _i in $_luaversions; do
done
md5sums="24f270663e9f6ca8ba2a02cef19f7963 lua-cjson-2.1.0.tar.gz
84a94739f4ead0b4b2e80376dbed7b08 0001-Use-pkg-config-to-detect-cflags-or-fallback-to-LUA_I.patch"
84a94739f4ead0b4b2e80376dbed7b08 0001-Use-pkg-config-to-detect-cflags-or-fallback-to-LUA_I.patch
1b37edbe331691d96d9a506ed6fbe1db 0002-lua53-integers.patch
18d361083d5b5aab987d897629a38982 0003-empty-array-metadata.patch"
sha256sums="51bc69cd55931e0cba2ceae39e9efa2483f4292da3a88a1ed470eda829f6c778 lua-cjson-2.1.0.tar.gz
cef22bd926c88053b1be147c6420e9b9918b09a32cb3cad9e81524619048020a 0001-Use-pkg-config-to-detect-cflags-or-fallback-to-LUA_I.patch"
cef22bd926c88053b1be147c6420e9b9918b09a32cb3cad9e81524619048020a 0001-Use-pkg-config-to-detect-cflags-or-fallback-to-LUA_I.patch
76bcddec37e70538831d366998e7b1ccf9609bd7f07fe181b3475667be7dcfd9 0002-lua53-integers.patch
a28eb784e0d33d149f69f1011a8f65549c38cbe5d9a2e823ce40c3cd9c7c6cde 0003-empty-array-metadata.patch"
sha512sums="4343513b942f2ed98dc1ea6d7e852303bc1263f8acc5c70c8d674aec7adfc8279c5af7d5173a417b6f9a74543b8f6c8f98742d002f4f75832bbf23bb5a30ad2f lua-cjson-2.1.0.tar.gz
5137cf25ca125b03ff2e95cedd8396d63b9a4919b1aba4ef333fd8945a4fd20f423c1e8d36b954a15969bd344cd43bb6c50df8b878cd74a706d6065455fbb003 0001-Use-pkg-config-to-detect-cflags-or-fallback-to-LUA_I.patch"
5137cf25ca125b03ff2e95cedd8396d63b9a4919b1aba4ef333fd8945a4fd20f423c1e8d36b954a15969bd344cd43bb6c50df8b878cd74a706d6065455fbb003 0001-Use-pkg-config-to-detect-cflags-or-fallback-to-LUA_I.patch
2cf4d4fa116850a6a8fb74f27779383a339ca08ed81cdcb03be985c731b91234e7552a26913b609f2c9b02516fc74171d4e5fbb446bcdaf0eddddac3af08865a 0002-lua53-integers.patch
77a05166a88b7ec7d1c7fa2cd7e22fdf75dd2882d67529f8c924e8408c8bf3d210b8e2cd803cffc6d6460a63e079e331237811f1dbfeb03051090f4d6278a350 0003-empty-array-metadata.patch"