From: ehaszla Date: Tue, 7 Dec 2010 18:15:35 +0000 (+0000) Subject: Simplify things by storing integer values only as int64_t's internally, and X-Git-Tag: json-c-0.10-20120530~59 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=252669cee672b101cc43b2baae86db4a8bcb80eb;p=thirdparty%2Fjson-c.git Simplify things by storing integer values only as int64_t's internally, and omit the range check during parsing since we already have the checks when accessing the value. There is no longer a json_type_int64, only json_type_int. Fix some problems with parsing 0 and -0 values, and add a couple of tests. Fix some minor compile issues on HPUX environments. git-svn-id: http://svn.metaparadigm.com/svn/json-c/trunk@60 327403b1-1117-474d-bef2-5cb71233fd97 --- diff --git a/json_object.c b/json_object.c index c2b6fe2c..2b6dad4b 100644 --- a/json_object.c +++ b/json_object.c @@ -43,7 +43,6 @@ static const char* json_type_name[] = { "object", "array", "string", - "int64", }; #endif /* REFCOUNT_DEBUG */ @@ -306,8 +305,6 @@ boolean json_object_get_boolean(struct json_object *jso) case json_type_boolean: return jso->o.c_boolean; case json_type_int: - return (jso->o.c_int != 0); - case json_type_int64: return (jso->o.c_int64 != 0); case json_type_double: return (jso->o.c_double != 0); @@ -324,10 +321,6 @@ boolean json_object_get_boolean(struct json_object *jso) static int json_object_int_to_json_string(struct json_object* jso, struct printbuf *pb) { - return sprintbuf(pb, "%d", jso->o.c_int); -} - -static int json_object_int64_to_json_string(struct json_object* jso, struct printbuf *pb) { return sprintbuf(pb, "%"PRId64, jso->o.c_int64); } @@ -336,7 +329,7 @@ struct json_object* json_object_new_int(int32_t i) struct json_object *jso = json_object_new(json_type_int); if(!jso) return NULL; jso->_to_json_string = &json_object_int_to_json_string; - jso->o.c_int = i; + jso->o.c_int64 = i; return jso; } @@ -355,13 +348,11 @@ int32_t json_object_get_int(struct json_object *jso) */ if (json_parse_int64(jso->o.c_string, &cint64) != 0) return 0; /* whoops, it didn't work. */ - o_type = json_type_int64; + o_type = json_type_int; } switch(jso->o_type) { case json_type_int: - return jso->o.c_int; - case json_type_int64: /* Make sure we return the correct values for out of range numbers. */ if (cint64 <= INT32_MIN) return INT32_MIN; @@ -380,9 +371,9 @@ int32_t json_object_get_int(struct json_object *jso) struct json_object* json_object_new_int64(int64_t i) { - struct json_object *jso = json_object_new(json_type_int64); + struct json_object *jso = json_object_new(json_type_int); if(!jso) return NULL; - jso->_to_json_string = &json_object_int64_to_json_string; + jso->_to_json_string = &json_object_int_to_json_string; jso->o.c_int64 = i; return jso; } @@ -394,8 +385,6 @@ int64_t json_object_get_int64(struct json_object *jso) if(!jso) return 0; switch(jso->o_type) { case json_type_int: - return (int64_t)jso->o.c_int; - case json_type_int64: return jso->o.c_int64; case json_type_double: return (int64_t)jso->o.c_double; @@ -435,8 +424,6 @@ double json_object_get_double(struct json_object *jso) case json_type_double: return jso->o.c_double; case json_type_int: - return jso->o.c_int; - case json_type_int64: return jso->o.c_int64; case json_type_boolean: return jso->o.c_boolean; diff --git a/json_object.h b/json_object.h index cea4c810..9a44c6ef 100644 --- a/json_object.h +++ b/json_object.h @@ -47,7 +47,6 @@ typedef enum json_type { json_type_object, json_type_array, json_type_string, - json_type_int64 } json_type; /* reference counting functions */ @@ -75,7 +74,6 @@ extern void json_object_put(struct json_object *obj); json_type_object, json_type_array, json_type_string, - json_type_int64, */ extern int json_object_is_type(struct json_object *obj, enum json_type type); @@ -89,7 +87,6 @@ extern int json_object_is_type(struct json_object *obj, enum json_type type); json_type_object, json_type_array, json_type_string, - json_type_int64, */ extern enum json_type json_object_get_type(struct json_object *obj); @@ -252,15 +249,17 @@ extern boolean json_object_get_boolean(struct json_object *obj); /* int type methods */ /** Create a new empty json_object of type json_type_int + * Note that values are stored as 64-bit values internally. + * To ensure the full range is maintained, use json_object_new_int64 instead. * @param i the integer * @returns a json_object of type json_type_int */ extern struct json_object* json_object_new_int(int32_t i); -/** Create a new empty json_object of type json_type_int64 +/** Create a new empty json_object of type json_type_int * @param i the integer - * @returns a json_object of type json_type_int64 + * @returns a json_object of type json_type_int */ extern struct json_object* json_object_new_int64(int64_t i); @@ -271,6 +270,10 @@ extern struct json_object* json_object_new_int64(int64_t i); * double objects will return their integer conversion. Strings will be * parsed as an integer. If no conversion exists then 0 is returned. * + * Note that integers are stored internally as 64-bit values. + * If the value of too big or too small to fit into 32-bit, INT32_MAX or + * INT32_MIN are returned, respectively. + * * @param obj the json_object instance * @returns an int */ diff --git a/json_object_private.h b/json_object_private.h index a0f98456..04f510ad 100644 --- a/json_object_private.h +++ b/json_object_private.h @@ -30,7 +30,6 @@ struct json_object union data { boolean c_boolean; double c_double; - int32_t c_int; int64_t c_int64; struct lh_table *c_object; struct array_list *c_array; diff --git a/json_tokener.c b/json_tokener.c index dbaacaa9..da414e74 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -204,7 +204,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, case json_tokener_state_eatws: /* Advance until we change state */ - while (isspace(c)) { + while (isspace((int)c)) { if ((!ADVANCE_CHAR(str, tok)) || (!POP_CHAR(c, tok))) goto out; } @@ -547,17 +547,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, int64_t num64; double numd; if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) { - // Decode the type based on the value range to keep compatibilty - // with code that checks the type of objects. i.e. this: - // json_object_get_type(o) == json_type_int - // will continue to work. - // The other option would be to eliminate any distinction between - // int and int64 types, but that would change the ABI of - // json_object_get_int(). - if (num64 < INT32_MAX && num64 > INT32_MIN) - current = json_object_new_int(num64); - else - current = json_object_new_int64(num64); + current = json_object_new_int64(num64); } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) { current = json_object_new_double(numd); } else { diff --git a/json_util.c b/json_util.c index 0dcd6d50..9eca953c 100644 --- a/json_util.c +++ b/json_util.c @@ -10,6 +10,7 @@ */ #include "config.h" +#undef realloc #include #include @@ -131,7 +132,7 @@ int json_parse_int64(const char *buf, int64_t *retval) int64_t num64; if (sscanf(buf, "%" SCNd64, &num64) != 1) { - printf("Failed to parse, sscanf != 1\n"); + MC_DEBUG("Failed to parse, sscanf != 1\n"); return 1; } const char *buf_skip_space = buf; @@ -144,9 +145,11 @@ int json_parse_int64(const char *buf, int64_t *retval) buf_skip_space++; orig_has_neg = 1; } - // Skip leading zeros - while (*buf_skip_space == '0' && *buf_skip_space) + // Skip leading zeros, but keep at least one digit + while (buf_skip_space[0] == '0' && buf_skip_space[1] != '\0') buf_skip_space++; + if (buf_skip_space[0] == '0' && buf_skip_space[1] == '\0') + orig_has_neg = 0; // "-0" is the same as just plain "0" if (errno != ERANGE) { @@ -171,7 +174,7 @@ int json_parse_int64(const char *buf, int64_t *retval) if (orig_has_neg != recheck_has_neg || strncmp(buf_skip_space, buf_cmp_start, strlen(buf_cmp_start)) != 0 || (strlen(buf_skip_space) != buf_cmp_len && - isdigit(buf_skip_space[buf_cmp_len]) + isdigit((int)buf_skip_space[buf_cmp_len]) ) ) { @@ -188,3 +191,14 @@ int json_parse_int64(const char *buf, int64_t *retval) *retval = num64; return 0; } + +#if HAVE_REALLOC == 0 +void* rpl_realloc(void* p, size_t n) +{ + if (n == 0) + n = 1; + if (p == 0) + return malloc(n); + return realloc(p, n); +} +#endif diff --git a/printbuf.c b/printbuf.c index 97366c39..6ed1e944 100644 --- a/printbuf.c +++ b/printbuf.c @@ -123,7 +123,7 @@ int sprintbuf(struct printbuf *p, const char *msg, ...) would have been written - this code handles both cases. */ if(size == -1 || size > 127) { va_start(ap, msg); - if((size = vasprintf(&t, msg, ap)) == -1) { va_end(ap); return -1; } + if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; } va_end(ap); printbuf_memappend(p, t, size); free(t); diff --git a/test_parse_int64.c b/test_parse_int64.c index 42d45756..08933568 100644 --- a/test_parse_int64.c +++ b/test_parse_int64.c @@ -29,6 +29,12 @@ int main() checkit("x"); + checkit("0"); + checkit("-0"); + + checkit("00000000"); + checkit("-00000000"); + checkit("1"); strcpy(buf, "2147483647"); // aka INT32_MAX diff --git a/test_parse_int64.expected b/test_parse_int64.expected index 2d01ca77..23a9803e 100644 --- a/test_parse_int64.expected +++ b/test_parse_int64.expected @@ -1,5 +1,8 @@ -Failed to parse, sscanf != 1 buf=x parseit=1, value=-666 +buf=0 parseit=0, value=0 +buf=-0 parseit=0, value=0 +buf=00000000 parseit=0, value=0 +buf=-00000000 parseit=0, value=0 buf=1 parseit=0, value=1 buf=2147483647 parseit=0, value=2147483647 buf=-1 parseit=0, value=-1