fix cjson bugs and reduce mem usage
This commit is contained in:
parent
c0d690ce7e
commit
54004a4beb
|
@ -1,44 +0,0 @@
|
|||
Version 2.1.0 (Mar 1 2012)
|
||||
* Added cjson.safe module interface which returns nil after an error
|
||||
* Improved Makefile compatibility with Solaris make
|
||||
|
||||
Version 2.0.0 (Jan 22 2012)
|
||||
* Improved platform compatibility for strtod/sprintf locale workaround
|
||||
* Added option to build with David Gay's dtoa.c for improved performance
|
||||
* Added support for Lua 5.2
|
||||
* Added option to encode infinity/NaN as JSON null
|
||||
* Fixed encode bug with a raised default limit and deeply nested tables
|
||||
* Updated Makefile for compatibility with non-GNU make implementations
|
||||
* Added CMake build support
|
||||
* Added HTML manual
|
||||
* Increased default nesting limit to 1000
|
||||
* Added support for re-entrant use of encode and decode
|
||||
* Added support for installing lua2json and json2lua utilities
|
||||
* Added encode_invalid_numbers() and decode_invalid_numbers()
|
||||
* Added decode_max_depth()
|
||||
* Removed registration of global cjson module table
|
||||
* Removed refuse_invalid_numbers()
|
||||
|
||||
Version 1.0.4 (Nov 30 2011)
|
||||
* Fixed numeric conversion under locales with a comma decimal separator
|
||||
|
||||
Version 1.0.3 (Sep 15 2011)
|
||||
* Fixed detection of objects with numeric string keys
|
||||
* Provided work around for missing isinf() on Solaris
|
||||
|
||||
Version 1.0.2 (May 30 2011)
|
||||
* Portability improvements for Windows
|
||||
- No longer links with -lm
|
||||
- Use "socket" instead of "posix" for sub-second timing
|
||||
* Removed UTF-8 test dependency on Perl Text::Iconv
|
||||
* Added simple CLI commands for testing Lua <-> JSON conversions
|
||||
* Added cjson.encode_number_precision()
|
||||
|
||||
Version 1.0.1 (May 10 2011)
|
||||
* Added build support for OSX
|
||||
* Removed unnecessary whitespace from JSON output
|
||||
* Added cjson.encode_keep_buffer()
|
||||
* Fixed memory leak on Lua stack overflow exception
|
||||
|
||||
Version 1.0 (May 9 2011)
|
||||
* Initial release
|
|
@ -184,7 +184,7 @@
|
|||
* a decimal expansion to decide close cases. This logic is only
|
||||
* used for input more than STRTOD_DIGLIM digits long (default 40).
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#include "dtoa_config.h"
|
||||
|
||||
#ifndef Long
|
||||
|
@ -4356,3 +4356,4 @@ dtoa
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef _DTOA_CONFIG_H
|
||||
#define _DTOA_CONFIG_H
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
@ -67,7 +67,7 @@ static pthread_mutex_t private_dtoa_lock[2] = {
|
|||
} while (0)
|
||||
|
||||
#endif /* MULTIPLE_THREADS */
|
||||
|
||||
#endif
|
||||
#endif /* _DTOA_CONFIG_H */
|
||||
|
||||
/* vi:ai et sw=4 ts=4:
|
|
@ -21,7 +21,7 @@
|
|||
* it suffices to declare buf
|
||||
* char buf[32];
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -109,3 +109,4 @@ fpconv_g_fmt(char *b, double x, int precision)
|
|||
#endif
|
||||
return b - b0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
package = "lua-cjson"
|
||||
version = "2.1devel-1"
|
||||
|
||||
source = {
|
||||
url = "http://www.kyne.com.au/~mark/software/download/lua-cjson-2.1devel.zip",
|
||||
}
|
||||
|
||||
description = {
|
||||
summary = "A fast JSON encoding/parsing module",
|
||||
detailed = [[
|
||||
The Lua CJSON module provides JSON support for Lua. It features:
|
||||
- Fast, standards compliant encoding/parsing routines
|
||||
- Full support for JSON with UTF-8, including decoding surrogate pairs
|
||||
- Optional run-time support for common exceptions to the JSON specification
|
||||
(infinity, NaN,..)
|
||||
- No dependencies on other libraries
|
||||
]],
|
||||
homepage = "http://www.kyne.com.au/~mark/software/lua-cjson.php",
|
||||
license = "MIT"
|
||||
}
|
||||
|
||||
dependencies = {
|
||||
"lua >= 5.1"
|
||||
}
|
||||
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
cjson = {
|
||||
sources = { "lua_cjson.c", "strbuf.c", "fpconv.c" },
|
||||
defines = {
|
||||
-- LuaRocks does not support platform specific configuration for Solaris.
|
||||
-- Uncomment the line below on Solaris platforms if required.
|
||||
-- "USE_INTERNAL_ISINF"
|
||||
}
|
||||
}
|
||||
},
|
||||
install = {
|
||||
lua = {
|
||||
["cjson.util"] = "lua/cjson/util.lua"
|
||||
},
|
||||
bin = {
|
||||
json2lua = "lua/json2lua.lua",
|
||||
lua2json = "lua/lua2json.lua"
|
||||
}
|
||||
},
|
||||
-- Override default build options (per platform)
|
||||
platforms = {
|
||||
win32 = { modules = { cjson = { defines = {
|
||||
"DISABLE_INVALID_NUMBERS"
|
||||
} } } }
|
||||
},
|
||||
copy_directories = { "tests" }
|
||||
}
|
||||
|
||||
-- vi:ai et sw=4 ts=4:
|
|
@ -1,80 +0,0 @@
|
|||
%define luaver 5.1
|
||||
%define lualibdir %{_libdir}/lua/%{luaver}
|
||||
%define luadatadir %{_datadir}/lua/%{luaver}
|
||||
|
||||
Name: lua-cjson
|
||||
Version: 2.1devel
|
||||
Release: 1%{?dist}
|
||||
Summary: A fast JSON encoding/parsing module for Lua
|
||||
|
||||
Group: Development/Libraries
|
||||
License: MIT
|
||||
URL: http://www.kyne.com.au/~mark/software/lua-cjson/
|
||||
Source0: http://www.kyne.com.au/~mark/software/lua-cjson/download/lua-cjson-%{version}.tar.gz
|
||||
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||
|
||||
BuildRequires: lua >= %{luaver}, lua-devel >= %{luaver}
|
||||
Requires: lua >= %{luaver}
|
||||
|
||||
%description
|
||||
The Lua CJSON module provides JSON support for Lua. It features:
|
||||
- Fast, standards compliant encoding/parsing routines
|
||||
- Full support for JSON with UTF-8, including decoding surrogate pairs
|
||||
- Optional run-time support for common exceptions to the JSON specification
|
||||
(infinity, NaN,..)
|
||||
- No dependencies on other libraries
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
|
||||
%build
|
||||
make %{?_smp_mflags} CFLAGS="%{optflags}" LUA_INCLUDE_DIR="%{_includedir}"
|
||||
|
||||
|
||||
%install
|
||||
rm -rf "$RPM_BUILD_ROOT"
|
||||
make install DESTDIR="$RPM_BUILD_ROOT" LUA_CMODULE_DIR="%{lualibdir}"
|
||||
make install-extra DESTDIR="$RPM_BUILD_ROOT" LUA_MODULE_DIR="%{luadatadir}" \
|
||||
LUA_BIN_DIR="%{_bindir}"
|
||||
|
||||
|
||||
%clean
|
||||
rm -rf "$RPM_BUILD_ROOT"
|
||||
|
||||
|
||||
%preun
|
||||
/bin/rm -f "%{luadatadir}/cjson/tests/utf8.dat"
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc LICENSE NEWS performance.html performance.txt manual.html manual.txt rfc4627.txt THANKS
|
||||
%{lualibdir}/*
|
||||
%{luadatadir}/*
|
||||
%{_bindir}/*
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Mar 1 2012 Mark Pulford <mark@kyne.com.au> - 2.1.0-1
|
||||
- Update for 2.1.0
|
||||
|
||||
* Sun Jan 22 2012 Mark Pulford <mark@kyne.com.au> - 2.0.0-1
|
||||
- Update for 2.0.0
|
||||
- Install lua2json / json2lua utilities
|
||||
|
||||
* Wed Nov 27 2011 Mark Pulford <mark@kyne.com.au> - 1.0.4-1
|
||||
- Update for 1.0.4
|
||||
|
||||
* Wed Sep 15 2011 Mark Pulford <mark@kyne.com.au> - 1.0.3-1
|
||||
- Update for 1.0.3
|
||||
|
||||
* Sun May 29 2011 Mark Pulford <mark@kyne.com.au> - 1.0.2-1
|
||||
- Update for 1.0.2
|
||||
|
||||
* Sun May 10 2011 Mark Pulford <mark@kyne.com.au> - 1.0.1-1
|
||||
- Update for 1.0.1
|
||||
|
||||
* Sun May 1 2011 Mark Pulford <mark@kyne.com.au> - 1.0-1
|
||||
- Initial package
|
|
@ -1,89 +0,0 @@
|
|||
JSON module performance comparison under Lua
|
||||
============================================
|
||||
Mark Pulford <mark@kyne.com.au>
|
||||
:revdate: January 22, 2012
|
||||
|
||||
This performance comparison aims to provide a guide of relative
|
||||
performance between several fast and popular JSON modules.
|
||||
|
||||
The examples used in this comparison were mostly sourced from the
|
||||
http://json.org[JSON website] and
|
||||
http://tools.ietf.org/html/rfc4627[RFC 4627].
|
||||
|
||||
Performance will vary widely between platforms and data sets. These
|
||||
results should only be used as an approximation.
|
||||
|
||||
|
||||
Modules
|
||||
-------
|
||||
|
||||
The following JSON modules for Lua were tested:
|
||||
|
||||
http://chiselapp.com/user/dhkolf/repository/dkjson/[DKJSON 2.1]::
|
||||
- Lua implementation with no dependencies on other libraries
|
||||
- Supports LPeg to improve decode performance
|
||||
|
||||
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]::
|
||||
- C implementation with no dependencies on other libraries
|
||||
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
All modules were built and tested as follows:
|
||||
|
||||
DKJSON:: Tested with/without LPeg 10.2.
|
||||
Lua YAJL:: Tested with YAJL 2.0.4.
|
||||
Lua CJSON:: Tested with Libc and internal floating point conversion
|
||||
routines.
|
||||
|
||||
The following Lua implementations were used for this comparison:
|
||||
|
||||
- http://www.lua.org[Lua 5.1.4] (_Lua_)
|
||||
- http://www.luajit.org[LuaJIT 2.0.0-beta9] (_JIT_)
|
||||
|
||||
These results show the number of JSON operations per second sustained by
|
||||
each module. All results have been normalised against the pure Lua
|
||||
DKJSON implementation.
|
||||
|
||||
.Decoding performance
|
||||
............................................................................
|
||||
| DKJSON | Lua YAJL | Lua CJSON
|
||||
| No LPeg With LPeg | | Libc Internal
|
||||
| Lua JIT Lua JIT | Lua JIT | Lua JIT Lua JIT
|
||||
example1 | 1x 2x 2.6x 3.4x | 7.1x 10x | 14x 20x 14x 20x
|
||||
example2 | 1x 2.2x 2.9x 4.4x | 6.7x 9.9x | 14x 22x 14x 22x
|
||||
example3 | 1x 2.1x 3x 4.3x | 6.9x 9.3x | 14x 21x 15x 22x
|
||||
example4 | 1x 2x 2.5x 3.7x | 7.3x 10x | 12x 19x 12x 20x
|
||||
example5 | 1x 2.2x 3x 4.5x | 7.8x 11x | 16x 24x 16x 24x
|
||||
numbers | 1x 2.2x 2.3x 4x | 4.6x 5.5x | 8.9x 10x 13x 17x
|
||||
rfc-example1 | 1x 2.1x 2.8x 4.3x | 6.1x 8.1x | 13x 19x 14x 21x
|
||||
rfc-example2 | 1x 2.1x 3.1x 4.2x | 7.1x 9.2x | 15x 21x 17x 24x
|
||||
types | 1x 2.2x 2.6x 4.3x | 5.3x 7.4x | 12x 20x 13x 21x
|
||||
-------------|-------------------------|------------|-----------------------
|
||||
= Average => | 1x 2.1x 2.7x 4.1x | 6.5x 9x | 13x 20x 14x 21x
|
||||
............................................................................
|
||||
|
||||
.Encoding performance
|
||||
.............................................................................
|
||||
| DKJSON | Lua YAJL | Lua CJSON
|
||||
| No LPeg With LPeg | | Libc Internal
|
||||
| Lua JIT Lua JIT | Lua JIT | Lua JIT Lua JIT
|
||||
example1 | 1x 1.8x 0.97x 1.6x | 3.1x 5.2x | 23x 29x 23x 29x
|
||||
example2 | 1x 2x 0.97x 1.7x | 2.6x 4.3x | 22x 28x 22x 28x
|
||||
example3 | 1x 1.9x 0.98x 1.6x | 2.8x 4.3x | 13x 15x 16x 18x
|
||||
example4 | 1x 1.7x 0.96x 1.3x | 3.9x 6.1x | 15x 19x 17x 21x
|
||||
example5 | 1x 2x 0.98x 1.7x | 2.7x 4.5x | 20x 23x 20x 23x
|
||||
numbers | 1x 2.3x 1x 2.2x | 1.3x 1.9x | 3.8x 4.1x 4.2x 4.6x
|
||||
rfc-example1 | 1x 1.9x 0.97x 1.6x | 2.2x 3.2x | 8.5x 9.3x 11x 12x
|
||||
rfc-example2 | 1x 1.9x 0.98x 1.6x | 2.6x 3.9x | 10x 11x 17x 19x
|
||||
types | 1x 2.2x 0.97x 2x | 1.2x 1.9x | 11x 13x 12x 14x
|
||||
-------------|-------------------------|------------|-----------------------
|
||||
= Average => | 1x 1.9x 0.98x 1.7x | 2.5x 3.9x | 14x 17x 16x 19x
|
||||
.............................................................................
|
||||
|
||||
|
||||
// vi:ft=asciidoc tw=72:
|
|
@ -41,7 +41,7 @@
|
|||
// exit(-1);
|
||||
// }
|
||||
|
||||
void strbuf_init(strbuf_t *s, int len)
|
||||
int strbuf_init(strbuf_t *s, int len)
|
||||
{
|
||||
int size;
|
||||
|
||||
|
@ -61,10 +61,11 @@ void strbuf_init(strbuf_t *s, int len)
|
|||
s->buf = c_malloc(size);
|
||||
if (!s->buf){
|
||||
NODE_ERR("not enough memory\n");
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
strbuf_ensure_null(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strbuf_t *strbuf_new(int len)
|
||||
|
@ -74,7 +75,7 @@ strbuf_t *strbuf_new(int len)
|
|||
s = c_malloc(sizeof(strbuf_t));
|
||||
if (!s){
|
||||
NODE_ERR("not enough memory\n");
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strbuf_init(s, len);
|
||||
|
@ -85,16 +86,17 @@ strbuf_t *strbuf_new(int len)
|
|||
return s;
|
||||
}
|
||||
|
||||
void strbuf_set_increment(strbuf_t *s, int increment)
|
||||
int 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){
|
||||
NODE_ERR("BUG: Invalid string increment");
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->increment = increment;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void debug_stats(strbuf_t *s)
|
||||
|
@ -169,7 +171,7 @@ static int calculate_new_size(strbuf_t *s, int len)
|
|||
|
||||
/* Ensure strbuf can handle a string length bytes long (ignoring NULL
|
||||
* optional termination). */
|
||||
void strbuf_resize(strbuf_t *s, int len)
|
||||
int strbuf_resize(strbuf_t *s, int len)
|
||||
{
|
||||
int newsize;
|
||||
|
||||
|
@ -180,13 +182,14 @@ void strbuf_resize(strbuf_t *s, int len)
|
|||
(long)s, s->size, newsize);
|
||||
}
|
||||
|
||||
s->size = newsize;
|
||||
s->buf = (char *)c_realloc(s->buf, s->size);
|
||||
s->buf = (char *)c_realloc(s->buf, newsize);
|
||||
if (!s->buf){
|
||||
NODE_ERR("not enough memory");
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
s->size = newsize;
|
||||
s->reallocs++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void strbuf_append_string(strbuf_t *s, const char *str)
|
||||
|
|
|
@ -50,15 +50,15 @@ typedef struct {
|
|||
|
||||
/* 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 int strbuf_init(strbuf_t *s, int len);
|
||||
extern int strbuf_set_increment(strbuf_t *s, int increment);
|
||||
|
||||
/* Release */
|
||||
extern void strbuf_free(strbuf_t *s);
|
||||
extern char *strbuf_free_to_string(strbuf_t *s, int *len);
|
||||
|
||||
/* Management */
|
||||
extern void strbuf_resize(strbuf_t *s, int len);
|
||||
extern int 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);
|
||||
|
@ -127,13 +127,13 @@ static inline void strbuf_append_char_unsafe(strbuf_t *s, const char c)
|
|||
static inline void strbuf_append_mem(strbuf_t *s, const char *c, int len)
|
||||
{
|
||||
strbuf_ensure_empty_length(s, len);
|
||||
memcpy(s->buf + s->length, c, len);
|
||||
c_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)
|
||||
{
|
||||
memcpy(s->buf + s->length, c, len);
|
||||
c_memcpy(s->buf + s->length, c, len);
|
||||
s->length += len;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "c_limits.h"
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include "flash_api.h"
|
||||
|
||||
#include "strbuf.h"
|
||||
#ifdef LUA_NUMBER_INTEGRAL
|
||||
|
@ -50,7 +51,6 @@
|
|||
#define FPCONV_G_FMT_BUFSIZE 32
|
||||
#define fpconv_strtod c_strtod
|
||||
#define fpconv_init() ((void)0)
|
||||
#define fpconv_g_fmt fpconv_g_fmt
|
||||
#endif
|
||||
|
||||
#ifndef CJSON_MODNAME
|
||||
|
@ -73,7 +73,7 @@
|
|||
#define DEFAULT_DECODE_MAX_DEPTH 1000
|
||||
#define DEFAULT_ENCODE_INVALID_NUMBERS 0
|
||||
#define DEFAULT_DECODE_INVALID_NUMBERS 1
|
||||
#define DEFAULT_ENCODE_KEEP_BUFFER 1
|
||||
#define DEFAULT_ENCODE_KEEP_BUFFER 0
|
||||
#define DEFAULT_ENCODE_NUMBER_PRECISION 14
|
||||
|
||||
#ifdef DISABLE_INVALID_NUMBERS
|
||||
|
@ -97,7 +97,7 @@ typedef enum {
|
|||
T_ERROR,
|
||||
T_UNKNOWN
|
||||
} json_token_type_t;
|
||||
|
||||
#if 0
|
||||
static const char *json_token_type_name[] = {
|
||||
"T_OBJ_BEGIN",
|
||||
"T_OBJ_END",
|
||||
|
@ -115,10 +115,27 @@ static const char *json_token_type_name[] = {
|
|||
"T_UNKNOWN",
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
static const char json_token_type_name[14][16] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = {
|
||||
{'T','_','O','B','J','_','B','E','G','I','N',0},
|
||||
{'T','_','O','B','J','_','E','N','D',0},
|
||||
{'T','_','A','R','R','_','B','E','G','I','N',0},
|
||||
{'T','_','A','R','R','_','E','N','D',0},
|
||||
{'T','_','S','T','R','I','N','G',0},
|
||||
{'T','_','N','U','M','B','E','R',0},
|
||||
{'T','_','B','O','O','L','E','A','N',0},
|
||||
{'T','_','N','U','L','L',0},
|
||||
{'T','_','C','O','L','O','N',0},
|
||||
{'T','_','C','O','M','M','A',0},
|
||||
{'T','_','E','N','D',0},
|
||||
{'T','_','W','H','I','T','E','S','P','A','C','E',0},
|
||||
{'T','_','E','R','R','O','R',0},
|
||||
{'T','_','U','N','K','N','O','W','N',0}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
json_token_type_t ch2token[256];
|
||||
char escape2char[256]; /* Decoding */
|
||||
// json_token_type_t ch2token[256]; // 256*4 = 1024 byte
|
||||
// char escape2char[256]; /* Decoding */
|
||||
|
||||
/* encode_buf is only allocated and used when
|
||||
* encode_keep_buffer is set */
|
||||
|
@ -155,6 +172,7 @@ typedef struct {
|
|||
int string_len;
|
||||
} json_token_t;
|
||||
|
||||
#if 0
|
||||
static const char *char2escape[256] = {
|
||||
"\\u0000", "\\u0001", "\\u0002", "\\u0003",
|
||||
"\\u0004", "\\u0005", "\\u0006", "\\u0007",
|
||||
|
@ -193,6 +211,99 @@ static const char *char2escape[256] = {
|
|||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* ===== HELPER FUNCTION ===== */
|
||||
static const char escape_array[36][8] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = {
|
||||
{'\\','u','0','0','0','0','\0','\0'},
|
||||
{'\\','u','0','0','0','1','\0','\0'},
|
||||
{'\\','u','0','0','0','2','\0','\0'},
|
||||
{'\\','u','0','0','0','3','\0','\0'},
|
||||
{'\\','u','0','0','0','4','\0','\0'},
|
||||
{'\\','u','0','0','0','5','\0','\0'},
|
||||
{'\\','u','0','0','0','6','\0','\0'},
|
||||
{'\\','u','0','0','0','7','\0','\0'},
|
||||
{'\\','b','\0','\0','\0','\0','\0','\0'},
|
||||
{'\\','t','\0','\0','\0','\0','\0','\0'},
|
||||
{'\\','n','\0','\0','\0','\0','\0','\0'},
|
||||
{'\\','u','0','0','0','b','\0','\0'},
|
||||
{'\\','f','\0','\0','\0','\0','\0','\0'},
|
||||
{'\\','r','\0','\0','\0','\0','\0','\0'},
|
||||
{'\\','u','0','0','0','e','\0','\0'},
|
||||
{'\\','u','0','0','0','f','\0','\0'},
|
||||
{'\\','u','0','0','1','0','\0','\0'},
|
||||
{'\\','u','0','0','1','1','\0','\0'},
|
||||
{'\\','u','0','0','1','2','\0','\0'},
|
||||
{'\\','u','0','0','1','3','\0','\0'},
|
||||
{'\\','u','0','0','1','4','\0','\0'},
|
||||
{'\\','u','0','0','1','5','\0','\0'},
|
||||
{'\\','u','0','0','1','6','\0','\0'},
|
||||
{'\\','u','0','0','1','7','\0','\0'},
|
||||
{'\\','u','0','0','1','8','\0','\0'},
|
||||
{'\\','u','0','0','1','9','\0','\0'},
|
||||
{'\\','u','0','0','1','a','\0','\0'},
|
||||
{'\\','u','0','0','1','b','\0','\0'},
|
||||
{'\\','u','0','0','1','c','\0','\0'},
|
||||
{'\\','u','0','0','1','d','\0','\0'},
|
||||
{'\\','u','0','0','1','e','\0','\0'},
|
||||
{'\\','u','0','0','1','f','\0','\0'},
|
||||
{'\\','\"','\0','\0','\0','\0','\0','\0'},
|
||||
{'\\','/','\0','\0','\0','\0','\0','\0'},
|
||||
{'\\','\\','\0','\0','\0','\0','\0','\0'},
|
||||
{'\\','u','0','0','7','f','\0','\0'}
|
||||
};
|
||||
|
||||
static const char *char2escape(unsigned char c){
|
||||
if(c<32) return escape_array[c];
|
||||
|
||||
switch(c){
|
||||
case 34: return escape_array[32];
|
||||
case 47: return escape_array[33];
|
||||
case 92: return escape_array[34];
|
||||
case 127: return escape_array[35];
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static json_token_type_t ch2token(unsigned char c){
|
||||
switch(c){
|
||||
case '{': return T_OBJ_BEGIN;
|
||||
case '}': return T_OBJ_END;
|
||||
case '[': return T_ARR_BEGIN;
|
||||
case ']': return T_ARR_END;
|
||||
case ',': return T_COMMA;
|
||||
case ':': return T_COLON;
|
||||
case '\0': return T_END;
|
||||
case ' ': return T_WHITESPACE;
|
||||
case '\t': return T_WHITESPACE;
|
||||
case '\n': return T_WHITESPACE;
|
||||
case '\r': return T_WHITESPACE;
|
||||
|
||||
/* Update characters that require further processing */
|
||||
case 'f': case 'i': case 'I': case 'n': case 'N': case 't': case '"': case '+': case '-':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
||||
return T_UNKNOWN;
|
||||
default:
|
||||
return T_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static char escape2char(unsigned char c){
|
||||
switch(c){
|
||||
case '"': return '"';
|
||||
case '\\': return '\\';
|
||||
case '/': return '/';
|
||||
case 'b': return '\b';
|
||||
case 't': return '\t';
|
||||
case 'n': return '\n';
|
||||
case 'f': return '\f';
|
||||
case 'r': return '\r';
|
||||
case 'u': return 'u';
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== CONFIGURATION ===== */
|
||||
#if 0
|
||||
|
@ -319,8 +430,10 @@ static int json_cfg_encode_keep_buffer(lua_State *l)
|
|||
|
||||
/* Init / free the buffer if the setting has changed */
|
||||
if (old_value ^ cfg->encode_keep_buffer) {
|
||||
if (cfg->encode_keep_buffer)
|
||||
strbuf_init(&cfg->encode_buf, 0);
|
||||
if (cfg->encode_keep_buffer){
|
||||
if(-1==strbuf_init(&cfg->encode_buf, 0))
|
||||
return luaL_error(l, "not enough memory");
|
||||
}
|
||||
else
|
||||
strbuf_free(&cfg->encode_buf);
|
||||
}
|
||||
|
@ -456,9 +569,7 @@ static json_config_t *json_fetch_config(lua_State *l)
|
|||
return &_cfg;
|
||||
}
|
||||
|
||||
static void cfg_init(json_config_t *cfg){
|
||||
int i;
|
||||
|
||||
static int cfg_init(json_config_t *cfg){
|
||||
cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT;
|
||||
cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO;
|
||||
cfg->encode_sparse_safe = DEFAULT_SPARSE_SAFE;
|
||||
|
@ -470,53 +581,13 @@ static void cfg_init(json_config_t *cfg){
|
|||
cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION;
|
||||
|
||||
#if DEFAULT_ENCODE_KEEP_BUFFER > 0
|
||||
strbuf_init(&cfg->encode_buf, 0);
|
||||
if(-1==strbuf_init(&cfg->encode_buf, 0)){
|
||||
NODE_ERR("not enough memory\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Decoding init */
|
||||
|
||||
/* Tag all characters as an error */
|
||||
for (i = 0; i < 256; i++)
|
||||
cfg->ch2token[i] = T_ERROR;
|
||||
|
||||
/* Set tokens that require no further processing */
|
||||
cfg->ch2token['{'] = T_OBJ_BEGIN;
|
||||
cfg->ch2token['}'] = T_OBJ_END;
|
||||
cfg->ch2token['['] = T_ARR_BEGIN;
|
||||
cfg->ch2token[']'] = T_ARR_END;
|
||||
cfg->ch2token[','] = T_COMMA;
|
||||
cfg->ch2token[':'] = T_COLON;
|
||||
cfg->ch2token['\0'] = T_END;
|
||||
cfg->ch2token[' '] = T_WHITESPACE;
|
||||
cfg->ch2token['\t'] = T_WHITESPACE;
|
||||
cfg->ch2token['\n'] = T_WHITESPACE;
|
||||
cfg->ch2token['\r'] = T_WHITESPACE;
|
||||
|
||||
/* Update characters that require further processing */
|
||||
cfg->ch2token['f'] = T_UNKNOWN; /* false? */
|
||||
cfg->ch2token['i'] = T_UNKNOWN; /* inf, ininity? */
|
||||
cfg->ch2token['I'] = T_UNKNOWN;
|
||||
cfg->ch2token['n'] = T_UNKNOWN; /* null, nan? */
|
||||
cfg->ch2token['N'] = T_UNKNOWN;
|
||||
cfg->ch2token['t'] = T_UNKNOWN; /* true? */
|
||||
cfg->ch2token['"'] = T_UNKNOWN; /* string? */
|
||||
cfg->ch2token['+'] = T_UNKNOWN; /* number? */
|
||||
cfg->ch2token['-'] = T_UNKNOWN;
|
||||
for (i = 0; i < 10; i++)
|
||||
cfg->ch2token['0' + i] = T_UNKNOWN;
|
||||
|
||||
/* Lookup table for parsing escape characters */
|
||||
for (i = 0; i < 256; i++)
|
||||
cfg->escape2char[i] = 0; /* String error */
|
||||
cfg->escape2char['"'] = '"';
|
||||
cfg->escape2char['\\'] = '\\';
|
||||
cfg->escape2char['/'] = '/';
|
||||
cfg->escape2char['b'] = '\b';
|
||||
cfg->escape2char['t'] = '\t';
|
||||
cfg->escape2char['n'] = '\n';
|
||||
cfg->escape2char['f'] = '\f';
|
||||
cfg->escape2char['r'] = '\r';
|
||||
cfg->escape2char['u'] = 'u'; /* Unicode parsing required */
|
||||
return 0;
|
||||
}
|
||||
/* ===== ENCODING ===== */
|
||||
|
||||
|
@ -552,9 +623,18 @@ static void json_append_string(lua_State *l, strbuf_t *json, int lindex)
|
|||
|
||||
strbuf_append_char_unsafe(json, '\"');
|
||||
for (i = 0; i < len; i++) {
|
||||
escstr = char2escape[(unsigned char)str[i]];
|
||||
if (escstr)
|
||||
escstr = char2escape((unsigned char)str[i]);
|
||||
if (escstr){
|
||||
int i;
|
||||
char temp[8]; // for now, 8-bytes is enough.
|
||||
for (i=0; i < 8; ++i)
|
||||
{
|
||||
temp[i] = byte_of_aligned_array(escstr, i);
|
||||
if(temp[i]==0) break;
|
||||
}
|
||||
escstr = temp;
|
||||
strbuf_append_string(json, escstr);
|
||||
}
|
||||
else
|
||||
strbuf_append_char_unsafe(json, str[i]);
|
||||
}
|
||||
|
@ -694,7 +774,12 @@ static void json_append_number(lua_State *l, json_config_t *cfg,
|
|||
}
|
||||
|
||||
strbuf_ensure_empty_length(json, FPCONV_G_FMT_BUFSIZE);
|
||||
#ifdef LUA_NUMBER_INTEGRAL
|
||||
len = fpconv_g_fmt(strbuf_empty_ptr(json), num, cfg->encode_number_precision);
|
||||
#else
|
||||
c_sprintf(strbuf_empty_ptr(json), "%.14g", num);
|
||||
len = c_strlen(strbuf_empty_ptr(json));
|
||||
#endif
|
||||
strbuf_extend_length(json, len);
|
||||
}
|
||||
|
||||
|
@ -796,7 +881,8 @@ static int json_encode(lua_State *l)
|
|||
if (!cfg->encode_keep_buffer) {
|
||||
/* Use private buffer */
|
||||
encode_buf = &local_encode_buf;
|
||||
strbuf_init(encode_buf, 0);
|
||||
if(-1==strbuf_init(encode_buf, 0))
|
||||
return luaL_error(l, "not enough memory");
|
||||
} else {
|
||||
/* Reuse existing buffer */
|
||||
encode_buf = &cfg->encode_buf;
|
||||
|
@ -967,7 +1053,7 @@ static void json_set_token_error(json_token_t *token, json_parse_t *json,
|
|||
|
||||
static void json_next_string_token(json_parse_t *json, json_token_t *token)
|
||||
{
|
||||
char *escape2char = json->cfg->escape2char;
|
||||
// char *escape2char = json->cfg->escape2char;
|
||||
char ch;
|
||||
|
||||
/* Caller must ensure a string is next */
|
||||
|
@ -995,7 +1081,7 @@ static void json_next_string_token(json_parse_t *json, json_token_t *token)
|
|||
ch = *(json->ptr + 1);
|
||||
|
||||
/* Translate escape code and append to tmp string */
|
||||
ch = escape2char[(unsigned char)ch];
|
||||
ch = escape2char((unsigned char)ch);
|
||||
if (ch == 'u') {
|
||||
if (json_append_unicode_escape(json) == 0)
|
||||
continue;
|
||||
|
@ -1107,13 +1193,13 @@ static void json_next_number_token(json_parse_t *json, json_token_t *token)
|
|||
*/
|
||||
static void json_next_token(json_parse_t *json, json_token_t *token)
|
||||
{
|
||||
const json_token_type_t *ch2token = json->cfg->ch2token;
|
||||
// const json_token_type_t *ch2token = json->cfg->ch2token;
|
||||
int ch;
|
||||
|
||||
/* Eat whitespace. */
|
||||
while (1) {
|
||||
ch = (unsigned char)*(json->ptr);
|
||||
token->type = ch2token[ch];
|
||||
token->type = ch2token(ch);
|
||||
if (token->type != T_WHITESPACE)
|
||||
break;
|
||||
json->ptr++;
|
||||
|
@ -1194,13 +1280,23 @@ static void json_throw_parse_error(lua_State *l, json_parse_t *json,
|
|||
const char *exp, json_token_t *token)
|
||||
{
|
||||
const char *found;
|
||||
char temp[16]; // for now, 16-bytes is enough.
|
||||
|
||||
strbuf_free(json->tmp);
|
||||
|
||||
if (token->type == T_ERROR)
|
||||
found = token->value.string;
|
||||
else
|
||||
{
|
||||
found = json_token_type_name[token->type];
|
||||
int i;
|
||||
for (i=0; i < 16; ++i)
|
||||
{
|
||||
temp[i] = byte_of_aligned_array(found, i);
|
||||
if(temp[i]==0) break;
|
||||
}
|
||||
found = temp;
|
||||
}
|
||||
|
||||
/* Note: token->index is 0 based, display starting from 1 */
|
||||
luaL_error(l, "Expected %s but found %s at character %d",
|
||||
|
@ -1369,6 +1465,9 @@ static int json_decode(lua_State *l)
|
|||
* This means we no longer need to do length checks since the decoded
|
||||
* string must be smaller than the entire json string */
|
||||
json.tmp = strbuf_new(json_len);
|
||||
if(json.tmp == NULL){
|
||||
return luaL_error(l, "not enought memory");
|
||||
}
|
||||
|
||||
json_next_token(&json, &token);
|
||||
json_process_value(l, &json, &token);
|
||||
|
@ -1434,6 +1533,7 @@ static int json_protect_conversion(lua_State *l)
|
|||
return luaL_error(l, "Memory allocation error in CJSON protected call");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Module function map
|
||||
#define MIN_OPT_LEVEL 2
|
||||
#include "lrodefs.h"
|
||||
|
@ -1459,7 +1559,9 @@ LUALIB_API int luaopen_cjson( lua_State *L )
|
|||
{
|
||||
/* Initialise number conversions */
|
||||
fpconv_init();
|
||||
cfg_init(&_cfg);
|
||||
if(-1==cfg_init(&_cfg)){
|
||||
return luaL_error(L, "BUG: Unable to init config for cjson");;
|
||||
}
|
||||
#if LUA_OPTIMIZE_MEMORY > 0
|
||||
return 0;
|
||||
#else // #if LUA_OPTIMIZE_MEMORY > 0
|
||||
|
|
Loading…
Reference in New Issue