Browse Source

fix cjson bugs and reduce mem usage

funshine 9 years ago
parent
commit
54004a4beb

+ 0 - 44
app/cjson/NEWS

@@ -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

+ 2 - 1
app/cjson/dtoa.c.bak → app/cjson/dtoa.c

@@ -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

+ 2 - 2
app/cjson/dtoa_config.h.bak → app/cjson/dtoa_config.h

@@ -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:

+ 2 - 1
app/cjson/g_fmt.c

@@ -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

+ 0 - 56
app/cjson/lua-cjson-2.1devel-1.rockspec

@@ -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:

+ 0 - 80
app/cjson/lua-cjson.spec

@@ -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

+ 0 - 89
app/cjson/performance.txt

@@ -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:

+ 12 - 9
app/cjson/strbuf.c

@@ -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)

+ 5 - 5
app/cjson/strbuf.h

@@ -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;
 }
 

+ 165 - 63
app/modules/cjson.c

@@ -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