From c06c1495fbe6b6f28c7903a5af1c8554896b6c39 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Tue, 23 Apr 2013 10:39:09 +0800 Subject: [PATCH] fix json format issue --- src/jconf.c | 10 +++++-- src/json.c | 85 ++++++++++++++++++++++++++++++++--------------------- src/json.h | 44 ++++++++++++++++++++++----- 3 files changed, 95 insertions(+), 44 deletions(-) diff --git a/src/jconf.c b/src/jconf.c index c415e3ab..c069e1e0 100644 --- a/src/jconf.c +++ b/src/jconf.c @@ -50,16 +50,20 @@ jconf_t *read_jconf(const char* file) { if (pos >= MAX_CONF_SIZE) FATAL("Too large config file."); - buf = malloc(pos); + buf = malloc(pos + 1); if (buf == NULL) FATAL("No enough memory."); fread(buf, pos, 1, f); fclose(f); - obj = json_parse(buf); + buf[pos] = '\0'; // end of string + + json_settings settings = { 0 }; + char error_buf[512]; + obj = json_parse_ex(&settings, buf, pos, error_buf); if (obj == NULL) { - FATAL("Invalid config file"); + FATAL(error_buf); } if (obj->type == json_object) { diff --git a/src/json.c b/src/json.c index fd9c59f1..543a4dc3 100644 --- a/src/json.c +++ b/src/json.c @@ -42,7 +42,6 @@ const struct _json_value json_value_none = { 0 }; #endif -#include #include #include #include @@ -66,20 +65,28 @@ static unsigned char hex_value (json_char c) typedef struct { - json_settings settings; - int first_pass; - unsigned long used_memory; unsigned int uint_max; unsigned long ulong_max; + json_settings settings; + int first_pass; + } json_state; -static void * json_alloc (json_state * state, unsigned long size, int zero) +static void * default_alloc (size_t size, int zero, void * user_data) +{ + return zero ? calloc (size, 1) : malloc (size); +} + +static void default_free (void * ptr, void * user_data) { - void * mem; + free (ptr); +} +static void * json_alloc (json_state * state, unsigned long size, int zero) +{ if ((state->ulong_max - state->used_memory) < size) return 0; @@ -89,10 +96,7 @@ static void * json_alloc (json_state * state, unsigned long size, int zero) return 0; } - if (! (mem = zero ? calloc (size, 1) : malloc (size))) - return 0; - - return mem; + return state->settings.mem_alloc (size, zero, state->settings.user_data); } static int new_value @@ -190,21 +194,31 @@ const static long flag_num_negative = 256, flag_num_zero = 512, flag_num_e = 1024, flag_num_e_got_sign = 2048, flag_num_e_negative = 4096; -json_value * json_parse_ex (json_settings * settings, const json_char * json, char * error_buf) +json_value * json_parse_ex (json_settings * settings, + const json_char * json, + size_t length, + char * error_buf) { json_char error [128]; unsigned int cur_line; - const json_char * cur_line_begin, * i; + const json_char * cur_line_begin, * i, * end; json_value * top, * root, * alloc = 0; - json_state state; + json_state state = { 0 }; long flags; - long num_digits, num_fraction, num_e; + long num_digits, num_e; + json_int_t num_fraction; error[0] = '\0'; + end = (json + length); - memset (&state, 0, sizeof (json_state)); memcpy (&state.settings, settings, sizeof (json_settings)); + if (!state.settings.mem_alloc) + state.settings.mem_alloc = default_alloc; + + if (!state.settings.mem_free) + state.settings.mem_free = default_free; + memset (&state.uint_max, 0xFF, sizeof (state.uint_max)); memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max)); @@ -226,7 +240,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch for (i = json ;; ++ i) { - json_char b = *i; + json_char b = (json == end ? 0 : *i); if (flags & flag_done) { @@ -440,7 +454,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch case 't': - if (*(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e') + if ((end - i) < 3 || *(++ i) != 'r' || *(++ i) != 'u' || *(++ i) != 'e') goto e_unknown_value; if (!new_value (&state, &top, &root, &alloc, json_boolean)) @@ -453,7 +467,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch case 'f': - if (*(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e') + if ((end - i) < 4 || *(++ i) != 'a' || *(++ i) != 'l' || *(++ i) != 's' || *(++ i) != 'e') goto e_unknown_value; if (!new_value (&state, &top, &root, &alloc, json_boolean)) @@ -464,7 +478,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch case 'n': - if (*(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l') + if ((end - i) < 3 || *(++ i) != 'u' || *(++ i) != 'l' || *(++ i) != 'l') goto e_unknown_value; if (!new_value (&state, &top, &root, &alloc, json_null)) @@ -617,7 +631,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch } top->type = json_double; - top->u.dbl = top->u.integer; + top->u.dbl = (double) top->u.integer; num_digits = 0; continue; @@ -642,7 +656,7 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch if (top->type == json_integer) { top->type = json_double; - top->u.dbl = top->u.integer; + top->u.dbl = (double) top->u.integer; } num_digits = 0; @@ -768,25 +782,23 @@ e_failed: while (alloc) { top = alloc->_reserved.next_alloc; - free (alloc); + state.settings.mem_free (alloc, state.settings.user_data); alloc = top; } if (!state.first_pass) - json_value_free (root); + json_value_free_ex (&state.settings, root); return 0; } -json_value * json_parse (const json_char * json) +json_value * json_parse (const json_char * json, size_t length) { - json_settings settings; - memset (&settings, 0, sizeof (json_settings)); - - return json_parse_ex (&settings, json, 0); + json_settings settings = { 0 }; + return json_parse_ex (&settings, json, length, 0); } -void json_value_free (json_value * value) +void json_value_free_ex (json_settings * settings, json_value * value) { json_value * cur_value; @@ -803,7 +815,7 @@ void json_value_free (json_value * value) if (!value->u.array.length) { - free (value->u.array.values); + settings->mem_free (value->u.array.values, settings->user_data); break; } @@ -814,7 +826,7 @@ void json_value_free (json_value * value) if (!value->u.object.length) { - free (value->u.object.values); + settings->mem_free (value->u.object.values, settings->user_data); break; } @@ -823,7 +835,7 @@ void json_value_free (json_value * value) case json_string: - free (value->u.string.ptr); + settings->mem_free (value->u.string.ptr, settings->user_data); break; default: @@ -832,7 +844,14 @@ void json_value_free (json_value * value) cur_value = value; value = value->parent; - free (cur_value); + settings->mem_free (cur_value, settings->user_data); } } +void json_value_free (json_value * value) +{ + json_settings settings = { 0 }; + settings.mem_free = default_free; + json_value_free_ex (&settings, value); +} + diff --git a/src/json.h b/src/json.h index f0d10d1f..a38c65c5 100644 --- a/src/json.h +++ b/src/json.h @@ -35,6 +35,17 @@ #define json_char char #endif +#ifndef json_int_t + #ifndef _MSC_VER + #include + #define json_int_t int64_t + #else + #define json_int_t __int64 + #endif +#endif + +#include + #ifdef __cplusplus #include @@ -49,6 +60,14 @@ typedef struct unsigned long max_memory; int settings; + /* Custom allocator support (leave null to use malloc/free) + */ + + void * (* mem_alloc) (size_t, int zero, void * user_data); + void (* mem_free) (void *, void * user_data); + + void * user_data; /* will be passed to mem_alloc and mem_free */ + } json_settings; #define json_relaxed_commas 1 @@ -77,7 +96,7 @@ typedef struct _json_value union { int boolean; - long integer; + json_int_t integer; double dbl; struct @@ -162,7 +181,7 @@ typedef struct _json_value }; } - inline operator long () const + inline operator json_int_t () const { switch (type) { @@ -170,7 +189,7 @@ typedef struct _json_value return u.integer; case json_double: - return (long) u.dbl; + return (json_int_t) u.dbl; default: return 0; @@ -190,7 +209,7 @@ typedef struct _json_value switch (type) { case json_integer: - return u.integer; + return (double) u.integer; case json_double: return u.dbl; @@ -204,15 +223,24 @@ typedef struct _json_value } json_value; -json_value * json_parse - (const json_char * json); +json_value * json_parse (const json_char * json, + size_t length); -json_value * json_parse_ex - (json_settings * settings, const json_char * json, char * error); +json_value * json_parse_ex (json_settings * settings, + const json_char * json, + size_t length, + char * error); void json_value_free (json_value *); +/* Not usually necessary, unless you used a custom mem_alloc and now want to + * use a custom mem_free. + */ +void json_value_free_ex (json_settings * settings, + json_value *); + + #ifdef __cplusplus } /* extern "C" */ #endif