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", | |||
"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; | |||
@@ -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 | |||
*/ | |||
@@ -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; | |||
@@ -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 { | |||
@@ -10,6 +10,7 @@ | |||
*/ | |||
#include "config.h" | |||
#undef realloc | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
@@ -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 |
@@ -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); | |||
@@ -29,6 +29,12 @@ int main() | |||
checkit("x"); | |||
checkit("0"); | |||
checkit("-0"); | |||
checkit("00000000"); | |||
checkit("-00000000"); | |||
checkit("1"); | |||
strcpy(buf, "2147483647"); // aka INT32_MAX | |||
@@ -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 | |||