mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Squashed 'src/deps/src/lua-cjson/' changes from 881accc8fa..f95cd9ea1e
f95cd9ea1e doc: add comment for dtoa.c. c92ecda533 feature: Lua 5.3 + 5.4 integer support, with CI and conflicts fixed. d20576d5ce bugfix: bus error or SIGSEGV caused by encode not keep buffer. 2bfad8f5ee Bugfix: Lua cjson integer overflow issues (CVE-2022-24834) (#94) git-subtree-dir: src/deps/src/lua-cjson git-subtree-split: f95cd9ea1e39221a36818772eb85f05b4164bbb1
This commit is contained in:
parent
4f9b885a2e
commit
cdc12b239d
17 changed files with 299 additions and 185 deletions
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
runtestArgs: "LUA_INCLUDE_DIR=.lua/include/luajit-2.1"
|
||||
runtestEnv: "SKIP_CMAKE=1"
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
|
@ -47,7 +47,7 @@ jobs:
|
|||
sudo cpanm --notest Test::Base Test::LongString
|
||||
|
||||
- name: cppcheck
|
||||
run: cppcheck -i .lua/ -i .install/ -i dtoa.c --force --error-exitcode=1 --enable=warning .
|
||||
run: cppcheck -i .lua/ -i .install/ -i dtoa.c --force --error-exitcode=1 --enable=warning --inline-suppr .
|
||||
|
||||
- name: prove
|
||||
run: LUA_BIN=lua prove -Itests tests
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,6 +1,7 @@
|
|||
*.html
|
||||
*.o
|
||||
*.so
|
||||
*.a
|
||||
notes
|
||||
packages
|
||||
tags
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ env:
|
|||
- JOBS=3
|
||||
- LUAROCKS_VER=2.4.2
|
||||
matrix:
|
||||
#- LUA=1 LUA_DIR=/usr LUA_INCLUDE_DIR=$LUA_DIR/include/lua5.1
|
||||
#- LUA=1 LUA_DIR=/usr LUA_INCLUDE_DIR=$LUA_DIR/include/lua5.1
|
||||
- LUAJIT=1 LUA_DIR=/usr/local LUA_INCLUDE_DIR=$LUA_DIR/include/luajit-2.1 LUA_SUFFIX=--lua-suffix=jit
|
||||
|
||||
install:
|
||||
|
|
|
|||
|
|
@ -68,6 +68,13 @@ else()
|
|||
set(_lua_module_dir "${_lua_lib_dir}/lua/5.1")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(-Dinline=__inline)
|
||||
add_definitions(-Dsnprintf=_snprintf)
|
||||
add_definitions(-Dstrncasecmp=_strnicmp)
|
||||
endif()
|
||||
|
||||
add_library(cjson MODULE lua_cjson.c strbuf.c ${FPCONV_SOURCES})
|
||||
set_target_properties(cjson PROPERTIES PREFIX "")
|
||||
target_link_libraries(cjson ${_MODULE_LINK})
|
||||
|
|
|
|||
8
Makefile
8
Makefile
|
|
@ -23,6 +23,8 @@ LUA_CMODULE_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION)
|
|||
LUA_MODULE_DIR ?= $(PREFIX)/share/lua/$(LUA_VERSION)
|
||||
LUA_BIN_DIR ?= $(PREFIX)/bin
|
||||
|
||||
AR= $(CC) -o
|
||||
|
||||
##### Platform overrides #####
|
||||
##
|
||||
## Tweak one of the platform sections below to suit your situation.
|
||||
|
|
@ -84,12 +86,12 @@ OBJS = lua_cjson.o strbuf.o $(FPCONV_OBJS)
|
|||
|
||||
.PHONY: all clean install install-extra doc
|
||||
|
||||
.SUFFIXES: .html .txt
|
||||
.SUFFIXES: .html .adoc
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(BUILD_CFLAGS) -o $@ $<
|
||||
|
||||
.txt.html:
|
||||
.adoc.html:
|
||||
$(ASCIIDOC) -n -a toc $<
|
||||
|
||||
all: $(TARGET)
|
||||
|
|
@ -97,7 +99,7 @@ all: $(TARGET)
|
|||
doc: manual.html performance.html
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) $(LDFLAGS) $(CJSON_LDFLAGS) -o $@ $(OBJS)
|
||||
$(AR) $@ $(LDFLAGS) $(CJSON_LDFLAGS) $(OBJS)
|
||||
|
||||
install: $(TARGET)
|
||||
mkdir -p $(DESTDIR)$(LUA_CMODULE_DIR)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# Build packages. Use current checked out version, or a specific tag/commit.
|
||||
|
||||
# Files requiring a version bump
|
||||
VERSION_FILES="lua-cjson-2.1devel-1.rockspec lua-cjson.spec lua_cjson.c manual.txt runtests.sh tests/test.lua"
|
||||
VERSION_FILES="lua-cjson-2.1devel-1.rockspec lua-cjson.spec lua_cjson.c manual.adoc runtests.sh tests/test.lua"
|
||||
|
||||
[ "$1" ] && BRANCH="$1" || BRANCH="`git describe --match '[1-3].[0-9]*'`"
|
||||
VERSION="`git describe --match '[1-3].[0-9]*' $BRANCH`"
|
||||
|
|
|
|||
115
dtoa.c
115
dtoa.c
|
|
@ -1,3 +1,7 @@
|
|||
/* The code comes from https://portal.ampl.com/~dmg/netlib/fp/dtoa.c
|
||||
* Go to https://portal.ampl.com/~dmg/netlib/fp/changes for the detailed changes.
|
||||
*/
|
||||
|
||||
/****************************************************************
|
||||
*
|
||||
* The author of this software is David M. Gay.
|
||||
|
|
@ -1533,12 +1537,18 @@ ThInfo {
|
|||
set_max_dtoa_threads(unsigned int n)
|
||||
{
|
||||
size_t L;
|
||||
ThInfo *newTI1;
|
||||
|
||||
if (n > maxthreads) {
|
||||
L = n*sizeof(ThInfo);
|
||||
if (TI1) {
|
||||
TI1 = (ThInfo*)REALLOC(TI1, L);
|
||||
memset(TI1 + maxthreads, 0, (n-maxthreads)*sizeof(ThInfo));
|
||||
newTI1 = (ThInfo*)REALLOC(TI1, L);
|
||||
if (newTI1) {
|
||||
TI1 = newTI1;
|
||||
memset(TI1 + maxthreads, 0, (n-maxthreads)*sizeof(ThInfo));
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else {
|
||||
TI1 = (ThInfo*)MALLOC(L);
|
||||
|
|
@ -1871,7 +1881,7 @@ mult(Bigint *a, Bigint *b MTd)
|
|||
#else
|
||||
#ifdef Pack_32
|
||||
for(; xb < xbe; xb++, xc0++) {
|
||||
if (y = *xb & 0xffff) {
|
||||
if ((y = *xb & 0xffff)) {
|
||||
x = xa;
|
||||
xc = xc0;
|
||||
carry = 0;
|
||||
|
|
@ -1885,7 +1895,7 @@ mult(Bigint *a, Bigint *b MTd)
|
|||
while(x < xae);
|
||||
*xc = carry;
|
||||
}
|
||||
if (y = *xb >> 16) {
|
||||
if ((y = *xb >> 16)) {
|
||||
x = xa;
|
||||
xc = xc0;
|
||||
carry = 0;
|
||||
|
|
@ -2718,13 +2728,14 @@ enum { /* rounding values: same as FLT_ROUNDS */
|
|||
};
|
||||
|
||||
void
|
||||
gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
||||
gethex(const char **sp, U *rvp, int rounding, int sign MTd)
|
||||
{
|
||||
Bigint *b;
|
||||
char d;
|
||||
const unsigned char *decpt, *s0, *s, *s1;
|
||||
Long e, e1;
|
||||
ULong L, lostbits, *x;
|
||||
int big, denorm, esign, havedig, k, n, nbits, up, zret;
|
||||
int big, denorm, esign, havedig, k, n, nb, nbits, nz, up, zret;
|
||||
#ifdef IBM
|
||||
int j;
|
||||
#endif
|
||||
|
|
@ -2742,6 +2753,9 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
#endif
|
||||
#endif /*}}*/
|
||||
};
|
||||
#ifdef IEEE_Arith
|
||||
int check_denorm = 0;
|
||||
#endif
|
||||
#ifdef USE_LOCALE
|
||||
int i;
|
||||
#ifdef NO_LOCALE_CACHE
|
||||
|
|
@ -2893,7 +2907,7 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
k++;
|
||||
b = Balloc(k MTa);
|
||||
x = b->x;
|
||||
n = 0;
|
||||
havedig = n = nz = 0;
|
||||
L = 0;
|
||||
#ifdef USE_LOCALE
|
||||
for(i = 0; decimalpoint[i+1]; ++i);
|
||||
|
|
@ -2908,22 +2922,28 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
if (*--s1 == '.')
|
||||
continue;
|
||||
#endif
|
||||
if ((d = hexdig[*s1]))
|
||||
havedig = 1;
|
||||
else if (!havedig) {
|
||||
e += 4;
|
||||
continue;
|
||||
}
|
||||
if (n == ULbits) {
|
||||
*x++ = L;
|
||||
L = 0;
|
||||
n = 0;
|
||||
}
|
||||
L |= (hexdig[*s1] & 0x0f) << n;
|
||||
L |= (d & 0x0f) << n;
|
||||
n += 4;
|
||||
}
|
||||
*x++ = L;
|
||||
b->wds = n = x - b->x;
|
||||
n = ULbits*n - hi0bits(L);
|
||||
nb = ULbits*n - hi0bits(L);
|
||||
nbits = Nbits;
|
||||
lostbits = 0;
|
||||
x = b->x;
|
||||
if (n > nbits) {
|
||||
n -= nbits;
|
||||
if (nb > nbits) {
|
||||
n = nb - nbits;
|
||||
if (any_on(b,n)) {
|
||||
lostbits = 1;
|
||||
k = n - 1;
|
||||
|
|
@ -2936,8 +2956,8 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
rshift(b, n);
|
||||
e += n;
|
||||
}
|
||||
else if (n < nbits) {
|
||||
n = nbits - n;
|
||||
else if (nb < nbits) {
|
||||
n = nbits - nb;
|
||||
b = lshift(b, n MTa);
|
||||
e -= n;
|
||||
x = b->x;
|
||||
|
|
@ -2992,12 +3012,49 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
return;
|
||||
}
|
||||
k = n - 1;
|
||||
#ifdef IEEE_Arith
|
||||
if (!k) {
|
||||
switch(rounding) {
|
||||
case Round_near:
|
||||
if (((b->x[0] & 3) == 3) || (lostbits && (b->x[0] & 1))) {
|
||||
multadd(b, 1, 1 MTa);
|
||||
emin_check:
|
||||
if (b->x[1] == (1 << (Exp_shift + 1))) {
|
||||
rshift(b,1);
|
||||
e = emin;
|
||||
goto normal;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Round_up:
|
||||
if (!sign && (lostbits || (b->x[0] & 1))) {
|
||||
incr_denorm:
|
||||
multadd(b, 1, 2 MTa);
|
||||
check_denorm = 1;
|
||||
lostbits = 0;
|
||||
goto emin_check;
|
||||
}
|
||||
break;
|
||||
case Round_down:
|
||||
if (sign && (lostbits || (b->x[0] & 1)))
|
||||
goto incr_denorm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (lostbits)
|
||||
lostbits = 1;
|
||||
else if (k > 0)
|
||||
lostbits = any_on(b,k);
|
||||
#ifdef IEEE_Arith
|
||||
else if (check_denorm)
|
||||
goto no_lostbits;
|
||||
#endif
|
||||
if (x[k>>kshift] & 1 << (k & kmask))
|
||||
lostbits |= 2;
|
||||
#ifdef IEEE_Arith
|
||||
no_lostbits:
|
||||
#endif
|
||||
nbits -= n;
|
||||
rshift(b,n);
|
||||
e = emin;
|
||||
|
|
@ -3022,16 +3079,9 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
k = b->wds;
|
||||
b = increment(b MTa);
|
||||
x = b->x;
|
||||
if (denorm) {
|
||||
#if 0
|
||||
if (nbits == Nbits - 1
|
||||
&& x[nbits >> kshift] & 1 << (nbits & kmask))
|
||||
denorm = 0; /* not currently used */
|
||||
#endif
|
||||
}
|
||||
else if (b->wds > k
|
||||
if (!denorm && (b->wds > k
|
||||
|| ((n = nbits & kmask) !=0
|
||||
&& hi0bits(x[k-1]) < 32-n)) {
|
||||
&& hi0bits(x[k-1]) < 32-n))) {
|
||||
rshift(b,1);
|
||||
if (++e > Emax)
|
||||
goto ovfl;
|
||||
|
|
@ -3041,8 +3091,10 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
|
|||
#ifdef IEEE_Arith
|
||||
if (denorm)
|
||||
word0(rvp) = b->wds > 1 ? b->x[1] & ~0x100000 : 0;
|
||||
else
|
||||
else {
|
||||
normal:
|
||||
word0(rvp) = (b->x[1] & ~0x100000) | ((e + 0x3ff + 52) << 20);
|
||||
}
|
||||
word1(rvp) = b->x[0];
|
||||
#endif
|
||||
#ifdef IBM
|
||||
|
|
@ -3409,6 +3461,7 @@ retlow1:
|
|||
if ((j = ((word0(rv) & Exp_mask) >> Exp_shift) - bc->scale) <= 0) {
|
||||
i = 1 - j;
|
||||
if (i <= 31) {
|
||||
/* cppcheck-suppress integerOverflowCond */
|
||||
if (word1(rv) & (0x1 << i))
|
||||
goto odd;
|
||||
}
|
||||
|
|
@ -3619,10 +3672,11 @@ fpconv_strtod(const char *s00, char **se)
|
|||
c = *++s;
|
||||
if (c > '0' && c <= '9') {
|
||||
L = c - '0';
|
||||
s1 = s;
|
||||
while((c = *++s) >= '0' && c <= '9')
|
||||
L = 10*L + c - '0';
|
||||
if (s - s1 > 8 || L > 19999)
|
||||
while((c = *++s) >= '0' && c <= '9') {
|
||||
if (L <= 19999)
|
||||
L = 10*L + c - '0';
|
||||
}
|
||||
if (L > 19999)
|
||||
/* Avoid confusion from exponents
|
||||
* so large that e might overflow.
|
||||
*/
|
||||
|
|
@ -4884,6 +4938,7 @@ nrv_alloc(const char *s, char *s0, size_t s0len, char **rve, int n MTd)
|
|||
s0 = rv_alloc(n MTa);
|
||||
else if (s0len <= n) {
|
||||
rv = 0;
|
||||
/* cppcheck-suppress nullPointerArithmetic */
|
||||
t = rv + n;
|
||||
goto rve_chk;
|
||||
}
|
||||
|
|
@ -5237,9 +5292,11 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
|
|||
#ifndef SET_INEXACT
|
||||
#ifdef Check_FLT_ROUNDS
|
||||
try_quick = Rounding == 1;
|
||||
#else
|
||||
try_quick = 1;
|
||||
#endif
|
||||
#endif /*SET_INEXACT*/
|
||||
#endif
|
||||
#endif /*USE_BF96*/
|
||||
|
||||
if (mode > 5) {
|
||||
mode -= 4;
|
||||
|
|
@ -5281,6 +5338,7 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
|
|||
else if (blen <= i) {
|
||||
buf = 0;
|
||||
if (rve)
|
||||
/* cppcheck-suppress nullPointerArithmetic */
|
||||
*rve = buf + i;
|
||||
return buf;
|
||||
}
|
||||
|
|
@ -5469,6 +5527,7 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
|
|||
res3 = p10->b1 * dbhi + (tv3 & 0xffffffffull);
|
||||
res = p10->b0 * dbhi + (tv3>>32) + (res3>>32);
|
||||
be += p10->e - 0x3fe;
|
||||
/* cppcheck-suppress integerOverflowCond */
|
||||
eulp = j1 = be - 54 + ulpadj;
|
||||
if (!(res & 0x8000000000000000ull)) {
|
||||
--be;
|
||||
|
|
|
|||
2
fpconv.c
2
fpconv.c
|
|
@ -130,7 +130,7 @@ double fpconv_strtod(const char *nptr, char **endptr)
|
|||
/* Duplicate number into buffer */
|
||||
if (buflen >= FPCONV_G_FMT_BUFSIZE) {
|
||||
/* Handle unusually large numbers */
|
||||
buf = malloc(buflen + 1);
|
||||
buf = (char *)malloc(buflen + 1);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Out of memory");
|
||||
abort();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package = "lua-cjson"
|
||||
version = "2.1.0.11-1"
|
||||
version = "2.1.0.14-1"
|
||||
|
||||
source = {
|
||||
url = "git+https://github.com/openresty/lua-cjson",
|
||||
tag = "2.1.0.11",
|
||||
tag = "2.1.0.14",
|
||||
}
|
||||
|
||||
description = {
|
||||
|
|
@ -50,7 +50,7 @@ rm -rf "$RPM_BUILD_ROOT"
|
|||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc LICENSE NEWS performance.html performance.txt manual.html manual.txt rfc4627.txt THANKS
|
||||
%doc LICENSE NEWS performance.html performance.adoc manual.html manual.adoc rfc4627.txt THANKS
|
||||
%{lualibdir}/*
|
||||
%{luadatadir}/*
|
||||
%{_bindir}/*
|
||||
|
|
|
|||
117
lua_cjson.c
117
lua_cjson.c
|
|
@ -40,6 +40,7 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
|
@ -65,6 +66,13 @@
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#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() */
|
||||
#if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF))
|
||||
#define isinf(x) (!isnan(x) && isnan((x) - (x)))
|
||||
|
|
@ -103,8 +111,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;
|
||||
|
|
@ -117,6 +125,7 @@ typedef enum {
|
|||
T_ARR_END,
|
||||
T_STRING,
|
||||
T_NUMBER,
|
||||
T_INTEGER,
|
||||
T_BOOLEAN,
|
||||
T_NULL,
|
||||
T_COLON,
|
||||
|
|
@ -134,6 +143,7 @@ static const char *json_token_type_name[] = {
|
|||
"T_ARR_END",
|
||||
"T_STRING",
|
||||
"T_NUMBER",
|
||||
"T_INTEGER",
|
||||
"T_BOOLEAN",
|
||||
"T_NULL",
|
||||
"T_COLON",
|
||||
|
|
@ -179,13 +189,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] = {
|
||||
|
|
@ -233,7 +244,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");
|
||||
|
||||
|
|
@ -442,7 +453,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;
|
||||
|
|
@ -455,7 +466,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);
|
||||
|
|
@ -547,9 +562,9 @@ static void json_encode_exception(lua_State *l, json_config_t *cfg, strbuf_t *js
|
|||
static void json_append_string(lua_State *l, strbuf_t *json, int lindex)
|
||||
{
|
||||
const char *escstr;
|
||||
unsigned i;
|
||||
const char *str;
|
||||
size_t len;
|
||||
size_t i;
|
||||
|
||||
str = lua_tolstring(l, lindex, &len);
|
||||
|
||||
|
|
@ -557,6 +572,8 @@ static void json_append_string(lua_State *l, strbuf_t *json, 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, '\"');
|
||||
|
|
@ -646,9 +663,9 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
/* 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_config_t *cfg, int current_depth,
|
||||
strbuf_t *json, int array_length)
|
||||
strbuf_t *json, int array_length, int raw)
|
||||
{
|
||||
int comma, i, json_pos, err;
|
||||
|
||||
|
|
@ -660,7 +677,17 @@ static void json_append_array(lua_State *l, json_config_t *cfg, int current_dept
|
|||
if (comma++ > 0)
|
||||
strbuf_append_char(json, ',');
|
||||
|
||||
lua_rawgeti(l, -1, i);
|
||||
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
|
||||
}
|
||||
|
||||
err = json_append_data(l, cfg, current_depth, json);
|
||||
if (err) {
|
||||
strbuf_set_length(json, json_pos);
|
||||
|
|
@ -677,8 +704,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 = sprintf(strbuf_empty_ptr(json), LUA_INTEGER_FMT, num);
|
||||
strbuf_extend_length(json, len);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
double num = lua_tonumber(l, lindex);
|
||||
|
||||
if (cfg->encode_invalid_numbers == 0) {
|
||||
/* Prevent encoding invalid numbers */
|
||||
|
|
@ -766,6 +802,7 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
int len;
|
||||
int as_array = 0;
|
||||
int has_metatable;
|
||||
int raw = 1;
|
||||
|
||||
switch (lua_type(l, -1)) {
|
||||
case LUA_TSTRING:
|
||||
|
|
@ -790,17 +827,30 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
lua_pushlightuserdata(l, json_lightudata_mask(&json_array));
|
||||
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, cfg, current_depth, json, len);
|
||||
json_append_array(l, cfg, current_depth, json, len, raw);
|
||||
} else {
|
||||
len = lua_array_length(l, cfg, json);
|
||||
|
||||
if (len > 0 || (len == 0 && !cfg->encode_empty_table_as_object)) {
|
||||
json_append_array(l, cfg, current_depth, json, len);
|
||||
json_append_array(l, cfg, current_depth, json, len, raw);
|
||||
} else {
|
||||
if (has_metatable) {
|
||||
lua_getmetatable(l, -1);
|
||||
|
|
@ -810,7 +860,9 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
as_array = lua_rawequal(l, -1, -2);
|
||||
lua_pop(l, 2); /* pop pointer + metatable */
|
||||
if (as_array) {
|
||||
json_append_array(l, cfg, current_depth, json, 0);
|
||||
len = lua_objlen(l, -1);
|
||||
raw = 1;
|
||||
json_append_array(l, cfg, current_depth, json, len, raw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -825,7 +877,7 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
|
|||
if (lua_touserdata(l, -1) == NULL) {
|
||||
strbuf_append_mem(json, "null", 4);
|
||||
} else if (lua_touserdata(l, -1) == json_lightudata_mask(&json_array)) {
|
||||
json_append_array(l, cfg, current_depth, json, 0);
|
||||
json_append_array(l, cfg, current_depth, json, 0, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -848,7 +900,7 @@ static int json_encode(lua_State *l)
|
|||
strbuf_t local_encode_buf;
|
||||
strbuf_t *encode_buf;
|
||||
char *json;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
|
||||
|
||||
|
|
@ -1138,13 +1190,19 @@ 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)
|
||||
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;
|
||||
}
|
||||
|
|
@ -1380,6 +1438,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;;
|
||||
|
|
@ -1595,7 +1656,7 @@ static int lua_cjson_safe_new(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int luaopen_cjson(lua_State *l)
|
||||
CJSON_EXPORT int luaopen_cjson(lua_State *l)
|
||||
{
|
||||
lua_cjson_new(l);
|
||||
|
||||
|
|
@ -1609,7 +1670,7 @@ int luaopen_cjson(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int luaopen_cjson_safe(lua_State *l)
|
||||
CJSON_EXPORT int luaopen_cjson_safe(lua_State *l)
|
||||
{
|
||||
lua_cjson_safe_new(l);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
= Lua CJSON 2.1devel Manual =
|
||||
Mark Pulford <mark@kyne.com.au>
|
||||
:revdate: 1st March 2012
|
||||
:revdate: August 2016
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
|
@ -20,7 +20,7 @@ The Lua CJSON module provides JSON support for Lua.
|
|||
Lua CJSON is covered by the MIT license. Review the file +LICENSE+ for
|
||||
details.
|
||||
|
||||
The latest version of this software is available from the
|
||||
The current stable version of this software is available from the
|
||||
http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CJSON website].
|
||||
|
||||
Feel free to email me if you have any patches, suggestions, or comments.
|
||||
|
|
@ -29,8 +29,8 @@ Feel free to email me if you have any patches, suggestions, or comments.
|
|||
Installation
|
||||
------------
|
||||
|
||||
Lua CJSON requires either http://www.lua.org[Lua] 5.1, Lua 5.2, or
|
||||
http://www.luajit.org[LuaJIT] to build.
|
||||
Lua CJSON requires either http://www.lua.org[Lua] 5.1, Lua 5.2, Lua 5.3,
|
||||
or http://www.luajit.org[LuaJIT] to build.
|
||||
|
||||
The build method can be selected from 4 options:
|
||||
|
||||
|
|
@ -203,8 +203,8 @@ Import Lua CJSON via the Lua +require+ function. Lua CJSON does not
|
|||
register a global module table.
|
||||
|
||||
The +cjson+ module will throw an error during JSON conversion if any
|
||||
invalid data is encountered. Refer to <<cjson_encode,+cjson.encode+>>
|
||||
and <<cjson_decode,+cjson.decode+>> for details.
|
||||
invalid data is encountered. Refer to <<encode,+cjson.encode+>> and
|
||||
<<decode,+cjson.decode+>> for details.
|
||||
|
||||
The +cjson.safe+ module behaves identically to the +cjson+ module,
|
||||
except when errors are encountered during JSON conversion. On error, the
|
||||
|
|
@ -238,6 +238,7 @@ workaround if required. Lua CJSON should be reinitialised via
|
|||
different locale per thread is not supported.
|
||||
|
||||
|
||||
[[decode]]
|
||||
decode
|
||||
~~~~~~
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ http://chiselapp.com/user/dhkolf/repository/dkjson/[DKJSON 2.1]::
|
|||
https://github.com/brimworks/lua-yajl[Lua YAJL 2.0]::
|
||||
- C wrapper for the YAJL library
|
||||
|
||||
http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CSJON 2.0.0]::
|
||||
http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CJSON 2.0.0]::
|
||||
- C implementation with no dependencies on other libraries
|
||||
|
||||
|
||||
116
strbuf.c
116
strbuf.c
|
|
@ -26,6 +26,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "strbuf.h"
|
||||
|
||||
|
|
@ -38,38 +39,38 @@ static void die(const char *fmt, ...)
|
|||
va_end(arg);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exit(-1);
|
||||
abort();
|
||||
}
|
||||
|
||||
void strbuf_init(strbuf_t *s, int len)
|
||||
void strbuf_init(strbuf_t *s, size_t len)
|
||||
{
|
||||
int size;
|
||||
size_t size;
|
||||
|
||||
if (len <= 0)
|
||||
if (!len)
|
||||
size = STRBUF_DEFAULT_SIZE;
|
||||
else
|
||||
size = len + 1; /* \0 terminator */
|
||||
|
||||
size = len + 1;
|
||||
if (size < len)
|
||||
die("Overflow, len: %zu", len);
|
||||
s->buf = NULL;
|
||||
s->size = size;
|
||||
s->length = 0;
|
||||
s->increment = STRBUF_DEFAULT_INCREMENT;
|
||||
s->dynamic = 0;
|
||||
s->reallocs = 0;
|
||||
s->debug = 0;
|
||||
|
||||
s->buf = malloc(size);
|
||||
s->buf = (char *)malloc(size);
|
||||
if (!s->buf)
|
||||
die("Out of memory");
|
||||
|
||||
strbuf_ensure_null(s);
|
||||
}
|
||||
|
||||
strbuf_t *strbuf_new(int len)
|
||||
strbuf_t *strbuf_new(size_t len)
|
||||
{
|
||||
strbuf_t *s;
|
||||
|
||||
s = malloc(sizeof(strbuf_t));
|
||||
s = (strbuf_t*)malloc(sizeof(strbuf_t));
|
||||
if (!s)
|
||||
die("Out of memory");
|
||||
|
||||
|
|
@ -81,20 +82,10 @@ strbuf_t *strbuf_new(int len)
|
|||
return s;
|
||||
}
|
||||
|
||||
void strbuf_set_increment(strbuf_t *s, int increment)
|
||||
{
|
||||
/* Increment > 0: Linear buffer growth rate
|
||||
* Increment < -1: Exponential buffer growth rate */
|
||||
if (increment == 0 || increment == -1)
|
||||
die("BUG: Invalid string increment");
|
||||
|
||||
s->increment = increment;
|
||||
}
|
||||
|
||||
static inline void debug_stats(strbuf_t *s)
|
||||
{
|
||||
if (s->debug) {
|
||||
fprintf(stderr, "strbuf(%lx) reallocs: %d, length: %d, size: %d\n",
|
||||
fprintf(stderr, "strbuf(%lx) reallocs: %d, length: %zd, size: %zd\n",
|
||||
(long)s, s->reallocs, s->length, s->size);
|
||||
}
|
||||
}
|
||||
|
|
@ -113,7 +104,7 @@ void strbuf_free(strbuf_t *s)
|
|||
free(s);
|
||||
}
|
||||
|
||||
char *strbuf_free_to_string(strbuf_t *s, int *len)
|
||||
char *strbuf_free_to_string(strbuf_t *s, size_t *len)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
|
|
@ -131,57 +122,63 @@ char *strbuf_free_to_string(strbuf_t *s, int *len)
|
|||
return buf;
|
||||
}
|
||||
|
||||
static int calculate_new_size(strbuf_t *s, int len)
|
||||
static size_t calculate_new_size(strbuf_t *s, size_t len)
|
||||
{
|
||||
int reqsize, newsize;
|
||||
size_t reqsize, newsize;
|
||||
|
||||
if (len <= 0)
|
||||
die("BUG: Invalid strbuf length requested");
|
||||
|
||||
/* Ensure there is room for optional NULL termination */
|
||||
reqsize = len + 1;
|
||||
if (reqsize < len)
|
||||
die("Overflow, len: %zu", len);
|
||||
|
||||
/* If the user has requested to shrink the buffer, do it exactly */
|
||||
if (s->size > reqsize)
|
||||
return reqsize;
|
||||
|
||||
newsize = s->size;
|
||||
if (s->increment < 0) {
|
||||
if (reqsize >= SIZE_MAX / 2) {
|
||||
newsize = reqsize;
|
||||
} else {
|
||||
/* Exponential sizing */
|
||||
while (newsize < reqsize)
|
||||
newsize *= -s->increment;
|
||||
} else if (s->increment != 0) {
|
||||
/* Linear sizing */
|
||||
newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;
|
||||
newsize *= 2;
|
||||
}
|
||||
|
||||
if (newsize < reqsize)
|
||||
die("BUG: strbuf length would overflow, len: %zu", len);
|
||||
|
||||
|
||||
return newsize;
|
||||
}
|
||||
|
||||
|
||||
/* Ensure strbuf can handle a string length bytes long (ignoring NULL
|
||||
* optional termination). */
|
||||
void strbuf_resize(strbuf_t *s, int len)
|
||||
void strbuf_resize(strbuf_t *s, size_t len)
|
||||
{
|
||||
int newsize;
|
||||
size_t newsize;
|
||||
|
||||
newsize = calculate_new_size(s, len);
|
||||
|
||||
if (s->debug > 1) {
|
||||
fprintf(stderr, "strbuf(%lx) resize: %d => %d\n",
|
||||
fprintf(stderr, "strbuf(%lx) resize: %zd => %zd\n",
|
||||
(long)s, s->size, newsize);
|
||||
}
|
||||
|
||||
s->size = newsize;
|
||||
s->buf = realloc(s->buf, s->size);
|
||||
s->buf = (char *)realloc(s->buf, s->size);
|
||||
if (!s->buf)
|
||||
die("Out of memory");
|
||||
die("Out of memory, len: %zu", len);
|
||||
s->reallocs++;
|
||||
}
|
||||
|
||||
void strbuf_append_string(strbuf_t *s, const char *str)
|
||||
{
|
||||
int space, i;
|
||||
int i;
|
||||
size_t space;
|
||||
|
||||
space = strbuf_empty_length(s);
|
||||
|
||||
|
|
@ -197,55 +194,6 @@ void strbuf_append_string(strbuf_t *s, const char *str)
|
|||
}
|
||||
}
|
||||
|
||||
/* strbuf_append_fmt() should only be used when an upper bound
|
||||
* is known for the output string. */
|
||||
void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
int fmt_len;
|
||||
|
||||
strbuf_ensure_empty_length(s, len);
|
||||
|
||||
va_start(arg, fmt);
|
||||
fmt_len = vsnprintf(s->buf + s->length, len, fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (fmt_len < 0)
|
||||
die("BUG: Unable to convert number"); /* This should never happen.. */
|
||||
|
||||
s->length += fmt_len;
|
||||
}
|
||||
|
||||
/* strbuf_append_fmt_retry() can be used when the there is no known
|
||||
* upper bound for the output string. */
|
||||
void strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
int fmt_len, try;
|
||||
int empty_len;
|
||||
|
||||
/* If the first attempt to append fails, resize the buffer appropriately
|
||||
* and try again */
|
||||
for (try = 0; ; try++) {
|
||||
va_start(arg, fmt);
|
||||
/* Append the new formatted string */
|
||||
/* fmt_len is the length of the string required, excluding the
|
||||
* trailing NULL */
|
||||
empty_len = strbuf_empty_length(s);
|
||||
/* Add 1 since there is also space to store the terminating NULL. */
|
||||
fmt_len = vsnprintf(s->buf + s->length, empty_len + 1, fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
if (fmt_len <= empty_len)
|
||||
break; /* SUCCESS */
|
||||
if (try > 0)
|
||||
die("BUG: length of formatted string changed");
|
||||
|
||||
strbuf_resize(s, s->length + fmt_len);
|
||||
}
|
||||
|
||||
s->length += fmt_len;
|
||||
}
|
||||
|
||||
/* vi:ai et sw=4 ts=4:
|
||||
*/
|
||||
|
|
|
|||
46
strbuf.h
46
strbuf.h
|
|
@ -32,15 +32,13 @@
|
|||
|
||||
/* Size: Total bytes allocated to *buf
|
||||
* Length: String length, excluding optional NULL terminator.
|
||||
* Increment: Allocation increments when resizing the string buffer.
|
||||
* Dynamic: True if created via strbuf_new()
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char *buf;
|
||||
int size;
|
||||
int length;
|
||||
int increment;
|
||||
size_t size;
|
||||
size_t length;
|
||||
int dynamic;
|
||||
int reallocs;
|
||||
int debug;
|
||||
|
|
@ -49,33 +47,27 @@ typedef struct {
|
|||
#ifndef STRBUF_DEFAULT_SIZE
|
||||
#define STRBUF_DEFAULT_SIZE 1023
|
||||
#endif
|
||||
#ifndef STRBUF_DEFAULT_INCREMENT
|
||||
#define STRBUF_DEFAULT_INCREMENT -2
|
||||
#endif
|
||||
|
||||
/* Initialise */
|
||||
extern strbuf_t *strbuf_new(int len);
|
||||
extern void strbuf_init(strbuf_t *s, int len);
|
||||
extern void strbuf_set_increment(strbuf_t *s, int increment);
|
||||
extern strbuf_t *strbuf_new(size_t len);
|
||||
extern void strbuf_init(strbuf_t *s, size_t len);
|
||||
|
||||
/* Release */
|
||||
extern void strbuf_free(strbuf_t *s);
|
||||
extern char *strbuf_free_to_string(strbuf_t *s, int *len);
|
||||
extern char *strbuf_free_to_string(strbuf_t *s, size_t *len);
|
||||
|
||||
/* Management */
|
||||
extern void strbuf_resize(strbuf_t *s, int len);
|
||||
static int strbuf_empty_length(strbuf_t *s);
|
||||
static int strbuf_length(strbuf_t *s);
|
||||
static char *strbuf_string(strbuf_t *s, int *len);
|
||||
static void strbuf_ensure_empty_length(strbuf_t *s, int len);
|
||||
extern void strbuf_resize(strbuf_t *s, size_t len);
|
||||
static size_t strbuf_empty_length(strbuf_t *s);
|
||||
static size_t strbuf_length(strbuf_t *s);
|
||||
static char *strbuf_string(strbuf_t *s, size_t *len);
|
||||
static void strbuf_ensure_empty_length(strbuf_t *s, size_t len);
|
||||
static char *strbuf_empty_ptr(strbuf_t *s);
|
||||
static void strbuf_extend_length(strbuf_t *s, int len);
|
||||
static void strbuf_extend_length(strbuf_t *s, size_t len);
|
||||
static void strbuf_set_length(strbuf_t *s, int len);
|
||||
|
||||
/* Update */
|
||||
extern void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...);
|
||||
extern void strbuf_append_fmt_retry(strbuf_t *s, const char *format, ...);
|
||||
static void strbuf_append_mem(strbuf_t *s, const char *c, int len);
|
||||
static void strbuf_append_mem(strbuf_t *s, const char *c, size_t len);
|
||||
extern void strbuf_append_string(strbuf_t *s, const char *str);
|
||||
static void strbuf_append_char(strbuf_t *s, const char c);
|
||||
static void strbuf_ensure_null(strbuf_t *s);
|
||||
|
|
@ -93,12 +85,12 @@ static inline int strbuf_allocated(strbuf_t *s)
|
|||
|
||||
/* Return bytes remaining in the string buffer
|
||||
* Ensure there is space for a NULL terminator. */
|
||||
static inline int strbuf_empty_length(strbuf_t *s)
|
||||
static inline size_t strbuf_empty_length(strbuf_t *s)
|
||||
{
|
||||
return s->size - s->length - 1;
|
||||
}
|
||||
|
||||
static inline void strbuf_ensure_empty_length(strbuf_t *s, int len)
|
||||
static inline void strbuf_ensure_empty_length(strbuf_t *s, size_t len)
|
||||
{
|
||||
if (len > strbuf_empty_length(s))
|
||||
strbuf_resize(s, s->length + len);
|
||||
|
|
@ -114,12 +106,12 @@ static inline void strbuf_set_length(strbuf_t *s, int len)
|
|||
s->length = len;
|
||||
}
|
||||
|
||||
static inline void strbuf_extend_length(strbuf_t *s, int len)
|
||||
static inline void strbuf_extend_length(strbuf_t *s, size_t len)
|
||||
{
|
||||
s->length += len;
|
||||
}
|
||||
|
||||
static inline int strbuf_length(strbuf_t *s)
|
||||
static inline size_t strbuf_length(strbuf_t *s)
|
||||
{
|
||||
return s->length;
|
||||
}
|
||||
|
|
@ -135,14 +127,14 @@ static inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)
|
|||
s->buf[s->length++] = c;
|
||||
}
|
||||
|
||||
static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)
|
||||
static inline void strbuf_append_mem(strbuf_t *s, const char *c, size_t len)
|
||||
{
|
||||
strbuf_ensure_empty_length(s, len);
|
||||
memcpy(s->buf + s->length, c, len);
|
||||
s->length += len;
|
||||
}
|
||||
|
||||
static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, int len)
|
||||
static inline void strbuf_append_mem_unsafe(strbuf_t *s, const char *c, size_t len)
|
||||
{
|
||||
memcpy(s->buf + s->length, c, len);
|
||||
s->length += len;
|
||||
|
|
@ -153,7 +145,7 @@ static inline void strbuf_ensure_null(strbuf_t *s)
|
|||
s->buf[s->length] = 0;
|
||||
}
|
||||
|
||||
static inline char *strbuf_string(strbuf_t *s, int *len)
|
||||
static inline char *strbuf_string(strbuf_t *s, size_t *len)
|
||||
{
|
||||
if (len)
|
||||
*len = s->length;
|
||||
|
|
|
|||
|
|
@ -332,3 +332,45 @@ Cannot serialise function: type not supported
|
|||
|
||||
{"valid":"valid"}
|
||||
["one","two","three"]
|
||||
|
||||
|
||||
|
||||
=== TEST 23: array-like proxy object with __len and __index
|
||||
--- lua
|
||||
local cjson = require "cjson"
|
||||
local real_array = {"foo", "bar", "baz"}
|
||||
local proxy_array = {}
|
||||
setmetatable(proxy_array, {
|
||||
__len = function() return 3 end,
|
||||
__index = function(t, k)
|
||||
return real_array[k]
|
||||
end,
|
||||
})
|
||||
|
||||
print(cjson.encode(proxy_array))
|
||||
--- out
|
||||
["foo","bar","baz"]
|
||||
|
||||
|
||||
|
||||
=== TEST 24: check that integers are handled correctly on Lua 5.3+
|
||||
--- lua
|
||||
local lv = tonumber((_VERSION):match("Lua 5%.([0-9]+)"))
|
||||
|
||||
if lv >= 3 then
|
||||
local cjson = require "cjson"
|
||||
local array = cjson.decode [[ [10, 10.0, 3.5] ]]
|
||||
for i = 1, 4 do
|
||||
print(tostring(i) .. ": " .. tostring(math.type(array[i])))
|
||||
end
|
||||
else
|
||||
print("1: integer")
|
||||
print("2: float")
|
||||
print("3: float")
|
||||
print("4: nil")
|
||||
end
|
||||
--- out
|
||||
1: integer
|
||||
2: float
|
||||
3: float
|
||||
4: nil
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
# cff03b039d850f370a7362f3313e5268
|
||||
|
||||
use strict;
|
||||
no warnings 'nonchar';
|
||||
|
||||
# 0xD800 - 0xDFFF are used to encode supplementary codepoints
|
||||
# 0x10000 - 0x10FFFF are supplementary codepoints
|
||||
|
|
|
|||
Loading…
Reference in a new issue