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-5cb71233fd97tags/json-c-0.10-20120530
| @@ -43,7 +43,6 @@ static const char* json_type_name[] = { | |||||
| "object", | "object", | ||||
| "array", | "array", | ||||
| "string", | "string", | ||||
| "int64", | |||||
| }; | }; | ||||
| #endif /* REFCOUNT_DEBUG */ | #endif /* REFCOUNT_DEBUG */ | ||||
| @@ -306,8 +305,6 @@ boolean json_object_get_boolean(struct json_object *jso) | |||||
| case json_type_boolean: | case json_type_boolean: | ||||
| return jso->o.c_boolean; | return jso->o.c_boolean; | ||||
| case json_type_int: | case json_type_int: | ||||
| return (jso->o.c_int != 0); | |||||
| case json_type_int64: | |||||
| return (jso->o.c_int64 != 0); | return (jso->o.c_int64 != 0); | ||||
| case json_type_double: | case json_type_double: | ||||
| return (jso->o.c_double != 0); | 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, | static int json_object_int_to_json_string(struct json_object* jso, | ||||
| struct printbuf *pb) | 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); | 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); | struct json_object *jso = json_object_new(json_type_int); | ||||
| if(!jso) return NULL; | if(!jso) return NULL; | ||||
| jso->_to_json_string = &json_object_int_to_json_string; | jso->_to_json_string = &json_object_int_to_json_string; | ||||
| jso->o.c_int = i; | |||||
| jso->o.c_int64 = i; | |||||
| return jso; | 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) | if (json_parse_int64(jso->o.c_string, &cint64) != 0) | ||||
| return 0; /* whoops, it didn't work. */ | return 0; /* whoops, it didn't work. */ | ||||
| o_type = json_type_int64; | |||||
| o_type = json_type_int; | |||||
| } | } | ||||
| switch(jso->o_type) { | switch(jso->o_type) { | ||||
| case json_type_int: | 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. */ | /* Make sure we return the correct values for out of range numbers. */ | ||||
| if (cint64 <= INT32_MIN) | if (cint64 <= INT32_MIN) | ||||
| return 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* 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; | 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; | jso->o.c_int64 = i; | ||||
| return jso; | return jso; | ||||
| } | } | ||||
| @@ -394,8 +385,6 @@ int64_t json_object_get_int64(struct json_object *jso) | |||||
| if(!jso) return 0; | if(!jso) return 0; | ||||
| switch(jso->o_type) { | switch(jso->o_type) { | ||||
| case json_type_int: | case json_type_int: | ||||
| return (int64_t)jso->o.c_int; | |||||
| case json_type_int64: | |||||
| return jso->o.c_int64; | return jso->o.c_int64; | ||||
| case json_type_double: | case json_type_double: | ||||
| return (int64_t)jso->o.c_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: | case json_type_double: | ||||
| return jso->o.c_double; | return jso->o.c_double; | ||||
| case json_type_int: | case json_type_int: | ||||
| return jso->o.c_int; | |||||
| case json_type_int64: | |||||
| return jso->o.c_int64; | return jso->o.c_int64; | ||||
| case json_type_boolean: | case json_type_boolean: | ||||
| return jso->o.c_boolean; | return jso->o.c_boolean; | ||||
| @@ -47,7 +47,6 @@ typedef enum json_type { | |||||
| json_type_object, | json_type_object, | ||||
| json_type_array, | json_type_array, | ||||
| json_type_string, | json_type_string, | ||||
| json_type_int64 | |||||
| } json_type; | } json_type; | ||||
| /* reference counting functions */ | /* reference counting functions */ | ||||
| @@ -75,7 +74,6 @@ extern void json_object_put(struct json_object *obj); | |||||
| json_type_object, | json_type_object, | ||||
| json_type_array, | json_type_array, | ||||
| json_type_string, | json_type_string, | ||||
| json_type_int64, | |||||
| */ | */ | ||||
| extern int json_object_is_type(struct json_object *obj, enum json_type type); | 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_object, | ||||
| json_type_array, | json_type_array, | ||||
| json_type_string, | json_type_string, | ||||
| json_type_int64, | |||||
| */ | */ | ||||
| extern enum json_type json_object_get_type(struct json_object *obj); | 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 */ | /* int type methods */ | ||||
| /** Create a new empty json_object of type json_type_int | /** 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 | * @param i the integer | ||||
| * @returns a json_object of type json_type_int | * @returns a json_object of type json_type_int | ||||
| */ | */ | ||||
| extern struct json_object* json_object_new_int(int32_t i); | 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 | * @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); | 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 | * double objects will return their integer conversion. Strings will be | ||||
| * parsed as an integer. If no conversion exists then 0 is returned. | * 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 | * @param obj the json_object instance | ||||
| * @returns an int | * @returns an int | ||||
| */ | */ | ||||
| @@ -30,7 +30,6 @@ struct json_object | |||||
| union data { | union data { | ||||
| boolean c_boolean; | boolean c_boolean; | ||||
| double c_double; | double c_double; | ||||
| int32_t c_int; | |||||
| int64_t c_int64; | int64_t c_int64; | ||||
| struct lh_table *c_object; | struct lh_table *c_object; | ||||
| struct array_list *c_array; | struct array_list *c_array; | ||||
| @@ -204,7 +204,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| case json_tokener_state_eatws: | case json_tokener_state_eatws: | ||||
| /* Advance until we change state */ | /* Advance until we change state */ | ||||
| while (isspace(c)) { | |||||
| while (isspace((int)c)) { | |||||
| if ((!ADVANCE_CHAR(str, tok)) || (!POP_CHAR(c, tok))) | if ((!ADVANCE_CHAR(str, tok)) || (!POP_CHAR(c, tok))) | ||||
| goto out; | goto out; | ||||
| } | } | ||||
| @@ -547,17 +547,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| int64_t num64; | int64_t num64; | ||||
| double numd; | double numd; | ||||
| if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) { | 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) { | } else if(tok->is_double && sscanf(tok->pb->buf, "%lf", &numd) == 1) { | ||||
| current = json_object_new_double(numd); | current = json_object_new_double(numd); | ||||
| } else { | } else { | ||||
| @@ -10,6 +10,7 @@ | |||||
| */ | */ | ||||
| #include "config.h" | #include "config.h" | ||||
| #undef realloc | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| @@ -131,7 +132,7 @@ int json_parse_int64(const char *buf, int64_t *retval) | |||||
| int64_t num64; | int64_t num64; | ||||
| if (sscanf(buf, "%" SCNd64, &num64) != 1) | if (sscanf(buf, "%" SCNd64, &num64) != 1) | ||||
| { | { | ||||
| printf("Failed to parse, sscanf != 1\n"); | |||||
| MC_DEBUG("Failed to parse, sscanf != 1\n"); | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| const char *buf_skip_space = buf; | const char *buf_skip_space = buf; | ||||
| @@ -144,9 +145,11 @@ int json_parse_int64(const char *buf, int64_t *retval) | |||||
| buf_skip_space++; | buf_skip_space++; | ||||
| orig_has_neg = 1; | 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++; | 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) | if (errno != ERANGE) | ||||
| { | { | ||||
| @@ -171,7 +174,7 @@ int json_parse_int64(const char *buf, int64_t *retval) | |||||
| if (orig_has_neg != recheck_has_neg || | if (orig_has_neg != recheck_has_neg || | ||||
| strncmp(buf_skip_space, buf_cmp_start, strlen(buf_cmp_start)) != 0 || | strncmp(buf_skip_space, buf_cmp_start, strlen(buf_cmp_start)) != 0 || | ||||
| (strlen(buf_skip_space) != buf_cmp_len && | (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; | *retval = num64; | ||||
| return 0; | 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 | |||||
| @@ -123,7 +123,7 @@ int sprintbuf(struct printbuf *p, const char *msg, ...) | |||||
| would have been written - this code handles both cases. */ | would have been written - this code handles both cases. */ | ||||
| if(size == -1 || size > 127) { | if(size == -1 || size > 127) { | ||||
| va_start(ap, msg); | 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); | va_end(ap); | ||||
| printbuf_memappend(p, t, size); | printbuf_memappend(p, t, size); | ||||
| free(t); | free(t); | ||||
| @@ -29,6 +29,12 @@ int main() | |||||
| checkit("x"); | checkit("x"); | ||||
| checkit("0"); | |||||
| checkit("-0"); | |||||
| checkit("00000000"); | |||||
| checkit("-00000000"); | |||||
| checkit("1"); | checkit("1"); | ||||
| strcpy(buf, "2147483647"); // aka INT32_MAX | strcpy(buf, "2147483647"); // aka INT32_MAX | ||||
| @@ -1,5 +1,8 @@ | |||||
| Failed to parse, sscanf != 1 | |||||
| buf=x parseit=1, value=-666 | 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=1 parseit=0, value=1 | ||||
| buf=2147483647 parseit=0, value=2147483647 | buf=2147483647 parseit=0, value=2147483647 | ||||
| buf=-1 parseit=0, value=-1 | buf=-1 parseit=0, value=-1 | ||||