Browse Source

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
tags/json-c-0.10-20120530
ehaszla 15 years ago
parent
commit
252669cee6
8 changed files with 43 additions and 41 deletions
  1. +4
    -17
      json_object.c
  2. +8
    -5
      json_object.h
  3. +0
    -1
      json_object_private.h
  4. +2
    -12
      json_tokener.c
  5. +18
    -4
      json_util.c
  6. +1
    -1
      printbuf.c
  7. +6
    -0
      test_parse_int64.c
  8. +4
    -1
      test_parse_int64.expected

+ 4
- 17
json_object.c View File

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


+ 8
- 5
json_object.h View File

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


+ 0
- 1
json_object_private.h View File

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


+ 2
- 12
json_tokener.c View File

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


+ 18
- 4
json_util.c View File

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

+ 1
- 1
printbuf.c View File

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


+ 6
- 0
test_parse_int64.c View File

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


+ 4
- 1
test_parse_int64.expected View File

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


Loading…
Cancel
Save