build(cjson): sync with upstream (#32114)

Sync with commit 91ca29db9a
This commit is contained in:
Tristan Knight
2025-02-26 08:40:02 +00:00
committed by GitHub
parent b0a1d35f69
commit 7ead328a48
4 changed files with 197 additions and 155 deletions

177
src/cjson/lua_cjson.c vendored
View File

@ -1,4 +1,5 @@
// Upstream: https://github.com/openresty/lua-cjson/blob/master/lua_cjson.c
// Synced Commit; 91ca29db9a4a4fd0eedaebcd5d5f3ba2ace5ae63
/* Lua CJSON - JSON support for Lua
*
@ -42,6 +43,7 @@
#include <stdint.h>
#include <string.h>
#include <math.h>
// #include <stdint.h>
#include <limits.h>
#include <lua.h>
#include <lauxlib.h>
@ -57,17 +59,14 @@
#endif
#ifndef CJSON_VERSION
#define CJSON_VERSION "2.1.0.9"
#define CJSON_VERSION "2.1.0.11"
#endif
#ifdef _MSC_VER
#define snprintf sprintf_s
#ifndef isnan
#include <float.h>
#define isnan(x) _isnan(x)
#endif
// #define CJSON_EXPORT __declspec(dllexport)
// #define strncasecmp(x,y,z) _strnicmp(x,y,z)
#else
#define CJSON_EXPORT extern
#endif
/* Workaround for Solaris platforms missing isinf() */
@ -87,6 +86,7 @@
#define DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT 0
#define DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT 0
#define DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH 1
#define DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES 0
#ifdef DISABLE_INVALID_NUMBERS
#undef DEFAULT_DECODE_INVALID_NUMBERS
@ -107,8 +107,8 @@
#define json_lightudata_mask(ludata) (ludata)
#endif
#if LUA_VERSION_NUM > 501
#define lua_objlen(L,i) lua_rawlen(L, (i))
#if LUA_VERSION_NUM >= 502
#define lua_objlen(L,i) luaL_len(L, (i))
#endif
static const char * const *json_empty_array;
@ -121,6 +121,7 @@ typedef enum {
T_ARR_END,
T_STRING,
T_NUMBER,
T_INTEGER,
T_BOOLEAN,
T_NULL,
T_COLON,
@ -138,6 +139,7 @@ static const char *json_token_type_name[] = {
"T_ARR_END",
"T_STRING",
"T_NUMBER",
"T_INTEGER",
"T_BOOLEAN",
"T_NULL",
"T_COLON",
@ -170,6 +172,7 @@ typedef struct {
int decode_invalid_numbers;
int decode_max_depth;
int decode_array_with_array_mt;
int encode_skip_unsupported_value_types;
} json_config_t;
typedef struct {
@ -200,13 +203,14 @@ typedef struct {
typedef struct {
json_token_type_t type;
int index;
size_t index;
union {
const char *string;
double number;
lua_Integer integer;
int boolean;
} value;
int string_len;
size_t string_len;
} json_token_t;
static const char *char2escape[256] = {
@ -254,7 +258,7 @@ static json_config_t *json_fetch_config(lua_State *l)
{
json_config_t *cfg;
cfg = lua_touserdata(l, lua_upvalueindex(1));
cfg = (json_config_t *)lua_touserdata(l, lua_upvalueindex(1));
if (!cfg)
luaL_error(l, "BUG: Unable to fetch CJSON configuration");
@ -397,6 +401,18 @@ static int json_cfg_decode_array_with_array_mt(lua_State *l)
}
*/
/* Configure how to treat invalid types */
/*
static int json_cfg_encode_skip_unsupported_value_types(lua_State *l)
{
json_config_t *cfg = json_arg_init(l, 1);
json_enum_option(l, 1, &cfg->encode_skip_unsupported_value_types, NULL, 1);
return 1;
}
*/
/* Configures JSON encoding buffer persistence */
/*
static int json_cfg_encode_keep_buffer(lua_State *l)
@ -479,7 +495,7 @@ static int json_destroy_config(lua_State *l)
{
json_config_t *cfg;
cfg = lua_touserdata(l, 1);
cfg = (json_config_t *)lua_touserdata(l, 1);
if (cfg)
strbuf_free(&cfg->encode_buf);
cfg = NULL;
@ -492,7 +508,11 @@ static void json_create_config(lua_State *l)
json_config_t *cfg;
int i;
cfg = lua_newuserdata(l, sizeof(*cfg));
cfg = (json_config_t *)lua_newuserdata(l, sizeof(*cfg));
if (!cfg)
abort();
memset(cfg, 0, sizeof(*cfg));
/* Create GC method to clean up strbuf */
lua_newtable(l);
@ -512,6 +532,7 @@ static void json_create_config(lua_State *l)
cfg->encode_empty_table_as_object = DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT;
cfg->decode_array_with_array_mt = DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT;
cfg->encode_escape_forward_slash = DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH;
cfg->encode_skip_unsupported_value_types = DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES;
#if DEFAULT_ENCODE_KEEP_BUFFER > 0
strbuf_init(&cfg->encode_buf, 0);
@ -583,9 +604,9 @@ static void json_encode_exception(lua_State *l, json_encode_t *ctx, int lindex,
static void json_append_string(lua_State *l, json_encode_t *ctx, int lindex)
{
const char *escstr;
unsigned i;
const char *str;
size_t len;
size_t i;
strbuf_t *json = ctx->json;
str = lua_tolstring(l, lindex, &len);
@ -594,6 +615,8 @@ static void json_append_string(lua_State *l, json_encode_t *ctx, int lindex)
* This buffer is reused constantly for small strings
* If there are any excess pages, they won't be hit anyway.
* This gains ~5% speedup. */
if (len > SIZE_MAX / 6 - 3)
abort(); /*Overflow check */
strbuf_ensure_empty_length(json, len * 6 + 2);
strbuf_append_char_unsafe(json, '\"');
@ -678,30 +701,44 @@ static void json_check_encode_depth(lua_State *l, json_config_t *cfg,
current_depth);
}
static void json_append_data(lua_State *l, json_encode_t *cfg,
static int json_append_data(lua_State *l, json_encode_t *cfg,
int current_depth);
/* json_append_array args:
* - lua_State
* - JSON strbuf
* - Size of passwd Lua array (top of stack) */
* - Size of passed Lua array (top of stack) */
static void json_append_array(lua_State *l, json_encode_t *ctx, int current_depth,
int array_length)
int array_length, int raw)
{
int comma, i;
int comma, i, json_pos, err;
strbuf_t *json = ctx->json;
strbuf_append_char(json, '[');
comma = 0;
for (i = 1; i <= array_length; i++) {
if (comma)
json_pos = strbuf_length(json);
if (comma++ > 0)
strbuf_append_char(json, ',');
else
comma = 1;
if (raw) {
lua_rawgeti(l, -1, i);
} else {
#if LUA_VERSION_NUM >= 503
lua_geti(l, -1, i);
#else
lua_pushinteger(l, i);
lua_gettable(l, -2);
#endif
}
lua_rawgeti(l, -1, i);
json_append_data(l, ctx, current_depth);
err = json_append_data(l, ctx, current_depth);
if (err) {
strbuf_set_length(json, json_pos);
if (comma == 1) {
comma = 0;
}
}
lua_pop(l, 1);
}
@ -711,8 +748,17 @@ static void json_append_array(lua_State *l, json_encode_t *ctx, int current_dept
static void json_append_number(lua_State *l, json_encode_t *ctx,
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 = sprintf(strbuf_empty_ptr(json), LUA_INTEGER_FMT, num);
strbuf_extend_length(json, len);
return;
}
#endif
double num = lua_tonumber(l, lindex);
json_config_t *cfg = ctx->cfg;
strbuf_t *json = ctx->json;
@ -751,7 +797,7 @@ static void json_append_number(lua_State *l, json_encode_t *ctx,
static void json_append_object(lua_State *l, json_encode_t *ctx,
int current_depth)
{
int comma, keytype;
int comma, keytype, json_pos, err;
strbuf_t *json = ctx->json;
/* Object */
@ -761,7 +807,8 @@ static void json_append_object(lua_State *l, json_encode_t *ctx,
/* table, startkey */
comma = 0;
while (lua_next(l, -2) != 0) {
if (comma)
json_pos = strbuf_length(json);
if (comma++ > 0)
strbuf_append_char(json, ',');
else
comma = 1;
@ -782,7 +829,14 @@ static void json_append_object(lua_State *l, json_encode_t *ctx,
}
/* table, key, value */
json_append_data(l, ctx, current_depth);
err = json_append_data(l, ctx, current_depth);
if (err) {
strbuf_set_length(json, json_pos);
if (comma == 1) {
comma = 0;
}
}
lua_pop(l, 1);
/* table, key */
}
@ -790,14 +844,15 @@ static void json_append_object(lua_State *l, json_encode_t *ctx,
strbuf_append_char(json, '}');
}
/* Serialise Lua data into JSON string. */
static void json_append_data(lua_State *l, json_encode_t *ctx,
/* Serialise Lua data into JSON string. Return 1 if error an error happend, else 0 */
static int json_append_data(lua_State *l, json_encode_t *ctx,
int current_depth)
{
int len;
int as_array = 0;
int as_empty_dict = 0;
int has_metatable;
int raw = 1;
json_config_t *cfg = ctx->cfg;
strbuf_t *json = ctx->json;
@ -831,17 +886,31 @@ static void json_append_data(lua_State *l, json_encode_t *ctx,
lua_rawget(l, LUA_REGISTRYINDEX);
as_array = lua_rawequal(l, -1, -2);
}
lua_pop(l, 2);
if (as_array) {
raw = 1;
lua_pop(l, 2);
len = lua_objlen(l, -1);
} else {
raw = 0;
lua_pop(l, 2);
if (luaL_getmetafield(l, -1, "__len")) {
lua_pushvalue(l, -2);
lua_call(l, 1, 1);
len = lua_tonumber(l, -1);
lua_pop(l, 1);
as_array = 1;
}
}
}
if (as_array) {
len = lua_objlen(l, -1);
json_append_array(l, ctx, current_depth, len);
json_append_array(l, ctx, current_depth, len, raw);
} else {
len = lua_array_length(l, ctx);
if (len > 0 || (len == 0 && !cfg->encode_empty_table_as_object && !as_empty_dict)) {
json_append_array(l, ctx, current_depth, len);
json_append_array(l, ctx, current_depth, len, raw);
} else {
if (has_metatable) {
lua_getmetatable(l, -1);
@ -851,7 +920,10 @@ static void json_append_data(lua_State *l, json_encode_t *ctx,
as_array = lua_rawequal(l, -1, -2);
lua_pop(l, 2); /* pop pointer + metatable */
if (as_array) {
json_append_array(l, ctx, current_depth, 0);
len = lua_objlen(l, -1);
raw = 1;
json_append_array(l, ctx, current_depth, len, raw);
break;
}
}
@ -864,7 +936,7 @@ static void json_append_data(lua_State *l, json_encode_t *ctx,
break;
case LUA_TLIGHTUSERDATA:
if (lua_touserdata(l, -1) == &json_array) {
json_append_array(l, ctx, current_depth, 0);
json_append_array(l, ctx, current_depth, 0, 1);
}
break;
case LUA_TUSERDATA:
@ -880,9 +952,15 @@ static void json_append_data(lua_State *l, json_encode_t *ctx,
default:
/* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD,
* and LUA_TLIGHTUSERDATA) cannot be serialised */
if (cfg->encode_skip_unsupported_value_types) {
return 1;
} else {
json_encode_exception(l, ctx, -1, "type not supported");
}
/* never returns */
}
return 0;
}
static int json_encode(lua_State *l)
@ -893,7 +971,7 @@ static int json_encode(lua_State *l)
strbuf_t local_encode_buf;
strbuf_t *encode_buf;
char *json;
int len;
size_t len;
const char *customChar2escape[256];
switch (lua_gettop(l)) {
@ -1215,12 +1293,19 @@ 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)
json_set_token_error(token, json, "invalid number");
else
json->ptr = endptr; /* Skip the processed number */
token->value.integer = strtoll(json->ptr, &endptr, 10);
if (json->ptr == endptr || *endptr == '.' || *endptr == 'e' ||
*endptr == 'E' || *endptr == 'x') {
token->type = T_NUMBER;
token->value.number = fpconv_strtod(json->ptr, &endptr);
if (json->ptr == endptr) {
json_set_token_error(token, json, "invalid number");
return;
}
} else {
token->type = T_INTEGER;
}
json->ptr = endptr; /* Skip the processed number */
return;
}
@ -1458,6 +1543,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;;
@ -1621,6 +1709,7 @@ int lua_cjson_new(lua_State *l)
{ "encode_invalid_numbers", json_cfg_encode_invalid_numbers },
{ "decode_invalid_numbers", json_cfg_decode_invalid_numbers },
{ "encode_escape_forward_slash", json_cfg_encode_escape_forward_slash },
{ "encode_skip_unsupported_value_types", json_cfg_encode_skip_unsupported_value_types },
*/
{ "new", lua_cjson_new },
{ NULL, NULL }
@ -1745,5 +1834,3 @@ int luaopen_cjson_safe(lua_State *l)
return 1;
}
/* vi:ai et sw=4 ts=4:
*/