aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2024-06-10 22:39:55 -0300
committerGitHub <noreply@github.com>2024-06-11 09:39:55 +0800
commitc92ecda53337490633c95e6ae00e322dc9ad1fb8 (patch)
tree47185f92938547b2c70fcf00b02c9acef772ac9c
parentd20576d5cef3d7aa3b6d62db7aee9d9d5f03cc70 (diff)
downloadlua-cjson-c92ecda53337490633c95e6ae00e322dc9ad1fb8.tar.gz
lua-cjson-c92ecda53337490633c95e6ae00e322dc9ad1fb8.tar.bz2
lua-cjson-c92ecda53337490633c95e6ae00e322dc9ad1fb8.zip
feature: Lua 5.3 + 5.4 integer support, with CI and conflicts fixed.
Co-Authored-By: Hisham Muhammad <hisham@gobolinux.org> Co-authored-by: Mark Pulford <mark@kyne.com.au> Co-authored-by: ichenq <ichenq@gmail.com> Co-authored-by: Cloud Wu <cloudwu@gmail.com> Co-authored-by: caijietao <t0350.prog@gmail.com> Co-authored-by: actboy168 <actboy168@gmail.com> Co-authored-by: wudeng <wudeng256@gmail.com> Co-authored-by: caiyiheng <rangercyh@qq.com>
-rw-r--r--.github/workflows/test.yml4
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt7
-rw-r--r--Makefile8
-rwxr-xr-xbuild-packages.sh2
-rw-r--r--dtoa.c111
-rw-r--r--fpconv.c2
-rw-r--r--lua-cjson-2.1.0.14-1.rockspec (renamed from lua-cjson-2.1.0.12-1.rockspec)4
-rw-r--r--lua-cjson.spec2
-rw-r--r--lua_cjson.c104
-rw-r--r--manual.adoc (renamed from manual.txt)13
-rw-r--r--performance.adoc (renamed from performance.txt)2
-rw-r--r--strbuf.c6
-rw-r--r--tests/agentzh.t42
-rwxr-xr-xtests/genutf8.pl1
15 files changed, 236 insertions, 73 deletions
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 74fdf1f..5567f63 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -17,7 +17,7 @@ jobs:
17 runtestArgs: "LUA_INCLUDE_DIR=.lua/include/luajit-2.1" 17 runtestArgs: "LUA_INCLUDE_DIR=.lua/include/luajit-2.1"
18 runtestEnv: "SKIP_CMAKE=1" 18 runtestEnv: "SKIP_CMAKE=1"
19 19
20 runs-on: ubuntu-latest 20 runs-on: ubuntu-24.04
21 21
22 steps: 22 steps:
23 - uses: actions/checkout@master 23 - uses: actions/checkout@master
@@ -47,7 +47,7 @@ jobs:
47 sudo cpanm --notest Test::Base Test::LongString 47 sudo cpanm --notest Test::Base Test::LongString
48 48
49 - name: cppcheck 49 - name: cppcheck
50 run: cppcheck -i .lua/ -i .install/ -i dtoa.c --force --error-exitcode=1 --enable=warning . 50 run: cppcheck -i .lua/ -i .install/ -i dtoa.c --force --error-exitcode=1 --enable=warning --inline-suppr .
51 51
52 - name: prove 52 - name: prove
53 run: LUA_BIN=lua prove -Itests tests 53 run: LUA_BIN=lua prove -Itests tests
diff --git a/.gitignore b/.gitignore
index b767889..d9b1095 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
1*.html 1*.html
2*.o 2*.o
3*.so 3*.so
4*.a
4notes 5notes
5packages 6packages
6tags 7tags
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f7eaf89..8ac6d38 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -68,6 +68,13 @@ else()
68 set(_lua_module_dir "${_lua_lib_dir}/lua/5.1") 68 set(_lua_module_dir "${_lua_lib_dir}/lua/5.1")
69endif() 69endif()
70 70
71if(MSVC)
72 add_definitions(-D_CRT_SECURE_NO_WARNINGS)
73 add_definitions(-Dinline=__inline)
74 add_definitions(-Dsnprintf=_snprintf)
75 add_definitions(-Dstrncasecmp=_strnicmp)
76endif()
77
71add_library(cjson MODULE lua_cjson.c strbuf.c ${FPCONV_SOURCES}) 78add_library(cjson MODULE lua_cjson.c strbuf.c ${FPCONV_SOURCES})
72set_target_properties(cjson PROPERTIES PREFIX "") 79set_target_properties(cjson PROPERTIES PREFIX "")
73target_link_libraries(cjson ${_MODULE_LINK}) 80target_link_libraries(cjson ${_MODULE_LINK})
diff --git a/Makefile b/Makefile
index 55c2142..c5966c5 100644
--- a/Makefile
+++ b/Makefile
@@ -23,6 +23,8 @@ LUA_CMODULE_DIR ?= $(PREFIX)/lib/lua/$(LUA_VERSION)
23LUA_MODULE_DIR ?= $(PREFIX)/share/lua/$(LUA_VERSION) 23LUA_MODULE_DIR ?= $(PREFIX)/share/lua/$(LUA_VERSION)
24LUA_BIN_DIR ?= $(PREFIX)/bin 24LUA_BIN_DIR ?= $(PREFIX)/bin
25 25
26AR= $(CC) -o
27
26##### Platform overrides ##### 28##### Platform overrides #####
27## 29##
28## Tweak one of the platform sections below to suit your situation. 30## Tweak one of the platform sections below to suit your situation.
@@ -84,12 +86,12 @@ OBJS = lua_cjson.o strbuf.o $(FPCONV_OBJS)
84 86
85.PHONY: all clean install install-extra doc 87.PHONY: all clean install install-extra doc
86 88
87.SUFFIXES: .html .txt 89.SUFFIXES: .html .adoc
88 90
89.c.o: 91.c.o:
90 $(CC) -c $(CFLAGS) $(CPPFLAGS) $(BUILD_CFLAGS) -o $@ $< 92 $(CC) -c $(CFLAGS) $(CPPFLAGS) $(BUILD_CFLAGS) -o $@ $<
91 93
92.txt.html: 94.adoc.html:
93 $(ASCIIDOC) -n -a toc $< 95 $(ASCIIDOC) -n -a toc $<
94 96
95all: $(TARGET) 97all: $(TARGET)
@@ -97,7 +99,7 @@ all: $(TARGET)
97doc: manual.html performance.html 99doc: manual.html performance.html
98 100
99$(TARGET): $(OBJS) 101$(TARGET): $(OBJS)
100 $(CC) $(LDFLAGS) $(CJSON_LDFLAGS) -o $@ $(OBJS) 102 $(AR) $@ $(LDFLAGS) $(CJSON_LDFLAGS) $(OBJS)
101 103
102install: $(TARGET) 104install: $(TARGET)
103 mkdir -p $(DESTDIR)$(LUA_CMODULE_DIR) 105 mkdir -p $(DESTDIR)$(LUA_CMODULE_DIR)
diff --git a/build-packages.sh b/build-packages.sh
index 23a6f2e..2c45e66 100755
--- a/build-packages.sh
+++ b/build-packages.sh
@@ -5,7 +5,7 @@
5# Build packages. Use current checked out version, or a specific tag/commit. 5# Build packages. Use current checked out version, or a specific tag/commit.
6 6
7# Files requiring a version bump 7# Files requiring a version bump
8VERSION_FILES="lua-cjson-2.1devel-1.rockspec lua-cjson.spec lua_cjson.c manual.txt runtests.sh tests/test.lua" 8VERSION_FILES="lua-cjson-2.1devel-1.rockspec lua-cjson.spec lua_cjson.c manual.adoc runtests.sh tests/test.lua"
9 9
10[ "$1" ] && BRANCH="$1" || BRANCH="`git describe --match '[1-3].[0-9]*'`" 10[ "$1" ] && BRANCH="$1" || BRANCH="`git describe --match '[1-3].[0-9]*'`"
11VERSION="`git describe --match '[1-3].[0-9]*' $BRANCH`" 11VERSION="`git describe --match '[1-3].[0-9]*' $BRANCH`"
diff --git a/dtoa.c b/dtoa.c
index 8dac7b8..33fd6f0 100644
--- a/dtoa.c
+++ b/dtoa.c
@@ -1533,12 +1533,18 @@ ThInfo {
1533set_max_dtoa_threads(unsigned int n) 1533set_max_dtoa_threads(unsigned int n)
1534{ 1534{
1535 size_t L; 1535 size_t L;
1536 ThInfo *newTI1;
1536 1537
1537 if (n > maxthreads) { 1538 if (n > maxthreads) {
1538 L = n*sizeof(ThInfo); 1539 L = n*sizeof(ThInfo);
1539 if (TI1) { 1540 if (TI1) {
1540 TI1 = (ThInfo*)REALLOC(TI1, L); 1541 newTI1 = (ThInfo*)REALLOC(TI1, L);
1541 memset(TI1 + maxthreads, 0, (n-maxthreads)*sizeof(ThInfo)); 1542 if (newTI1) {
1543 TI1 = newTI1;
1544 memset(TI1 + maxthreads, 0, (n-maxthreads)*sizeof(ThInfo));
1545 }
1546 else
1547 return;
1542 } 1548 }
1543 else { 1549 else {
1544 TI1 = (ThInfo*)MALLOC(L); 1550 TI1 = (ThInfo*)MALLOC(L);
@@ -1871,7 +1877,7 @@ mult(Bigint *a, Bigint *b MTd)
1871#else 1877#else
1872#ifdef Pack_32 1878#ifdef Pack_32
1873 for(; xb < xbe; xb++, xc0++) { 1879 for(; xb < xbe; xb++, xc0++) {
1874 if (y = *xb & 0xffff) { 1880 if ((y = *xb & 0xffff)) {
1875 x = xa; 1881 x = xa;
1876 xc = xc0; 1882 xc = xc0;
1877 carry = 0; 1883 carry = 0;
@@ -1885,7 +1891,7 @@ mult(Bigint *a, Bigint *b MTd)
1885 while(x < xae); 1891 while(x < xae);
1886 *xc = carry; 1892 *xc = carry;
1887 } 1893 }
1888 if (y = *xb >> 16) { 1894 if ((y = *xb >> 16)) {
1889 x = xa; 1895 x = xa;
1890 xc = xc0; 1896 xc = xc0;
1891 carry = 0; 1897 carry = 0;
@@ -2718,13 +2724,14 @@ enum { /* rounding values: same as FLT_ROUNDS */
2718 }; 2724 };
2719 2725
2720 void 2726 void
2721gethex( const char **sp, U *rvp, int rounding, int sign MTd) 2727gethex(const char **sp, U *rvp, int rounding, int sign MTd)
2722{ 2728{
2723 Bigint *b; 2729 Bigint *b;
2730 char d;
2724 const unsigned char *decpt, *s0, *s, *s1; 2731 const unsigned char *decpt, *s0, *s, *s1;
2725 Long e, e1; 2732 Long e, e1;
2726 ULong L, lostbits, *x; 2733 ULong L, lostbits, *x;
2727 int big, denorm, esign, havedig, k, n, nbits, up, zret; 2734 int big, denorm, esign, havedig, k, n, nb, nbits, nz, up, zret;
2728#ifdef IBM 2735#ifdef IBM
2729 int j; 2736 int j;
2730#endif 2737#endif
@@ -2742,6 +2749,9 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
2742#endif 2749#endif
2743#endif /*}}*/ 2750#endif /*}}*/
2744 }; 2751 };
2752#ifdef IEEE_Arith
2753 int check_denorm = 0;
2754#endif
2745#ifdef USE_LOCALE 2755#ifdef USE_LOCALE
2746 int i; 2756 int i;
2747#ifdef NO_LOCALE_CACHE 2757#ifdef NO_LOCALE_CACHE
@@ -2893,7 +2903,7 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
2893 k++; 2903 k++;
2894 b = Balloc(k MTa); 2904 b = Balloc(k MTa);
2895 x = b->x; 2905 x = b->x;
2896 n = 0; 2906 havedig = n = nz = 0;
2897 L = 0; 2907 L = 0;
2898#ifdef USE_LOCALE 2908#ifdef USE_LOCALE
2899 for(i = 0; decimalpoint[i+1]; ++i); 2909 for(i = 0; decimalpoint[i+1]; ++i);
@@ -2908,22 +2918,28 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
2908 if (*--s1 == '.') 2918 if (*--s1 == '.')
2909 continue; 2919 continue;
2910#endif 2920#endif
2921 if ((d = hexdig[*s1]))
2922 havedig = 1;
2923 else if (!havedig) {
2924 e += 4;
2925 continue;
2926 }
2911 if (n == ULbits) { 2927 if (n == ULbits) {
2912 *x++ = L; 2928 *x++ = L;
2913 L = 0; 2929 L = 0;
2914 n = 0; 2930 n = 0;
2915 } 2931 }
2916 L |= (hexdig[*s1] & 0x0f) << n; 2932 L |= (d & 0x0f) << n;
2917 n += 4; 2933 n += 4;
2918 } 2934 }
2919 *x++ = L; 2935 *x++ = L;
2920 b->wds = n = x - b->x; 2936 b->wds = n = x - b->x;
2921 n = ULbits*n - hi0bits(L); 2937 nb = ULbits*n - hi0bits(L);
2922 nbits = Nbits; 2938 nbits = Nbits;
2923 lostbits = 0; 2939 lostbits = 0;
2924 x = b->x; 2940 x = b->x;
2925 if (n > nbits) { 2941 if (nb > nbits) {
2926 n -= nbits; 2942 n = nb - nbits;
2927 if (any_on(b,n)) { 2943 if (any_on(b,n)) {
2928 lostbits = 1; 2944 lostbits = 1;
2929 k = n - 1; 2945 k = n - 1;
@@ -2936,8 +2952,8 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
2936 rshift(b, n); 2952 rshift(b, n);
2937 e += n; 2953 e += n;
2938 } 2954 }
2939 else if (n < nbits) { 2955 else if (nb < nbits) {
2940 n = nbits - n; 2956 n = nbits - nb;
2941 b = lshift(b, n MTa); 2957 b = lshift(b, n MTa);
2942 e -= n; 2958 e -= n;
2943 x = b->x; 2959 x = b->x;
@@ -2992,12 +3008,49 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
2992 return; 3008 return;
2993 } 3009 }
2994 k = n - 1; 3010 k = n - 1;
3011#ifdef IEEE_Arith
3012 if (!k) {
3013 switch(rounding) {
3014 case Round_near:
3015 if (((b->x[0] & 3) == 3) || (lostbits && (b->x[0] & 1))) {
3016 multadd(b, 1, 1 MTa);
3017 emin_check:
3018 if (b->x[1] == (1 << (Exp_shift + 1))) {
3019 rshift(b,1);
3020 e = emin;
3021 goto normal;
3022 }
3023 }
3024 break;
3025 case Round_up:
3026 if (!sign && (lostbits || (b->x[0] & 1))) {
3027 incr_denorm:
3028 multadd(b, 1, 2 MTa);
3029 check_denorm = 1;
3030 lostbits = 0;
3031 goto emin_check;
3032 }
3033 break;
3034 case Round_down:
3035 if (sign && (lostbits || (b->x[0] & 1)))
3036 goto incr_denorm;
3037 break;
3038 }
3039 }
3040#endif
2995 if (lostbits) 3041 if (lostbits)
2996 lostbits = 1; 3042 lostbits = 1;
2997 else if (k > 0) 3043 else if (k > 0)
2998 lostbits = any_on(b,k); 3044 lostbits = any_on(b,k);
3045#ifdef IEEE_Arith
3046 else if (check_denorm)
3047 goto no_lostbits;
3048#endif
2999 if (x[k>>kshift] & 1 << (k & kmask)) 3049 if (x[k>>kshift] & 1 << (k & kmask))
3000 lostbits |= 2; 3050 lostbits |= 2;
3051#ifdef IEEE_Arith
3052 no_lostbits:
3053#endif
3001 nbits -= n; 3054 nbits -= n;
3002 rshift(b,n); 3055 rshift(b,n);
3003 e = emin; 3056 e = emin;
@@ -3022,16 +3075,9 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
3022 k = b->wds; 3075 k = b->wds;
3023 b = increment(b MTa); 3076 b = increment(b MTa);
3024 x = b->x; 3077 x = b->x;
3025 if (denorm) { 3078 if (!denorm && (b->wds > k
3026#if 0
3027 if (nbits == Nbits - 1
3028 && x[nbits >> kshift] & 1 << (nbits & kmask))
3029 denorm = 0; /* not currently used */
3030#endif
3031 }
3032 else if (b->wds > k
3033 || ((n = nbits & kmask) !=0 3079 || ((n = nbits & kmask) !=0
3034 && hi0bits(x[k-1]) < 32-n)) { 3080 && hi0bits(x[k-1]) < 32-n))) {
3035 rshift(b,1); 3081 rshift(b,1);
3036 if (++e > Emax) 3082 if (++e > Emax)
3037 goto ovfl; 3083 goto ovfl;
@@ -3041,8 +3087,10 @@ gethex( const char **sp, U *rvp, int rounding, int sign MTd)
3041#ifdef IEEE_Arith 3087#ifdef IEEE_Arith
3042 if (denorm) 3088 if (denorm)
3043 word0(rvp) = b->wds > 1 ? b->x[1] & ~0x100000 : 0; 3089 word0(rvp) = b->wds > 1 ? b->x[1] & ~0x100000 : 0;
3044 else 3090 else {
3091 normal:
3045 word0(rvp) = (b->x[1] & ~0x100000) | ((e + 0x3ff + 52) << 20); 3092 word0(rvp) = (b->x[1] & ~0x100000) | ((e + 0x3ff + 52) << 20);
3093 }
3046 word1(rvp) = b->x[0]; 3094 word1(rvp) = b->x[0];
3047#endif 3095#endif
3048#ifdef IBM 3096#ifdef IBM
@@ -3409,6 +3457,7 @@ retlow1:
3409 if ((j = ((word0(rv) & Exp_mask) >> Exp_shift) - bc->scale) <= 0) { 3457 if ((j = ((word0(rv) & Exp_mask) >> Exp_shift) - bc->scale) <= 0) {
3410 i = 1 - j; 3458 i = 1 - j;
3411 if (i <= 31) { 3459 if (i <= 31) {
3460 /* cppcheck-suppress integerOverflowCond */
3412 if (word1(rv) & (0x1 << i)) 3461 if (word1(rv) & (0x1 << i))
3413 goto odd; 3462 goto odd;
3414 } 3463 }
@@ -3619,10 +3668,11 @@ fpconv_strtod(const char *s00, char **se)
3619 c = *++s; 3668 c = *++s;
3620 if (c > '0' && c <= '9') { 3669 if (c > '0' && c <= '9') {
3621 L = c - '0'; 3670 L = c - '0';
3622 s1 = s; 3671 while((c = *++s) >= '0' && c <= '9') {
3623 while((c = *++s) >= '0' && c <= '9') 3672 if (L <= 19999)
3624 L = 10*L + c - '0'; 3673 L = 10*L + c - '0';
3625 if (s - s1 > 8 || L > 19999) 3674 }
3675 if (L > 19999)
3626 /* Avoid confusion from exponents 3676 /* Avoid confusion from exponents
3627 * so large that e might overflow. 3677 * so large that e might overflow.
3628 */ 3678 */
@@ -4884,6 +4934,7 @@ nrv_alloc(const char *s, char *s0, size_t s0len, char **rve, int n MTd)
4884 s0 = rv_alloc(n MTa); 4934 s0 = rv_alloc(n MTa);
4885 else if (s0len <= n) { 4935 else if (s0len <= n) {
4886 rv = 0; 4936 rv = 0;
4937 /* cppcheck-suppress nullPointerArithmetic */
4887 t = rv + n; 4938 t = rv + n;
4888 goto rve_chk; 4939 goto rve_chk;
4889 } 4940 }
@@ -5237,9 +5288,11 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
5237#ifndef SET_INEXACT 5288#ifndef SET_INEXACT
5238#ifdef Check_FLT_ROUNDS 5289#ifdef Check_FLT_ROUNDS
5239 try_quick = Rounding == 1; 5290 try_quick = Rounding == 1;
5291#else
5292 try_quick = 1;
5240#endif 5293#endif
5241#endif /*SET_INEXACT*/ 5294#endif /*SET_INEXACT*/
5242#endif 5295#endif /*USE_BF96*/
5243 5296
5244 if (mode > 5) { 5297 if (mode > 5) {
5245 mode -= 4; 5298 mode -= 4;
@@ -5281,6 +5334,7 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
5281 else if (blen <= i) { 5334 else if (blen <= i) {
5282 buf = 0; 5335 buf = 0;
5283 if (rve) 5336 if (rve)
5337 /* cppcheck-suppress nullPointerArithmetic */
5284 *rve = buf + i; 5338 *rve = buf + i;
5285 return buf; 5339 return buf;
5286 } 5340 }
@@ -5469,6 +5523,7 @@ dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char
5469 res3 = p10->b1 * dbhi + (tv3 & 0xffffffffull); 5523 res3 = p10->b1 * dbhi + (tv3 & 0xffffffffull);
5470 res = p10->b0 * dbhi + (tv3>>32) + (res3>>32); 5524 res = p10->b0 * dbhi + (tv3>>32) + (res3>>32);
5471 be += p10->e - 0x3fe; 5525 be += p10->e - 0x3fe;
5526 /* cppcheck-suppress integerOverflowCond */
5472 eulp = j1 = be - 54 + ulpadj; 5527 eulp = j1 = be - 54 + ulpadj;
5473 if (!(res & 0x8000000000000000ull)) { 5528 if (!(res & 0x8000000000000000ull)) {
5474 --be; 5529 --be;
diff --git a/fpconv.c b/fpconv.c
index 0ef7f18..64208f8 100644
--- a/fpconv.c
+++ b/fpconv.c
@@ -130,7 +130,7 @@ double fpconv_strtod(const char *nptr, char **endptr)
130 /* Duplicate number into buffer */ 130 /* Duplicate number into buffer */
131 if (buflen >= FPCONV_G_FMT_BUFSIZE) { 131 if (buflen >= FPCONV_G_FMT_BUFSIZE) {
132 /* Handle unusually large numbers */ 132 /* Handle unusually large numbers */
133 buf = malloc(buflen + 1); 133 buf = (char *)malloc(buflen + 1);
134 if (!buf) { 134 if (!buf) {
135 fprintf(stderr, "Out of memory"); 135 fprintf(stderr, "Out of memory");
136 abort(); 136 abort();
diff --git a/lua-cjson-2.1.0.12-1.rockspec b/lua-cjson-2.1.0.14-1.rockspec
index 9ed4272..4376a08 100644
--- a/lua-cjson-2.1.0.12-1.rockspec
+++ b/lua-cjson-2.1.0.14-1.rockspec
@@ -1,9 +1,9 @@
1package = "lua-cjson" 1package = "lua-cjson"
2version = "2.1.0.11-1" 2version = "2.1.0.14-1"
3 3
4source = { 4source = {
5 url = "git+https://github.com/openresty/lua-cjson", 5 url = "git+https://github.com/openresty/lua-cjson",
6 tag = "2.1.0.11", 6 tag = "2.1.0.14",
7} 7}
8 8
9description = { 9description = {
diff --git a/lua-cjson.spec b/lua-cjson.spec
index 13fc56d..3d3cb16 100644
--- a/lua-cjson.spec
+++ b/lua-cjson.spec
@@ -50,7 +50,7 @@ rm -rf "$RPM_BUILD_ROOT"
50 50
51%files 51%files
52%defattr(-,root,root,-) 52%defattr(-,root,root,-)
53%doc LICENSE NEWS performance.html performance.txt manual.html manual.txt rfc4627.txt THANKS 53%doc LICENSE NEWS performance.html performance.adoc manual.html manual.adoc rfc4627.txt THANKS
54%{lualibdir}/* 54%{lualibdir}/*
55%{luadatadir}/* 55%{luadatadir}/*
56%{_bindir}/* 56%{_bindir}/*
diff --git a/lua_cjson.c b/lua_cjson.c
index ae178eb..bbd8eff 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -66,6 +66,13 @@
66 66
67#endif 67#endif
68 68
69#ifdef _MSC_VER
70#define CJSON_EXPORT __declspec(dllexport)
71#define strncasecmp(x,y,z) _strnicmp(x,y,z)
72#else
73#define CJSON_EXPORT extern
74#endif
75
69/* Workaround for Solaris platforms missing isinf() */ 76/* Workaround for Solaris platforms missing isinf() */
70#if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF)) 77#if !defined(isinf) && (defined(USE_INTERNAL_ISINF) || defined(MISSING_ISINF))
71#define isinf(x) (!isnan(x) && isnan((x) - (x))) 78#define isinf(x) (!isnan(x) && isnan((x) - (x)))
@@ -104,8 +111,8 @@
104#define json_lightudata_mask(ludata) (ludata) 111#define json_lightudata_mask(ludata) (ludata)
105#endif 112#endif
106 113
107#if LUA_VERSION_NUM > 501 114#if LUA_VERSION_NUM >= 502
108#define lua_objlen(L,i) lua_rawlen(L, (i)) 115#define lua_objlen(L,i) luaL_len(L, (i))
109#endif 116#endif
110 117
111static const char * const *json_empty_array; 118static const char * const *json_empty_array;
@@ -118,6 +125,7 @@ typedef enum {
118 T_ARR_END, 125 T_ARR_END,
119 T_STRING, 126 T_STRING,
120 T_NUMBER, 127 T_NUMBER,
128 T_INTEGER,
121 T_BOOLEAN, 129 T_BOOLEAN,
122 T_NULL, 130 T_NULL,
123 T_COLON, 131 T_COLON,
@@ -135,6 +143,7 @@ static const char *json_token_type_name[] = {
135 "T_ARR_END", 143 "T_ARR_END",
136 "T_STRING", 144 "T_STRING",
137 "T_NUMBER", 145 "T_NUMBER",
146 "T_INTEGER",
138 "T_BOOLEAN", 147 "T_BOOLEAN",
139 "T_NULL", 148 "T_NULL",
140 "T_COLON", 149 "T_COLON",
@@ -184,6 +193,7 @@ typedef struct {
184 union { 193 union {
185 const char *string; 194 const char *string;
186 double number; 195 double number;
196 lua_Integer integer;
187 int boolean; 197 int boolean;
188 } value; 198 } value;
189 size_t string_len; 199 size_t string_len;
@@ -234,7 +244,7 @@ static json_config_t *json_fetch_config(lua_State *l)
234{ 244{
235 json_config_t *cfg; 245 json_config_t *cfg;
236 246
237 cfg = lua_touserdata(l, lua_upvalueindex(1)); 247 cfg = (json_config_t *)lua_touserdata(l, lua_upvalueindex(1));
238 if (!cfg) 248 if (!cfg)
239 luaL_error(l, "BUG: Unable to fetch CJSON configuration"); 249 luaL_error(l, "BUG: Unable to fetch CJSON configuration");
240 250
@@ -443,7 +453,7 @@ static int json_destroy_config(lua_State *l)
443{ 453{
444 json_config_t *cfg; 454 json_config_t *cfg;
445 455
446 cfg = lua_touserdata(l, 1); 456 cfg = (json_config_t *)lua_touserdata(l, 1);
447 if (cfg) 457 if (cfg)
448 strbuf_free(&cfg->encode_buf); 458 strbuf_free(&cfg->encode_buf);
449 cfg = NULL; 459 cfg = NULL;
@@ -456,7 +466,7 @@ static void json_create_config(lua_State *l)
456 json_config_t *cfg; 466 json_config_t *cfg;
457 int i; 467 int i;
458 468
459 cfg = lua_newuserdata(l, sizeof(*cfg)); 469 cfg = (json_config_t *)lua_newuserdata(l, sizeof(*cfg));
460 if (!cfg) 470 if (!cfg)
461 abort(); 471 abort();
462 472
@@ -552,9 +562,9 @@ static void json_encode_exception(lua_State *l, json_config_t *cfg, strbuf_t *js
552static void json_append_string(lua_State *l, strbuf_t *json, int lindex) 562static void json_append_string(lua_State *l, strbuf_t *json, int lindex)
553{ 563{
554 const char *escstr; 564 const char *escstr;
555 unsigned i;
556 const char *str; 565 const char *str;
557 size_t len; 566 size_t len;
567 size_t i;
558 568
559 str = lua_tolstring(l, lindex, &len); 569 str = lua_tolstring(l, lindex, &len);
560 570
@@ -653,9 +663,9 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
653/* json_append_array args: 663/* json_append_array args:
654 * - lua_State 664 * - lua_State
655 * - JSON strbuf 665 * - JSON strbuf
656 * - Size of passwd Lua array (top of stack) */ 666 * - Size of passed Lua array (top of stack) */
657static void json_append_array(lua_State *l, json_config_t *cfg, int current_depth, 667static void json_append_array(lua_State *l, json_config_t *cfg, int current_depth,
658 strbuf_t *json, int array_length) 668 strbuf_t *json, int array_length, int raw)
659{ 669{
660 int comma, i, json_pos, err; 670 int comma, i, json_pos, err;
661 671
@@ -667,7 +677,17 @@ static void json_append_array(lua_State *l, json_config_t *cfg, int current_dept
667 if (comma++ > 0) 677 if (comma++ > 0)
668 strbuf_append_char(json, ','); 678 strbuf_append_char(json, ',');
669 679
670 lua_rawgeti(l, -1, i); 680 if (raw) {
681 lua_rawgeti(l, -1, i);
682 } else {
683#if LUA_VERSION_NUM >= 503
684 lua_geti(l, -1, i);
685#else
686 lua_pushinteger(l, i);
687 lua_gettable(l, -2);
688#endif
689 }
690
671 err = json_append_data(l, cfg, current_depth, json); 691 err = json_append_data(l, cfg, current_depth, json);
672 if (err) { 692 if (err) {
673 strbuf_set_length(json, json_pos); 693 strbuf_set_length(json, json_pos);
@@ -684,8 +704,17 @@ static void json_append_array(lua_State *l, json_config_t *cfg, int current_dept
684static void json_append_number(lua_State *l, json_config_t *cfg, 704static void json_append_number(lua_State *l, json_config_t *cfg,
685 strbuf_t *json, int lindex) 705 strbuf_t *json, int lindex)
686{ 706{
687 double num = lua_tonumber(l, lindex);
688 int len; 707 int len;
708#if LUA_VERSION_NUM >= 503
709 if (lua_isinteger(l, lindex)) {
710 lua_Integer num = lua_tointeger(l, lindex);
711 strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE); /* max length of int64 is 19 */
712 len = sprintf(strbuf_empty_ptr(json), LUA_INTEGER_FMT, num);
713 strbuf_extend_length(json, len);
714 return;
715 }
716#endif
717 double num = lua_tonumber(l, lindex);
689 718
690 if (cfg->encode_invalid_numbers == 0) { 719 if (cfg->encode_invalid_numbers == 0) {
691 /* Prevent encoding invalid numbers */ 720 /* Prevent encoding invalid numbers */
@@ -773,6 +802,7 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
773 int len; 802 int len;
774 int as_array = 0; 803 int as_array = 0;
775 int has_metatable; 804 int has_metatable;
805 int raw = 1;
776 806
777 switch (lua_type(l, -1)) { 807 switch (lua_type(l, -1)) {
778 case LUA_TSTRING: 808 case LUA_TSTRING:
@@ -797,17 +827,30 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
797 lua_pushlightuserdata(l, json_lightudata_mask(&json_array)); 827 lua_pushlightuserdata(l, json_lightudata_mask(&json_array));
798 lua_rawget(l, LUA_REGISTRYINDEX); 828 lua_rawget(l, LUA_REGISTRYINDEX);
799 as_array = lua_rawequal(l, -1, -2); 829 as_array = lua_rawequal(l, -1, -2);
800 lua_pop(l, 2); 830 if (as_array) {
831 raw = 1;
832 lua_pop(l, 2);
833 len = lua_objlen(l, -1);
834 } else {
835 raw = 0;
836 lua_pop(l, 2);
837 if (luaL_getmetafield(l, -1, "__len")) {
838 lua_pushvalue(l, -2);
839 lua_call(l, 1, 1);
840 len = lua_tonumber(l, -1);
841 lua_pop(l, 1);
842 as_array = 1;
843 }
844 }
801 } 845 }
802 846
803 if (as_array) { 847 if (as_array) {
804 len = lua_objlen(l, -1); 848 json_append_array(l, cfg, current_depth, json, len, raw);
805 json_append_array(l, cfg, current_depth, json, len);
806 } else { 849 } else {
807 len = lua_array_length(l, cfg, json); 850 len = lua_array_length(l, cfg, json);
808 851
809 if (len > 0 || (len == 0 && !cfg->encode_empty_table_as_object)) { 852 if (len > 0 || (len == 0 && !cfg->encode_empty_table_as_object)) {
810 json_append_array(l, cfg, current_depth, json, len); 853 json_append_array(l, cfg, current_depth, json, len, raw);
811 } else { 854 } else {
812 if (has_metatable) { 855 if (has_metatable) {
813 lua_getmetatable(l, -1); 856 lua_getmetatable(l, -1);
@@ -817,7 +860,9 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
817 as_array = lua_rawequal(l, -1, -2); 860 as_array = lua_rawequal(l, -1, -2);
818 lua_pop(l, 2); /* pop pointer + metatable */ 861 lua_pop(l, 2); /* pop pointer + metatable */
819 if (as_array) { 862 if (as_array) {
820 json_append_array(l, cfg, current_depth, json, 0); 863 len = lua_objlen(l, -1);
864 raw = 1;
865 json_append_array(l, cfg, current_depth, json, len, raw);
821 break; 866 break;
822 } 867 }
823 } 868 }
@@ -832,7 +877,7 @@ static int json_append_data(lua_State *l, json_config_t *cfg,
832 if (lua_touserdata(l, -1) == NULL) { 877 if (lua_touserdata(l, -1) == NULL) {
833 strbuf_append_mem(json, "null", 4); 878 strbuf_append_mem(json, "null", 4);
834 } else if (lua_touserdata(l, -1) == json_lightudata_mask(&json_array)) { 879 } else if (lua_touserdata(l, -1) == json_lightudata_mask(&json_array)) {
835 json_append_array(l, cfg, current_depth, json, 0); 880 json_append_array(l, cfg, current_depth, json, 0, 1);
836 } 881 }
837 break; 882 break;
838 default: 883 default:
@@ -1145,13 +1190,19 @@ static int json_is_invalid_number(json_parse_t *json)
1145static void json_next_number_token(json_parse_t *json, json_token_t *token) 1190static void json_next_number_token(json_parse_t *json, json_token_t *token)
1146{ 1191{
1147 char *endptr; 1192 char *endptr;
1148 1193 token->value.integer = strtoll(json->ptr, &endptr, 10);
1149 token->type = T_NUMBER; 1194 if (json->ptr == endptr || *endptr == '.' || *endptr == 'e' ||
1150 token->value.number = fpconv_strtod(json->ptr, &endptr); 1195 *endptr == 'E' || *endptr == 'x') {
1151 if (json->ptr == endptr) 1196 token->type = T_NUMBER;
1152 json_set_token_error(token, json, "invalid number"); 1197 token->value.number = fpconv_strtod(json->ptr, &endptr);
1153 else 1198 if (json->ptr == endptr) {
1154 json->ptr = endptr; /* Skip the processed number */ 1199 json_set_token_error(token, json, "invalid number");
1200 return;
1201 }
1202 } else {
1203 token->type = T_INTEGER;
1204 }
1205 json->ptr = endptr; /* Skip the processed number */
1155 1206
1156 return; 1207 return;
1157} 1208}
@@ -1387,6 +1438,9 @@ static void json_process_value(lua_State *l, json_parse_t *json,
1387 case T_NUMBER: 1438 case T_NUMBER:
1388 lua_pushnumber(l, token->value.number); 1439 lua_pushnumber(l, token->value.number);
1389 break;; 1440 break;;
1441 case T_INTEGER:
1442 lua_pushinteger(l, token->value.integer);
1443 break;;
1390 case T_BOOLEAN: 1444 case T_BOOLEAN:
1391 lua_pushboolean(l, token->value.boolean); 1445 lua_pushboolean(l, token->value.boolean);
1392 break;; 1446 break;;
@@ -1602,7 +1656,7 @@ static int lua_cjson_safe_new(lua_State *l)
1602 return 1; 1656 return 1;
1603} 1657}
1604 1658
1605int luaopen_cjson(lua_State *l) 1659CJSON_EXPORT int luaopen_cjson(lua_State *l)
1606{ 1660{
1607 lua_cjson_new(l); 1661 lua_cjson_new(l);
1608 1662
@@ -1616,7 +1670,7 @@ int luaopen_cjson(lua_State *l)
1616 return 1; 1670 return 1;
1617} 1671}
1618 1672
1619int luaopen_cjson_safe(lua_State *l) 1673CJSON_EXPORT int luaopen_cjson_safe(lua_State *l)
1620{ 1674{
1621 lua_cjson_safe_new(l); 1675 lua_cjson_safe_new(l);
1622 1676
diff --git a/manual.txt b/manual.adoc
index a12e378..83303a3 100644
--- a/manual.txt
+++ b/manual.adoc
@@ -1,6 +1,6 @@
1= Lua CJSON 2.1devel Manual = 1= Lua CJSON 2.1devel Manual =
2Mark Pulford <mark@kyne.com.au> 2Mark Pulford <mark@kyne.com.au>
3:revdate: 1st March 2012 3:revdate: August 2016
4 4
5Overview 5Overview
6-------- 6--------
@@ -20,7 +20,7 @@ The Lua CJSON module provides JSON support for Lua.
20Lua CJSON is covered by the MIT license. Review the file +LICENSE+ for 20Lua CJSON is covered by the MIT license. Review the file +LICENSE+ for
21details. 21details.
22 22
23The latest version of this software is available from the 23The current stable version of this software is available from the
24http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CJSON website]. 24http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CJSON website].
25 25
26Feel free to email me if you have any patches, suggestions, or comments. 26Feel 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.
29Installation 29Installation
30------------ 30------------
31 31
32Lua CJSON requires either http://www.lua.org[Lua] 5.1, Lua 5.2, or 32Lua CJSON requires either http://www.lua.org[Lua] 5.1, Lua 5.2, Lua 5.3,
33http://www.luajit.org[LuaJIT] to build. 33or http://www.luajit.org[LuaJIT] to build.
34 34
35The build method can be selected from 4 options: 35The build method can be selected from 4 options:
36 36
@@ -203,8 +203,8 @@ Import Lua CJSON via the Lua +require+ function. Lua CJSON does not
203register a global module table. 203register a global module table.
204 204
205The +cjson+ module will throw an error during JSON conversion if any 205The +cjson+ module will throw an error during JSON conversion if any
206invalid data is encountered. Refer to <<cjson_encode,+cjson.encode+>> 206invalid data is encountered. Refer to <<encode,+cjson.encode+>> and
207and <<cjson_decode,+cjson.decode+>> for details. 207<<decode,+cjson.decode+>> for details.
208 208
209The +cjson.safe+ module behaves identically to the +cjson+ module, 209The +cjson.safe+ module behaves identically to the +cjson+ module,
210except when errors are encountered during JSON conversion. On error, the 210except when errors are encountered during JSON conversion. On error, the
@@ -238,6 +238,7 @@ workaround if required. Lua CJSON should be reinitialised via
238different locale per thread is not supported. 238different locale per thread is not supported.
239 239
240 240
241[[decode]]
241decode 242decode
242~~~~~~ 243~~~~~~
243 244
diff --git a/performance.txt b/performance.adoc
index fc3a5bb..a36412d 100644
--- a/performance.txt
+++ b/performance.adoc
@@ -26,7 +26,7 @@ http://chiselapp.com/user/dhkolf/repository/dkjson/[DKJSON 2.1]::
26https://github.com/brimworks/lua-yajl[Lua YAJL 2.0]:: 26https://github.com/brimworks/lua-yajl[Lua YAJL 2.0]::
27 - C wrapper for the YAJL library 27 - C wrapper for the YAJL library
28 28
29http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CSJON 2.0.0]:: 29http://www.kyne.com.au/%7Emark/software/lua-cjson.php[Lua CJSON 2.0.0]::
30 - C implementation with no dependencies on other libraries 30 - C implementation with no dependencies on other libraries
31 31
32 32
diff --git a/strbuf.c b/strbuf.c
index 2dc30be..73cd9b8 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -59,7 +59,7 @@ void strbuf_init(strbuf_t *s, size_t len)
59 s->reallocs = 0; 59 s->reallocs = 0;
60 s->debug = 0; 60 s->debug = 0;
61 61
62 s->buf = malloc(size); 62 s->buf = (char *)malloc(size);
63 if (!s->buf) 63 if (!s->buf)
64 die("Out of memory"); 64 die("Out of memory");
65 65
@@ -70,7 +70,7 @@ strbuf_t *strbuf_new(size_t len)
70{ 70{
71 strbuf_t *s; 71 strbuf_t *s;
72 72
73 s = malloc(sizeof(strbuf_t)); 73 s = (strbuf_t*)malloc(sizeof(strbuf_t));
74 if (!s) 74 if (!s)
75 die("Out of memory"); 75 die("Out of memory");
76 76
@@ -169,7 +169,7 @@ void strbuf_resize(strbuf_t *s, size_t len)
169 } 169 }
170 170
171 s->size = newsize; 171 s->size = newsize;
172 s->buf = realloc(s->buf, s->size); 172 s->buf = (char *)realloc(s->buf, s->size);
173 if (!s->buf) 173 if (!s->buf)
174 die("Out of memory, len: %zu", len); 174 die("Out of memory, len: %zu", len);
175 s->reallocs++; 175 s->reallocs++;
diff --git a/tests/agentzh.t b/tests/agentzh.t
index 552630a..88a94b8 100644
--- a/tests/agentzh.t
+++ b/tests/agentzh.t
@@ -332,3 +332,45 @@ Cannot serialise function: type not supported
332 332
333{"valid":"valid"} 333{"valid":"valid"}
334["one","two","three"] 334["one","two","three"]
335
336
337
338=== TEST 23: array-like proxy object with __len and __index
339--- lua
340local cjson = require "cjson"
341local real_array = {"foo", "bar", "baz"}
342local proxy_array = {}
343setmetatable(proxy_array, {
344 __len = function() return 3 end,
345 __index = function(t, k)
346 return real_array[k]
347 end,
348})
349
350print(cjson.encode(proxy_array))
351--- out
352["foo","bar","baz"]
353
354
355
356=== TEST 24: check that integers are handled correctly on Lua 5.3+
357--- lua
358local lv = tonumber((_VERSION):match("Lua 5%.([0-9]+)"))
359
360if lv >= 3 then
361 local cjson = require "cjson"
362 local array = cjson.decode [[ [10, 10.0, 3.5] ]]
363 for i = 1, 4 do
364 print(tostring(i) .. ": " .. tostring(math.type(array[i])))
365 end
366else
367 print("1: integer")
368 print("2: float")
369 print("3: float")
370 print("4: nil")
371end
372--- out
3731: integer
3742: float
3753: float
3764: nil
diff --git a/tests/genutf8.pl b/tests/genutf8.pl
index db661a1..c79f238 100755
--- a/tests/genutf8.pl
+++ b/tests/genutf8.pl
@@ -6,6 +6,7 @@
6# cff03b039d850f370a7362f3313e5268 6# cff03b039d850f370a7362f3313e5268
7 7
8use strict; 8use strict;
9no warnings 'nonchar';
9 10
10# 0xD800 - 0xDFFF are used to encode supplementary codepoints 11# 0xD800 - 0xDFFF are used to encode supplementary codepoints
11# 0x10000 - 0x10FFFF are supplementary codepoints 12# 0x10000 - 0x10FFFF are supplementary codepoints