From 3c3b5920f77c751471cd46b92f9d3f5aa6ff2557 Mon Sep 17 00:00:00 2001 From: dota17 Date: Thu, 20 Feb 2020 15:17:05 +0800 Subject: [PATCH 1/4] add uint64 data to json-c --- CMakeLists.txt | 11 ++++ cmake/config.h.in | 2 + config.h.win32 | 2 + configure.ac | 1 + json_inttypes.h | 1 + json_object.c | 95 +++++++++++++++++++++++++++++++++ json_object.h | 49 +++++++++++++++++ json_object_private.h | 1 + json_tokener.c | 32 +++++++---- json_util.c | 21 +++++++- json_util.h | 1 + json_visit.c | 1 + tests/test_cast.c | 19 +++++-- tests/test_cast.expected | 45 ++++++++++------ tests/test_compare.c | 21 ++++++++ tests/test_compare.expected | 3 ++ tests/test_int_add.c | 12 +++++ tests/test_int_add.expected | 2 + tests/test_parse.c | 12 ++++- tests/test_parse.expected | 10 +++- tests/test_parse_int64.c | 82 ++++++++++++++++++++++++++-- tests/test_parse_int64.expected | 28 ++++++++++ tests/test_set_value.c | 16 ++++++ tests/test_set_value.expected | 1 + 24 files changed, 431 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0008cbb..2fce869 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,6 +142,7 @@ endif() if (MSVC) check_symbol_exists(strtoll "stdlib.h" HAVE_STRTOLL) + check_symbol_exists(strtoull "stdlib.h" HAVE_STRTOULL) set(json_c_strtoll "strtoll") if (NOT HAVE_STRTOLL) @@ -153,6 +154,16 @@ if (MSVC) # could do the same for strtoull, if needed endif() endif() + + set(json_c_strtoull "strtoull") + if (NOT HAVE_STRTOULL) + # Use _strtoui64 if strtoull is not available. + check_symbol_exists(_strtoui64 "stdlib.h" __have_strtoui64) + if (__have_strtoui64) + set(HAVE_STRTOULL 1) + set(json_c_strtoull "_strtoui64") + endif() + endif() endif() diff --git a/cmake/config.h.in b/cmake/config.h.in index 628ddfe..3539d6f 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -137,6 +137,8 @@ #cmakedefine HAVE_STRTOLL #cmakedefine strtoll @json_c_strtoll@ +#cmakedefine HAVE_STRTOULL +#cmakedefine strtoull @json_c_strtoull@ /* Have __thread */ #cmakedefine HAVE___THREAD diff --git a/config.h.win32 b/config.h.win32 index 0e14c7a..a2896bf 100644 --- a/config.h.win32 +++ b/config.h.win32 @@ -115,6 +115,8 @@ #cmakedefine HAVE_STRTOLL #cmakedefine strtoll @cmake_strtoll@ +#cmakedefine HAVE_STRTOULL +#cmakedefine strtoull @cmake_strtoull@ /* Define to 1 if you have the header file. */ #undef HAVE_SYSLOG_H diff --git a/configure.ac b/configure.ac index 120797e..5fae89d 100644 --- a/configure.ac +++ b/configure.ac @@ -200,6 +200,7 @@ AX_COMPILE_CHECK_SIZEOF(long) AX_COMPILE_CHECK_SIZEOF(long long) AX_COMPILE_CHECK_SIZEOF(size_t, [#include ]) AX_COMPILE_CHECK_SIZEOF(int64_t, [#include ]) +AX_COMPILE_CHECK_SIZEOF(uint64_t, [#include ]) AC_CONFIG_FILES([ Makefile diff --git a/json_inttypes.h b/json_inttypes.h index 3854913..e047d4f 100644 --- a/json_inttypes.h +++ b/json_inttypes.h @@ -17,6 +17,7 @@ #define PRId64 "I64d" #define SCNd64 "I64d" +#define PRIu64 "I64u" #endif diff --git a/json_object.c b/json_object.c index ded3661..6bd8517 100644 --- a/json_object.c +++ b/json_object.c @@ -51,6 +51,7 @@ static json_object_to_json_string_fn json_object_object_to_json_string; static json_object_to_json_string_fn json_object_boolean_to_json_string; static json_object_to_json_string_fn json_object_double_to_json_string_default; static json_object_to_json_string_fn json_object_int_to_json_string; +static json_object_to_json_string_fn json_object_uint_to_json_string; static json_object_to_json_string_fn json_object_string_to_json_string; static json_object_to_json_string_fn json_object_array_to_json_string; static json_object_to_json_string_fn _json_object_userdata_to_json_string; @@ -302,6 +303,9 @@ void json_object_set_serializer(json_object *jso, case json_type_int: jso->_to_json_string = &json_object_int_to_json_string; break; + case json_type_uint: + jso->_to_json_string = &json_object_uint_to_json_string; + break; case json_type_object: jso->_to_json_string = &json_object_object_to_json_string; break; @@ -592,6 +596,8 @@ json_bool json_object_get_boolean(const struct json_object *jso) return jso->o.c_boolean; case json_type_int: return (jso->o.c_int64 != 0); + case json_type_uint: + return (jso->o.c_uint64 != 0); case json_type_double: return (jso->o.c_double != 0); case json_type_string: @@ -622,6 +628,17 @@ static int json_object_int_to_json_string(struct json_object* jso, return printbuf_memappend (pb, sbuf, strlen(sbuf)); } +static int json_object_uint_to_json_string(struct json_object* jso, + struct printbuf *pb, + int level, + int flags) +{ + /* room for 20 digits, and a null term */ + char sbuf[21]; + snprintf(sbuf, sizeof(sbuf), "%" PRIu64, jso->o.c_uint64); + return printbuf_memappend (pb, sbuf, strlen(sbuf)); +} + struct json_object* json_object_new_int(int32_t i) { struct json_object *jso = json_object_new(json_type_int); @@ -661,6 +678,10 @@ int32_t json_object_get_int(const struct json_object *jso) if (cint64 >= INT32_MAX) return INT32_MAX; return (int32_t) cint64; + case json_type_uint: + if (jso->o.c_uint64 >= INT32_MAX) + return INT32_MAX; + return (int32_t)jso->o.c_uint64; case json_type_double: if (jso->o.c_double <= INT32_MIN) return INT32_MIN; @@ -691,6 +712,16 @@ struct json_object* json_object_new_int64(int64_t i) return jso; } +struct json_object* json_object_new_uint64(uint64_t i) +{ + struct json_object *jso = json_object_new(json_type_uint); + if (!jso) + return NULL; + jso->_to_json_string = &json_object_uint_to_json_string; + jso->o.c_uint64 = i; + return jso; +} + int64_t json_object_get_int64(const struct json_object *jso) { int64_t cint; @@ -701,6 +732,10 @@ int64_t json_object_get_int64(const struct json_object *jso) { case json_type_int: return jso->o.c_int64; + case json_type_uint: + if (jso->o.c_uint64 >= INT64_MAX) + return INT64_MAX; + return (int64_t)jso->o.c_uint64; case json_type_double: // INT64_MAX can't be exactly represented as a double // so cast to tell the compiler it's ok to round up. @@ -720,6 +755,39 @@ int64_t json_object_get_int64(const struct json_object *jso) } } +uint64_t json_object_get_uint64(const struct json_object *jso) +{ + uint64_t cuint; + + if (!jso) + return 0; + switch(jso->o_type) + { + case json_type_int: + if (jso->o.c_int64 < 0) + return 0; + return (uint64_t)jso->o.c_int64; + case json_type_uint: + return jso->o.c_uint64; + case json_type_double: + // UINT64_MAX can't be exactly represented as a double + // so cast to tell the compiler it's ok to round up. + if (jso->o.c_double >= (double)UINT64_MAX) + return UINT64_MAX; + if (jso->o.c_double < 0) + return 0; + return (uint64_t)jso->o.c_double; + case json_type_boolean: + return jso->o.c_boolean; + case json_type_string: + if (json_parse_uint64(get_string_component(jso), &cuint) == 0) + return cuint; + /* FALLTHRU */ + default: + return 0; + } +} + int json_object_set_int64(struct json_object *jso,int64_t new_value){ if (!jso || jso->o_type!=json_type_int) return 0; @@ -727,6 +795,13 @@ int json_object_set_int64(struct json_object *jso,int64_t new_value){ return 1; } +int json_object_set_uint64(struct json_object *jso,uint64_t new_value){ + if (!jso || jso->o_type!=json_type_uint) + return 0; + jso->o.c_uint64=new_value; + return 1; +} + int json_object_int_inc(struct json_object *jso, int64_t val) { if (!jso || jso->o_type != json_type_int) return 0; @@ -740,6 +815,17 @@ int json_object_int_inc(struct json_object *jso, int64_t val) { return 1; } +int json_object_uint_inc(struct json_object *jso, uint64_t val) { + if (!jso || jso->o_type != json_type_uint) + return 0; + if (jso->o.c_uint64 > UINT64_MAX - val) { + jso->o.c_uint64 = UINT64_MAX; + } else { + jso->o.c_uint64 += val; + } + return 1; +} + /* json_object_double */ #if defined(HAVE___THREAD) @@ -962,6 +1048,8 @@ double json_object_get_double(const struct json_object *jso) return jso->o.c_double; case json_type_int: return jso->o.c_int64; + case json_type_uint: + return jso->o.c_uint64; case json_type_boolean: return jso->o.c_boolean; case json_type_string: @@ -1342,6 +1430,9 @@ int json_object_equal(struct json_object* jso1, struct json_object* jso2) case json_type_int: return (jso1->o.c_int64 == jso2->o.c_int64); + case json_type_uint: + return (jso1->o.c_uint64 == jso2->o.c_uint64); + case json_type_string: return (jso1->o.c_string.len == jso2->o.c_string.len && memcmp(get_string_component(jso1), @@ -1405,6 +1496,10 @@ int json_c_shallow_copy_default(json_object *src, json_object *parent, const cha *dst = json_object_new_int64(src->o.c_int64); break; + case json_type_uint: + *dst = json_object_new_uint64(src->o.c_uint64); + break; + case json_type_string: *dst = json_object_new_string(get_string_component(src)); break; diff --git a/json_object.h b/json_object.h index c36d68b..4e13ec1 100644 --- a/json_object.h +++ b/json_object.h @@ -176,6 +176,7 @@ typedef enum json_type { json_type_boolean, json_type_double, json_type_int, + json_type_uint, json_type_object, json_type_array, json_type_string @@ -210,6 +211,7 @@ JSON_EXPORT int json_object_put(struct json_object *obj); json_type_boolean, json_type_double, json_type_int, + json_type_uint, json_type_object, json_type_array, json_type_string @@ -226,6 +228,7 @@ JSON_EXPORT int json_object_is_type(const struct json_object *obj, enum json_typ json_type_boolean, json_type_double, json_type_int, + json_type_uint, json_type_object, json_type_array, json_type_string @@ -701,6 +704,13 @@ JSON_EXPORT struct json_object* json_object_new_int(int32_t i); JSON_EXPORT struct json_object* json_object_new_int64(int64_t i); +/** Create a new empty json_object of type json_type_uint + * @param i the integer + * @returns a json_object of type json_type_uint + */ +JSON_EXPORT struct json_object* json_object_new_uint64(uint64_t i); + + /** Get the int value of a json_object * * The type is coerced to a int if the passed object is not a int. @@ -745,6 +755,19 @@ JSON_EXPORT int json_object_set_int(struct json_object *obj,int new_value); */ JSON_EXPORT int json_object_int_inc(struct json_object *obj, int64_t val); +/** Increment a json_type_uint object by the given amount, which may be negative. + * + * If the type of obj is not json_type_uint then 0 is returned with no further + * action taken. + * If the addition would result in a overflow, the object value + * is set to UINT64_MAX. + * Neither overflow nor underflow affect the return value. + * + * @param obj the json_object instance + * @param val the value to add + * @returns 1 if the increment succeded, 0 otherwise + */ +JSON_EXPORT int json_object_uint_inc(struct json_object *obj, uint64_t val); /** Get the int value of a json_object * @@ -761,6 +784,20 @@ JSON_EXPORT int json_object_int_inc(struct json_object *obj, int64_t val); */ JSON_EXPORT int64_t json_object_get_int64(const struct json_object *obj); +/** Get the uint value of a json_object + * + * The type is coerced to a uint64 if the passed object is not a uint64. + * double objects will return their uint64 conversion. Strings will be + * parsed as an uint64. If no conversion exists then 0 is returned. + * + * NOTE: Set errno to 0 directly before a call to this function to determine + * whether or not conversion was successful (it does not clear the value for + * you). + * + * @param obj the json_object instance + * @returns an uint64 + */ +JSON_EXPORT uint64_t json_object_get_uint64(const struct json_object *obj); /** Set the int64_t value of a json_object * @@ -774,6 +811,18 @@ JSON_EXPORT int64_t json_object_get_int64(const struct json_object *obj); */ JSON_EXPORT int json_object_set_int64(struct json_object *obj,int64_t new_value); +/** Set the uint64_t value of a json_object + * + * The type of obj is checked to be a json_type_uint and 0 is returned + * if it is not without any further actions. If type of obj is json_type_uint + * the object value is changed to new_value + * + * @param obj the json_object instance + * @param new_value the value to be set + * @returns 1 if value is set correctly, 0 otherwise + */ +JSON_EXPORT int json_object_set_uint64(struct json_object *obj,uint64_t new_value); + /* double type methods */ /** Create a new empty json_object of type json_type_double diff --git a/json_object_private.h b/json_object_private.h index 4c6681a..f7109b7 100644 --- a/json_object_private.h +++ b/json_object_private.h @@ -35,6 +35,7 @@ struct json_object json_bool c_boolean; double c_double; int64_t c_int64; + uint64_t c_uint64; struct lh_table *c_object; struct array_list *c_array; struct { diff --git a/json_tokener.c b/json_tokener.c index 246d5bd..68795c6 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -792,21 +792,33 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, } { int64_t num64; + uint64_t numuint64; double numd; - if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) { - if (num64 && tok->pb->buf[0]=='0' && - (tok->flags & JSON_TOKENER_STRICT)) { - /* in strict mode, number must not start with 0 */ - tok->err = json_tokener_error_parse_number; - goto out; - } + if (!tok->is_double && tok->pb->buf[0] == '-' + && json_parse_int64(tok->pb->buf, &num64) == 0) { current = json_object_new_int64(num64); if(current == NULL) goto out; - } - else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) + } else if ( !tok->is_double && tok->pb->buf[0] != '-' + && json_parse_uint64(tok->pb->buf, &numuint64) == 0) { + if (numuint64 && tok->pb->buf[0]=='0' && + (tok->flags & JSON_TOKENER_STRICT)) { + tok->err = json_tokener_error_parse_number; + goto out; + } + if (numuint64 <= INT64_MAX){ + num64 = (uint64_t) numuint64; + current = json_object_new_int64(num64); + if(current == NULL) + goto out; + } else { + current = json_object_new_uint64(numuint64); + if(current == NULL) + goto out; + } + } else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) { - current = json_object_new_double_s(numd, tok->pb->buf); + current = json_object_new_double_s(numd, tok->pb->buf); if(current == NULL) goto out; } else { diff --git a/json_util.c b/json_util.c index 3ff631d..8902d31 100644 --- a/json_util.c +++ b/json_util.c @@ -40,8 +40,9 @@ #ifdef WIN32 # if MSC_VER < 1800 -/* strtoll is available only since Visual Studio 2013 */ +/* strtoll/strtoull is available only since Visual Studio 2013 */ # define strtoll _strtoi64 +# define strtoull _strtoui64 # endif # define WIN32_LEAN_AND_MEAN # include @@ -230,6 +231,23 @@ int json_parse_int64(const char *buf, int64_t *retval) return ((val == 0 && errno != 0) || (end == buf)) ? 1 : 0; } +int json_parse_uint64(const char *buf, uint64_t *retval) +{ + char *end = NULL; + uint64_t val; + errno = 1; + + while (*buf == ' ') { + buf++; + } + if (*buf == '-') errno = 0; + + val = strtoull(buf, &end, 10); + if (end != buf) + *retval = val; + return ((errno == 0) || (end == buf)) ? 1 : 0; +} + #ifndef HAVE_REALLOC void* rpl_realloc(void* p, size_t n) { @@ -248,6 +266,7 @@ static const char* json_type_name[] = { "boolean", "double", "int", + "uint", "object", "array", "string", diff --git a/json_util.h b/json_util.h index 9620809..43adca9 100644 --- a/json_util.h +++ b/json_util.h @@ -103,6 +103,7 @@ JSON_EXPORT const char *json_util_get_last_err(void); JSON_EXPORT int json_parse_int64(const char *buf, int64_t *retval); +JSON_EXPORT int json_parse_uint64(const char *buf, uint64_t *retval); JSON_EXPORT int json_parse_double(const char *buf, double *retval); /** diff --git a/json_visit.c b/json_visit.c index 1126ff8..4419614 100644 --- a/json_visit.c +++ b/json_visit.c @@ -57,6 +57,7 @@ static int _json_c_visit(json_object *jso, json_object *parent_jso, case json_type_boolean: case json_type_double: case json_type_int: + case json_type_uint: case json_type_string: // we already called userfunc above, move on to the next object return JSON_C_VISIT_RETURN_CONTINUE; diff --git a/tests/test_cast.c b/tests/test_cast.c index 7e2bcd5..3daf5e1 100644 --- a/tests/test_cast.c +++ b/tests/test_cast.c @@ -25,10 +25,13 @@ int main(int argc, char **argv) \"decimal_number\": 99.55,\n\ \"boolean_true\": true,\n\ \"boolean_false\": false,\n\ - \"big_number\": 2147483649,\n\ + \"int64_number\": 2147483649,\n\ + \"negative_number\": -321321321,\n\ \"a_null\": null,\n\ }"; /* Note: 2147483649 = INT_MAX + 2 */ + /* Note: 9223372036854775809 = INT64_MAX + 2 */ + /* Note: 18446744073709551617 = UINT64_MAX + 2 */ struct json_object *new_obj; @@ -43,7 +46,8 @@ int main(int argc, char **argv) getit(new_obj, "decimal_number"); getit(new_obj, "boolean_true"); getit(new_obj, "boolean_false"); - getit(new_obj, "big_number"); + getit(new_obj, "int64_number"); + getit(new_obj, "negative_number"); getit(new_obj, "a_null"); // Now check the behaviour of the json_object_is_type() function. @@ -55,7 +59,8 @@ int main(int argc, char **argv) checktype(new_obj, "decimal_number"); checktype(new_obj, "boolean_true"); checktype(new_obj, "boolean_false"); - checktype(new_obj, "big_number"); + checktype(new_obj, "int64_number"); + checktype(new_obj, "negative_number"); checktype(new_obj, "a_null"); json_object_put(new_obj); @@ -76,6 +81,8 @@ static void getit(struct json_object *new_obj, const char *field) json_object_get_int(o)); printf("new_obj.%s json_object_get_int64()=%" PRId64 "\n", field, json_object_get_int64(o)); + printf("new_obj.%s json_object_get_uint64()=%" PRIu64 "\n", field, + json_object_get_uint64(o)); printf("new_obj.%s json_object_get_boolean()=%d\n", field, json_object_get_boolean(o)); printf("new_obj.%s json_object_get_double()=%f\n", field, @@ -84,11 +91,12 @@ static void getit(struct json_object *new_obj, const char *field) static void checktype_header() { - printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s\n", + printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s,%s\n", json_type_to_name(json_type_null), json_type_to_name(json_type_boolean), json_type_to_name(json_type_double), json_type_to_name(json_type_int), + json_type_to_name(json_type_uint), json_type_to_name(json_type_object), json_type_to_name(json_type_array), json_type_to_name(json_type_string)); @@ -99,12 +107,13 @@ static void checktype(struct json_object *new_obj, const char *field) if (field && !json_object_object_get_ex(new_obj, field, &o)) printf("Field %s does not exist\n", field); - printf("new_obj%s%-18s: %d,%d,%d,%d,%d,%d,%d\n", + printf("new_obj%s%-18s: %d,%d,%d,%d,%d,%d,%d,%d\n", field ? "." : " ", field ? field : "", json_object_is_type(o, json_type_null), json_object_is_type(o, json_type_boolean), json_object_is_type(o, json_type_double), json_object_is_type(o, json_type_int), + json_object_is_type(o, json_type_uint), json_object_is_type(o, json_type_object), json_object_is_type(o, json_type_array), json_object_is_type(o, json_type_string)); diff --git a/tests/test_cast.expected b/tests/test_cast.expected index 76ff823..92ea886 100644 --- a/tests/test_cast.expected +++ b/tests/test_cast.expected @@ -4,53 +4,68 @@ Parsed input: { "decimal_number": 99.55, "boolean_true": true, "boolean_false": false, - "big_number": 2147483649, + "int64_number": 2147483649, + "negative_number": -321321321, "a_null": null, } Result is not NULL new_obj.string_of_digits json_object_get_type()=string new_obj.string_of_digits json_object_get_int()=123 new_obj.string_of_digits json_object_get_int64()=123 +new_obj.string_of_digits json_object_get_uint64()=123 new_obj.string_of_digits json_object_get_boolean()=1 new_obj.string_of_digits json_object_get_double()=123.000000 new_obj.regular_number json_object_get_type()=int new_obj.regular_number json_object_get_int()=222 new_obj.regular_number json_object_get_int64()=222 +new_obj.regular_number json_object_get_uint64()=222 new_obj.regular_number json_object_get_boolean()=1 new_obj.regular_number json_object_get_double()=222.000000 new_obj.decimal_number json_object_get_type()=double new_obj.decimal_number json_object_get_int()=99 new_obj.decimal_number json_object_get_int64()=99 +new_obj.decimal_number json_object_get_uint64()=99 new_obj.decimal_number json_object_get_boolean()=1 new_obj.decimal_number json_object_get_double()=99.550000 new_obj.boolean_true json_object_get_type()=boolean new_obj.boolean_true json_object_get_int()=1 new_obj.boolean_true json_object_get_int64()=1 +new_obj.boolean_true json_object_get_uint64()=1 new_obj.boolean_true json_object_get_boolean()=1 new_obj.boolean_true json_object_get_double()=1.000000 new_obj.boolean_false json_object_get_type()=boolean new_obj.boolean_false json_object_get_int()=0 new_obj.boolean_false json_object_get_int64()=0 +new_obj.boolean_false json_object_get_uint64()=0 new_obj.boolean_false json_object_get_boolean()=0 new_obj.boolean_false json_object_get_double()=0.000000 -new_obj.big_number json_object_get_type()=int -new_obj.big_number json_object_get_int()=2147483647 -new_obj.big_number json_object_get_int64()=2147483649 -new_obj.big_number json_object_get_boolean()=1 -new_obj.big_number json_object_get_double()=2147483649.000000 +new_obj.int64_number json_object_get_type()=int +new_obj.int64_number json_object_get_int()=2147483647 +new_obj.int64_number json_object_get_int64()=2147483649 +new_obj.int64_number json_object_get_uint64()=2147483649 +new_obj.int64_number json_object_get_boolean()=1 +new_obj.int64_number json_object_get_double()=2147483649.000000 +new_obj.negative_number json_object_get_type()=int +new_obj.negative_number json_object_get_int()=-321321321 +new_obj.negative_number json_object_get_int64()=-321321321 +new_obj.negative_number json_object_get_uint64()=0 +new_obj.negative_number json_object_get_boolean()=1 +new_obj.negative_number json_object_get_double()=-321321321.000000 new_obj.a_null json_object_get_type()=null new_obj.a_null json_object_get_int()=0 new_obj.a_null json_object_get_int64()=0 +new_obj.a_null json_object_get_uint64()=0 new_obj.a_null json_object_get_boolean()=0 new_obj.a_null json_object_get_double()=0.000000 ================================ -json_object_is_type: null,boolean,double,int,object,array,string -new_obj : 0,0,0,0,1,0,0 -new_obj.string_of_digits : 0,0,0,0,0,0,1 -new_obj.regular_number : 0,0,0,1,0,0,0 -new_obj.decimal_number : 0,0,1,0,0,0,0 -new_obj.boolean_true : 0,1,0,0,0,0,0 -new_obj.boolean_false : 0,1,0,0,0,0,0 -new_obj.big_number : 0,0,0,1,0,0,0 -new_obj.a_null : 1,0,0,0,0,0,0 +json_object_is_type: null,boolean,double,int,uint,object,array,string +new_obj : 0,0,0,0,0,1,0,0 +new_obj.string_of_digits : 0,0,0,0,0,0,0,1 +new_obj.regular_number : 0,0,0,1,0,0,0,0 +new_obj.decimal_number : 0,0,1,0,0,0,0,0 +new_obj.boolean_true : 0,1,0,0,0,0,0,0 +new_obj.boolean_false : 0,1,0,0,0,0,0,0 +new_obj.int64_number : 0,0,0,1,0,0,0,0 +new_obj.negative_number : 0,0,0,1,0,0,0,0 +new_obj.a_null : 1,0,0,0,0,0,0,0 diff --git a/tests/test_compare.c b/tests/test_compare.c index 49b0587..13ad3ea 100644 --- a/tests/test_compare.c +++ b/tests/test_compare.c @@ -15,6 +15,9 @@ int main() struct json_object *int1 = json_object_new_int(0); struct json_object *int2 = json_object_new_int(1); struct json_object *int3 = json_object_new_int(1); + struct json_object *uint1 = json_object_new_uint64(0); + struct json_object *uint2 = json_object_new_uint64(1); + struct json_object *uint3 = json_object_new_uint64(1); if (!json_object_equal(int1, int2)) printf("JSON integer comparison is correct\n"); @@ -31,9 +34,27 @@ int main() else printf("JSON same integer comparison failed\n"); + if (!json_object_equal(uint1, uint2)) + printf("JSON usigned integer comparison is correct\n"); + else + printf("JSON usigned integer comparison failed\n"); + + if (json_object_equal(uint1, uint1)) + printf("JSON same usigned object comparison is correct\n"); + else + printf("JSON same usigned object comparison failed\n"); + + if (json_object_equal(uint2, uint3)) + printf("JSON same usigned integer comparison is correct\n"); + else + printf("JSON same usigned integer comparison failed\n"); + json_object_put(int1); json_object_put(int2); json_object_put(int3); + json_object_put(uint1); + json_object_put(uint2); + json_object_put(uint3); /* string tests */ struct json_object *str1 = json_object_new_string("TESTSTRING"); diff --git a/tests/test_compare.expected b/tests/test_compare.expected index 5468f83..a183aab 100644 --- a/tests/test_compare.expected +++ b/tests/test_compare.expected @@ -1,6 +1,9 @@ JSON integer comparison is correct JSON same object comparison is correct JSON same integer comparison is correct +JSON usigned integer comparison is correct +JSON same usigned object comparison is correct +JSON same usigned integer comparison is correct Comparing equal strings is correct Comparing different strings is correct Comparing equal doubles is correct diff --git a/tests/test_int_add.c b/tests/test_int_add.c index 08a8802..8b02e79 100644 --- a/tests/test_int_add.c +++ b/tests/test_int_add.c @@ -41,6 +41,18 @@ int main(int argc, char **argv) assert(json_object_get_int64(tmp) != INT64_MIN); json_object_put(tmp); printf("INT64 ADD UNDERFLOW PASSED\n"); + tmp = json_object_new_uint64(321321321); + json_object_uint_inc(tmp, 321321321); + assert(json_object_get_uint64(tmp) == 642642642); + json_object_put(tmp); + printf("UINT64 ADD PASSED\n"); + tmp = json_object_new_uint64(UINT64_MAX); + json_object_uint_inc(tmp, 100); + assert(json_object_get_uint64(tmp) == UINT64_MAX); + json_object_uint_inc(tmp, -100); + assert(json_object_get_uint64(tmp) != INT64_MAX); + json_object_put(tmp); + printf("UINT64 ADD OVERFLOW PASSED\n"); printf("PASSED\n"); return 0; diff --git a/tests/test_int_add.expected b/tests/test_int_add.expected index 61c205c..144233a 100644 --- a/tests/test_int_add.expected +++ b/tests/test_int_add.expected @@ -4,4 +4,6 @@ INT ADD UNDERFLOW PASSED INT64 ADD PASSED INT64 ADD OVERFLOW PASSED INT64 ADD UNDERFLOW PASSED +UINT64 ADD PASSED +UINT64 ADD OVERFLOW PASSED PASSED diff --git a/tests/test_parse.c b/tests/test_parse.c index f8fc8b7..61844ca 100644 --- a/tests/test_parse.c +++ b/tests/test_parse.c @@ -128,8 +128,18 @@ static void test_basic_parse() single_basic_parse("[0e]", 1); single_basic_parse("[0e+]", 1); single_basic_parse("[0e+-1]", 1); - single_basic_parse("[18446744073709551616]", 1); single_basic_parse("\"hello world!\"", 1); + + // uint64/int64 range test + single_basic_parse("[9223372036854775806]", 1); + single_basic_parse("[9223372036854775807]", 1); + single_basic_parse("[9223372036854775808]", 1); + single_basic_parse("[-9223372036854775807]", 1); + single_basic_parse("[-9223372036854775808]", 1); + single_basic_parse("[-9223372036854775809]", 1); + single_basic_parse("[18446744073709551614]", 1); + single_basic_parse("[18446744073709551615]", 1); + single_basic_parse("[18446744073709551616]", 1); } static void test_utf8_parse() diff --git a/tests/test_parse.expected b/tests/test_parse.expected index 68e55b1..83c5573 100644 --- a/tests/test_parse.expected +++ b/tests/test_parse.expected @@ -66,8 +66,16 @@ new_obj.to_string(false)=false new_obj.to_string([0e])=[ 0.0 ] new_obj.to_string([0e+])=[ 0.0 ] new_obj.to_string([0e+-1])=null -new_obj.to_string([18446744073709551616])=[ 9223372036854775807 ] new_obj.to_string("hello world!")="hello world!" +new_obj.to_string([9223372036854775806])=[ 9223372036854775806 ] +new_obj.to_string([9223372036854775807])=[ 9223372036854775807 ] +new_obj.to_string([9223372036854775808])=[ 9223372036854775808 ] +new_obj.to_string([-9223372036854775807])=[ -9223372036854775807 ] +new_obj.to_string([-9223372036854775808])=[ -9223372036854775808 ] +new_obj.to_string([-9223372036854775809])=[ -9223372036854775808 ] +new_obj.to_string([18446744073709551614])=[ 18446744073709551614 ] +new_obj.to_string([18446744073709551615])=[ 18446744073709551615 ] +new_obj.to_string([18446744073709551616])=[ 18446744073709551615 ] ================================== new_obj.to_string()=null new_obj.to_string({})=null diff --git a/tests/test_parse_int64.c b/tests/test_parse_int64.c index c251e01..33dd9bc 100644 --- a/tests/test_parse_int64.c +++ b/tests/test_parse_int64.c @@ -15,10 +15,18 @@ void checkit(const char *buf) printf("buf=%s parseit=%d, value=%" PRId64 " \n", buf, retval, cint64); } +void checkit_uint(const char *buf) +{ + uint64_t cuint64 = 666; + + int retval = json_parse_uint64(buf, &cuint64); + printf("buf=%s parseit=%d, value=%" PRIu64 " \n", buf, retval, cuint64); +} + /** - * This test calls json_parse_int64 with a variety of different strings. - * It's purpose is to ensure that the results are consistent across all - * different environments that it might be executed in. + * This test calls json_parse_int64 and json_parse_int64 with a variety + * of different strings. It's purpose is to ensure that the results are + * consistent across all different environments that it might be executed in. * * This always exits with a 0 exit value. The output should be compared * against previously saved expected output. @@ -27,6 +35,7 @@ int main() { char buf[100]; + printf("==========json_parse_int64() test===========\n"); checkit("x"); checkit("0"); @@ -59,8 +68,10 @@ int main() checkit(buf); strcpy(buf, "4294967295"); // aka UINT32_MAX + checkit(buf); - sprintf(buf, "4294967296"); // aka UINT32_MAX + 1 + strcpy(buf, "4294967296"); // aka UINT32_MAX + 1 + checkit(buf); strcpy(buf, "21474836470"); // INT32_MAX * 10 checkit(buf); @@ -111,5 +122,68 @@ int main() strcpy(buf, "123"); checkit(buf); + printf("\n==========json_parse_uint64() test===========\n"); + checkit_uint("x"); + + checkit_uint("0"); + checkit_uint("-0"); + + checkit_uint("00000000"); + checkit_uint("-00000000"); + + checkit_uint("1"); + + strcpy(buf, "2147483647"); // aka INT32_MAX + checkit_uint(buf); + + strcpy(buf, "-1"); + checkit_uint(buf); + + strcpy(buf, "-9223372036854775808"); + checkit_uint(buf); + + strcpy(buf, " 1"); + checkit_uint(buf); + + strcpy(buf, "00001234"); + checkit_uint(buf); + + strcpy(buf, "0001234x"); + checkit_uint(buf); + + strcpy(buf, "4294967295"); // aka UINT32_MAX + checkit_uint(buf); + + strcpy(buf, "4294967296"); // aka UINT32_MAX + 1 + checkit_uint(buf); + + strcpy(buf, "21474836470"); // INT32_MAX * 10 + checkit_uint(buf); + + strcpy(buf, "31474836470"); // INT32_MAX * 10 + a bunch + checkit_uint(buf); + + strcpy(buf, "9223372036854775806"); // INT64_MAX - 1 + checkit_uint(buf); + + strcpy(buf, "9223372036854775807"); // INT64_MAX + checkit_uint(buf); + + strcpy(buf, "9223372036854775808"); // INT64_MAX + 1 + checkit_uint(buf); + + strcpy(buf, "18446744073709551614"); // UINT64_MAX - 1 + checkit_uint(buf); + + strcpy(buf, "18446744073709551615"); // UINT64_MAX + checkit_uint(buf); + + strcpy(buf, "18446744073709551616"); // UINT64_MAX + 1 + checkit_uint(buf); + + // Ensure we can still parse valid numbers after parsing out of range ones. + strcpy(buf, "123"); + checkit_uint(buf); + return 0; } diff --git a/tests/test_parse_int64.expected b/tests/test_parse_int64.expected index d9cdf5a..f4c5750 100644 --- a/tests/test_parse_int64.expected +++ b/tests/test_parse_int64.expected @@ -1,3 +1,4 @@ +==========json_parse_int64() test=========== buf=x parseit=1, value=-666 buf=0 parseit=0, value=0 buf=-0 parseit=0, value=0 @@ -11,6 +12,8 @@ buf=00001234 parseit=0, value=1234 buf=0001234x parseit=0, value=1234 buf=-00001234 parseit=0, value=-1234 buf=-00001234x parseit=0, value=-1234 +buf=4294967295 parseit=0, value=4294967295 +buf=4294967296 parseit=0, value=4294967296 buf=21474836470 parseit=0, value=21474836470 buf=31474836470 parseit=0, value=31474836470 buf=-2147483647 parseit=0, value=-2147483647 @@ -27,3 +30,28 @@ buf=18446744073709551615 parseit=0, value=9223372036854775807 buf=18446744073709551616 parseit=0, value=9223372036854775807 buf=-18446744073709551616 parseit=0, value=-9223372036854775808 buf=123 parseit=0, value=123 + +==========json_parse_uint64() test=========== +buf=x parseit=1, value=666 +buf=0 parseit=0, value=0 +buf=-0 parseit=1, value=0 +buf=00000000 parseit=0, value=0 +buf=-00000000 parseit=1, value=0 +buf=1 parseit=0, value=1 +buf=2147483647 parseit=0, value=2147483647 +buf=-1 parseit=1, value=18446744073709551615 +buf=-9223372036854775808 parseit=1, value=9223372036854775808 +buf= 1 parseit=0, value=1 +buf=00001234 parseit=0, value=1234 +buf=0001234x parseit=0, value=1234 +buf=4294967295 parseit=0, value=4294967295 +buf=4294967296 parseit=0, value=4294967296 +buf=21474836470 parseit=0, value=21474836470 +buf=31474836470 parseit=0, value=31474836470 +buf=9223372036854775806 parseit=0, value=9223372036854775806 +buf=9223372036854775807 parseit=0, value=9223372036854775807 +buf=9223372036854775808 parseit=0, value=9223372036854775808 +buf=18446744073709551614 parseit=0, value=18446744073709551614 +buf=18446744073709551615 parseit=0, value=18446744073709551615 +buf=18446744073709551616 parseit=0, value=18446744073709551615 +buf=123 parseit=0, value=123 diff --git a/tests/test_set_value.c b/tests/test_set_value.c index 6cd9563..25124be 100644 --- a/tests/test_set_value.c +++ b/tests/test_set_value.c @@ -15,6 +15,16 @@ int main(int argc, char **argv) assert (json_object_get_int64(tmp)==321321321); json_object_put(tmp); printf("INT64 PASSED\n"); + tmp=json_object_new_uint64(123); + assert (json_object_get_int(tmp)==123); + assert (json_object_get_int64(tmp)==123); + assert (json_object_get_uint64(tmp)==123); + json_object_set_uint64(tmp,(uint64_t)321321321); + assert (json_object_get_uint64(tmp)==321321321); + json_object_set_uint64(tmp,9223372036854775808U); + assert (json_object_get_uint64(tmp)==9223372036854775808U); + json_object_put(tmp); + printf("UINT64 PASSED\n"); tmp=json_object_new_boolean(1); assert (json_object_get_boolean(tmp)==1); json_object_set_boolean(tmp,0); @@ -29,6 +39,12 @@ int main(int argc, char **argv) assert (json_object_get_double(tmp)==34.56); json_object_set_double(tmp,6435.34); assert (json_object_get_double(tmp)==6435.34); + json_object_set_double(tmp,2e21); + assert (json_object_get_int64(tmp)==INT64_MAX); + assert (json_object_get_uint64(tmp)==UINT64_MAX); + json_object_set_double(tmp,-2e21); + assert (json_object_get_int64(tmp)==INT64_MIN); + assert (json_object_get_uint64(tmp)==0); json_object_put(tmp); printf("DOUBLE PASSED\n"); #define SHORT "SHORT" diff --git a/tests/test_set_value.expected b/tests/test_set_value.expected index 4cbd5bc..18dd49e 100644 --- a/tests/test_set_value.expected +++ b/tests/test_set_value.expected @@ -1,5 +1,6 @@ INT PASSED INT64 PASSED +UINT64 PASSED BOOL PASSED DOUBLE PASSED STRING PASSED From c816de212bd43f07b6d78a43e9058cce6ef3655e Mon Sep 17 00:00:00 2001 From: dota17 Date: Wed, 26 Feb 2020 20:54:36 +0800 Subject: [PATCH 2/4] modify the json_object, replace c_int64/c_uint64 with struct{union{int64, uint64},...} --- json_object.c | 152 ++++++++++++++++++++++----------------- json_object.h | 9 ++- json_object_private.h | 9 ++- json_util.c | 1 - json_visit.c | 1 - tests/test_cast.c | 6 +- tests/test_cast.expected | 20 +++--- 7 files changed, 111 insertions(+), 87 deletions(-) diff --git a/json_object.c b/json_object.c index 6bd8517..b8209cc 100644 --- a/json_object.c +++ b/json_object.c @@ -51,7 +51,6 @@ static json_object_to_json_string_fn json_object_object_to_json_string; static json_object_to_json_string_fn json_object_boolean_to_json_string; static json_object_to_json_string_fn json_object_double_to_json_string_default; static json_object_to_json_string_fn json_object_int_to_json_string; -static json_object_to_json_string_fn json_object_uint_to_json_string; static json_object_to_json_string_fn json_object_string_to_json_string; static json_object_to_json_string_fn json_object_array_to_json_string; static json_object_to_json_string_fn _json_object_userdata_to_json_string; @@ -303,9 +302,6 @@ void json_object_set_serializer(json_object *jso, case json_type_int: jso->_to_json_string = &json_object_int_to_json_string; break; - case json_type_uint: - jso->_to_json_string = &json_object_uint_to_json_string; - break; case json_type_object: jso->_to_json_string = &json_object_object_to_json_string; break; @@ -595,9 +591,14 @@ json_bool json_object_get_boolean(const struct json_object *jso) case json_type_boolean: return jso->o.c_boolean; case json_type_int: - return (jso->o.c_int64 != 0); - case json_type_uint: - return (jso->o.c_uint64 != 0); + switch(jso->o.c_int.cint_type) { + case json_object_int_type_int64: + return (jso->o.c_int.cint.c_int64 != 0); + case json_object_int_type_uint64: + return (jso->o.c_int.cint.c_uint64 != 0); + default: + return 0; + } case json_type_double: return (jso->o.c_double != 0); case json_type_string: @@ -624,18 +625,10 @@ static int json_object_int_to_json_string(struct json_object* jso, { /* room for 19 digits, the sign char, and a null term */ char sbuf[21]; - snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int64); - return printbuf_memappend (pb, sbuf, strlen(sbuf)); -} - -static int json_object_uint_to_json_string(struct json_object* jso, - struct printbuf *pb, - int level, - int flags) -{ - /* room for 20 digits, and a null term */ - char sbuf[21]; - snprintf(sbuf, sizeof(sbuf), "%" PRIu64, jso->o.c_uint64); + if (jso->o.c_int.cint_type == json_object_int_type_int64) + snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int.cint.c_int64); + else if (jso->o.c_int.cint_type == json_object_int_type_uint64) + snprintf(sbuf, sizeof(sbuf), "%" PRIu64, jso->o.c_int.cint.c_uint64); return printbuf_memappend (pb, sbuf, strlen(sbuf)); } @@ -645,7 +638,8 @@ struct json_object* json_object_new_int(int32_t i) if (!jso) return NULL; jso->_to_json_string = &json_object_int_to_json_string; - jso->o.c_int64 = i; + jso->o.c_int.cint.c_int64 = i; + jso->o.c_int.cint_type = json_object_int_type_int64; return jso; } @@ -657,7 +651,13 @@ int32_t json_object_get_int(const struct json_object *jso) if(!jso) return 0; o_type = jso->o_type; - cint64 = jso->o.c_int64; + if (jso->o.c_int.cint_type == json_object_int_type_int64) { + cint64 = jso->o.c_int.cint.c_int64; + } else if (jso->o.c_int.cint_type == json_object_int_type_uint64) { + if (jso->o.c_int.cint.c_uint64 >= INT64_MAX) + cint64 = INT64_MAX; + cint64 = (int64_t)jso->o.c_int.cint.c_uint64; + } if (o_type == json_type_string) { @@ -678,10 +678,6 @@ int32_t json_object_get_int(const struct json_object *jso) if (cint64 >= INT32_MAX) return INT32_MAX; return (int32_t) cint64; - case json_type_uint: - if (jso->o.c_uint64 >= INT32_MAX) - return INT32_MAX; - return (int32_t)jso->o.c_uint64; case json_type_double: if (jso->o.c_double <= INT32_MIN) return INT32_MIN; @@ -696,9 +692,9 @@ int32_t json_object_get_int(const struct json_object *jso) } int json_object_set_int(struct json_object *jso,int new_value){ - if (!jso || jso->o_type!=json_type_int) + if (!jso || jso->o_type!=json_type_int || jso->o.c_int.cint_type != json_object_int_type_int64) return 0; - jso->o.c_int64=new_value; + jso->o.c_int.cint.c_int64=new_value; return 1; } @@ -708,17 +704,19 @@ struct json_object* json_object_new_int64(int64_t i) if (!jso) return NULL; jso->_to_json_string = &json_object_int_to_json_string; - jso->o.c_int64 = i; + jso->o.c_int.cint.c_int64 = i; + jso->o.c_int.cint_type = json_object_int_type_int64; return jso; } struct json_object* json_object_new_uint64(uint64_t i) { - struct json_object *jso = json_object_new(json_type_uint); + struct json_object *jso = json_object_new(json_type_int); if (!jso) return NULL; - jso->_to_json_string = &json_object_uint_to_json_string; - jso->o.c_uint64 = i; + jso->_to_json_string = &json_object_int_to_json_string; + jso->o.c_int.cint.c_uint64 = i; + jso->o.c_int.cint_type = json_object_int_type_uint64; return jso; } @@ -731,11 +729,16 @@ int64_t json_object_get_int64(const struct json_object *jso) switch(jso->o_type) { case json_type_int: - return jso->o.c_int64; - case json_type_uint: - if (jso->o.c_uint64 >= INT64_MAX) - return INT64_MAX; - return (int64_t)jso->o.c_uint64; + switch(jso->o.c_int.cint_type) { + case json_object_int_type_int64: + return jso->o.c_int.cint.c_int64; + case json_object_int_type_uint64: + if (jso->o.c_int.cint.c_uint64 >= INT64_MAX) + return INT64_MAX; + return (int64_t)jso->o.c_int.cint.c_uint64; + default: + return 0; + } case json_type_double: // INT64_MAX can't be exactly represented as a double // so cast to tell the compiler it's ok to round up. @@ -764,11 +767,16 @@ uint64_t json_object_get_uint64(const struct json_object *jso) switch(jso->o_type) { case json_type_int: - if (jso->o.c_int64 < 0) + switch(jso->o.c_int.cint_type) { + case json_object_int_type_int64: + if (jso->o.c_int.cint.c_int64 < 0) + return 0; + return (uint64_t)jso->o.c_int.cint.c_int64; + case json_object_int_type_uint64: + return jso->o.c_int.cint.c_uint64; + default: return 0; - return (uint64_t)jso->o.c_int64; - case json_type_uint: - return jso->o.c_uint64; + } case json_type_double: // UINT64_MAX can't be exactly represented as a double // so cast to tell the compiler it's ok to round up. @@ -789,39 +797,39 @@ uint64_t json_object_get_uint64(const struct json_object *jso) } int json_object_set_int64(struct json_object *jso,int64_t new_value){ - if (!jso || jso->o_type!=json_type_int) + if (!jso || jso->o_type!=json_type_int || jso->o.c_int.cint_type != json_object_int_type_int64) return 0; - jso->o.c_int64=new_value; + jso->o.c_int.cint.c_int64=new_value; return 1; } int json_object_set_uint64(struct json_object *jso,uint64_t new_value){ - if (!jso || jso->o_type!=json_type_uint) + if (!jso || jso->o_type!=json_type_int || jso->o.c_int.cint_type != json_object_int_type_uint64) return 0; - jso->o.c_uint64=new_value; + jso->o.c_int.cint.c_uint64=new_value; return 1; } int json_object_int_inc(struct json_object *jso, int64_t val) { - if (!jso || jso->o_type != json_type_int) + if (!jso || jso->o_type != json_type_int || jso->o.c_int.cint_type != json_object_int_type_int64) return 0; - if (val > 0 && jso->o.c_int64 > INT64_MAX - val) { - jso->o.c_int64 = INT64_MAX; - } else if (val < 0 && jso->o.c_int64 < INT64_MIN - val) { - jso->o.c_int64 = INT64_MIN; + if (val > 0 && jso->o.c_int.cint.c_int64 > INT64_MAX - val) { + jso->o.c_int.cint.c_int64 = INT64_MAX; + } else if (val < 0 && jso->o.c_int.cint.c_int64 < INT64_MIN - val) { + jso->o.c_int.cint.c_int64 = INT64_MIN; } else { - jso->o.c_int64 += val; + jso->o.c_int.cint.c_int64 += val; } return 1; } int json_object_uint_inc(struct json_object *jso, uint64_t val) { - if (!jso || jso->o_type != json_type_uint) + if (!jso || jso->o_type != json_type_int || jso->o.c_int.cint_type != json_object_int_type_uint64) return 0; - if (jso->o.c_uint64 > UINT64_MAX - val) { - jso->o.c_uint64 = UINT64_MAX; + if (jso->o.c_int.cint.c_uint64 > UINT64_MAX - val) { + jso->o.c_int.cint.c_uint64 = UINT64_MAX; } else { - jso->o.c_uint64 += val; + jso->o.c_int.cint.c_uint64 += val; } return 1; } @@ -1047,9 +1055,14 @@ double json_object_get_double(const struct json_object *jso) case json_type_double: return jso->o.c_double; case json_type_int: - return jso->o.c_int64; - case json_type_uint: - return jso->o.c_uint64; + switch(jso->o.c_int.cint_type) { + case json_object_int_type_int64: + return jso->o.c_int.cint.c_int64; + case json_object_int_type_uint64: + return jso->o.c_int.cint.c_uint64; + default: + return 0.0; + } case json_type_boolean: return jso->o.c_boolean; case json_type_string: @@ -1428,10 +1441,14 @@ int json_object_equal(struct json_object* jso1, struct json_object* jso2) return (jso1->o.c_double == jso2->o.c_double); case json_type_int: - return (jso1->o.c_int64 == jso2->o.c_int64); - - case json_type_uint: - return (jso1->o.c_uint64 == jso2->o.c_uint64); + if ((jso1->o.c_int.cint_type == json_object_int_type_int64) + && (jso2->o.c_int.cint_type == json_object_int_type_int64)) + return (jso1->o.c_int.cint.c_int64 == jso2->o.c_int.cint.c_int64); + else if ((jso1->o.c_int.cint_type == json_object_int_type_uint64) + && (jso2->o.c_int.cint_type == json_object_int_type_uint64)) + return (jso1->o.c_int.cint.c_uint64 == jso2->o.c_int.cint.c_uint64); + else + return 0; case json_type_string: return (jso1->o.c_string.len == jso2->o.c_string.len && @@ -1493,11 +1510,14 @@ int json_c_shallow_copy_default(json_object *src, json_object *parent, const cha break; case json_type_int: - *dst = json_object_new_int64(src->o.c_int64); - break; - - case json_type_uint: - *dst = json_object_new_uint64(src->o.c_uint64); + switch(src->o.c_int.cint_type) { + case json_object_int_type_int64: + *dst = json_object_new_int64(src->o.c_int.cint.c_int64); + break; + case json_object_int_type_uint64: + *dst = json_object_new_uint64(src->o.c_int.cint.c_uint64); + break; + } break; case json_type_string: diff --git a/json_object.h b/json_object.h index 4e13ec1..2fa9b3b 100644 --- a/json_object.h +++ b/json_object.h @@ -176,12 +176,17 @@ typedef enum json_type { json_type_boolean, json_type_double, json_type_int, - json_type_uint, json_type_object, json_type_array, json_type_string } json_type; +/* json object int type, support extension*/ +typedef enum json_object_int_type { + json_object_int_type_int64, + json_object_int_type_uint64 +}json_object_int_type; + /* reference counting functions */ /** @@ -211,7 +216,6 @@ JSON_EXPORT int json_object_put(struct json_object *obj); json_type_boolean, json_type_double, json_type_int, - json_type_uint, json_type_object, json_type_array, json_type_string @@ -228,7 +232,6 @@ JSON_EXPORT int json_object_is_type(const struct json_object *obj, enum json_typ json_type_boolean, json_type_double, json_type_int, - json_type_uint, json_type_object, json_type_array, json_type_string diff --git a/json_object_private.h b/json_object_private.h index f7109b7..cf7867e 100644 --- a/json_object_private.h +++ b/json_object_private.h @@ -34,8 +34,13 @@ struct json_object union data { json_bool c_boolean; double c_double; - int64_t c_int64; - uint64_t c_uint64; + struct { + union { + int64_t c_int64; + uint64_t c_uint64; + } cint; + enum json_object_int_type cint_type; + } c_int; struct lh_table *c_object; struct array_list *c_array; struct { diff --git a/json_util.c b/json_util.c index 8902d31..1c1fa46 100644 --- a/json_util.c +++ b/json_util.c @@ -266,7 +266,6 @@ static const char* json_type_name[] = { "boolean", "double", "int", - "uint", "object", "array", "string", diff --git a/json_visit.c b/json_visit.c index 4419614..1126ff8 100644 --- a/json_visit.c +++ b/json_visit.c @@ -57,7 +57,6 @@ static int _json_c_visit(json_object *jso, json_object *parent_jso, case json_type_boolean: case json_type_double: case json_type_int: - case json_type_uint: case json_type_string: // we already called userfunc above, move on to the next object return JSON_C_VISIT_RETURN_CONTINUE; diff --git a/tests/test_cast.c b/tests/test_cast.c index 3daf5e1..d09aa7f 100644 --- a/tests/test_cast.c +++ b/tests/test_cast.c @@ -91,12 +91,11 @@ static void getit(struct json_object *new_obj, const char *field) static void checktype_header() { - printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s,%s\n", + printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s\n", json_type_to_name(json_type_null), json_type_to_name(json_type_boolean), json_type_to_name(json_type_double), json_type_to_name(json_type_int), - json_type_to_name(json_type_uint), json_type_to_name(json_type_object), json_type_to_name(json_type_array), json_type_to_name(json_type_string)); @@ -107,13 +106,12 @@ static void checktype(struct json_object *new_obj, const char *field) if (field && !json_object_object_get_ex(new_obj, field, &o)) printf("Field %s does not exist\n", field); - printf("new_obj%s%-18s: %d,%d,%d,%d,%d,%d,%d,%d\n", + printf("new_obj%s%-18s: %d,%d,%d,%d,%d,%d,%d\n", field ? "." : " ", field ? field : "", json_object_is_type(o, json_type_null), json_object_is_type(o, json_type_boolean), json_object_is_type(o, json_type_double), json_object_is_type(o, json_type_int), - json_object_is_type(o, json_type_uint), json_object_is_type(o, json_type_object), json_object_is_type(o, json_type_array), json_object_is_type(o, json_type_string)); diff --git a/tests/test_cast.expected b/tests/test_cast.expected index 92ea886..347d540 100644 --- a/tests/test_cast.expected +++ b/tests/test_cast.expected @@ -59,13 +59,13 @@ new_obj.a_null json_object_get_boolean()=0 new_obj.a_null json_object_get_double()=0.000000 ================================ -json_object_is_type: null,boolean,double,int,uint,object,array,string -new_obj : 0,0,0,0,0,1,0,0 -new_obj.string_of_digits : 0,0,0,0,0,0,0,1 -new_obj.regular_number : 0,0,0,1,0,0,0,0 -new_obj.decimal_number : 0,0,1,0,0,0,0,0 -new_obj.boolean_true : 0,1,0,0,0,0,0,0 -new_obj.boolean_false : 0,1,0,0,0,0,0,0 -new_obj.int64_number : 0,0,0,1,0,0,0,0 -new_obj.negative_number : 0,0,0,1,0,0,0,0 -new_obj.a_null : 1,0,0,0,0,0,0,0 +json_object_is_type: null,boolean,double,int,object,array,string +new_obj : 0,0,0,0,1,0,0 +new_obj.string_of_digits : 0,0,0,0,0,0,1 +new_obj.regular_number : 0,0,0,1,0,0,0 +new_obj.decimal_number : 0,0,1,0,0,0,0 +new_obj.boolean_true : 0,1,0,0,0,0,0 +new_obj.boolean_false : 0,1,0,0,0,0,0 +new_obj.int64_number : 0,0,0,1,0,0,0 +new_obj.negative_number : 0,0,0,1,0,0,0 +new_obj.a_null : 1,0,0,0,0,0,0 From 9532f94fa4a4a8d3fb5dbbd3ed797a2622de536b Mon Sep 17 00:00:00 2001 From: dota17 Date: Thu, 27 Feb 2020 15:01:06 +0800 Subject: [PATCH 3/4] modify partial functions and testcase, in order to support automatic conversion for int64/uint64 --- json_object.c | 112 +++++++++++++++++++++++++----------- json_object.h | 6 -- json_object_private.h | 6 ++ tests/test_compare.c | 44 ++++++++++++++ tests/test_compare.expected | 8 +++ tests/test_int_add.c | 34 ++++++++++- tests/test_int_add.expected | 1 + 7 files changed, 169 insertions(+), 42 deletions(-) diff --git a/json_object.c b/json_object.c index b8209cc..bd820d2 100644 --- a/json_object.c +++ b/json_object.c @@ -594,10 +594,8 @@ json_bool json_object_get_boolean(const struct json_object *jso) switch(jso->o.c_int.cint_type) { case json_object_int_type_int64: return (jso->o.c_int.cint.c_int64 != 0); - case json_object_int_type_uint64: - return (jso->o.c_int.cint.c_uint64 != 0); default: - return 0; + return (jso->o.c_int.cint.c_uint64 != 0); } case json_type_double: return (jso->o.c_double != 0); @@ -629,6 +627,8 @@ static int json_object_int_to_json_string(struct json_object* jso, snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int.cint.c_int64); else if (jso->o.c_int.cint_type == json_object_int_type_uint64) snprintf(sbuf, sizeof(sbuf), "%" PRIu64, jso->o.c_int.cint.c_uint64); + else + return 0; return printbuf_memappend (pb, sbuf, strlen(sbuf)); } @@ -692,10 +692,7 @@ int32_t json_object_get_int(const struct json_object *jso) } int json_object_set_int(struct json_object *jso,int new_value){ - if (!jso || jso->o_type!=json_type_int || jso->o.c_int.cint_type != json_object_int_type_int64) - return 0; - jso->o.c_int.cint.c_int64=new_value; - return 1; + return json_object_set_int64(jso,(int64_t)new_value); } struct json_object* json_object_new_int64(int64_t i) @@ -797,41 +794,77 @@ uint64_t json_object_get_uint64(const struct json_object *jso) } int json_object_set_int64(struct json_object *jso,int64_t new_value){ - if (!jso || jso->o_type!=json_type_int || jso->o.c_int.cint_type != json_object_int_type_int64) + if (!jso || jso->o_type!=json_type_int) return 0; jso->o.c_int.cint.c_int64=new_value; + jso->o.c_int.cint_type = json_object_int_type_int64; return 1; } int json_object_set_uint64(struct json_object *jso,uint64_t new_value){ - if (!jso || jso->o_type!=json_type_int || jso->o.c_int.cint_type != json_object_int_type_uint64) + if (!jso || jso->o_type!=json_type_int) return 0; jso->o.c_int.cint.c_uint64=new_value; + jso->o.c_int.cint_type = json_object_int_type_uint64; return 1; } int json_object_int_inc(struct json_object *jso, int64_t val) { - if (!jso || jso->o_type != json_type_int || jso->o.c_int.cint_type != json_object_int_type_int64) + if (!jso || jso->o_type != json_type_int) + return 0; + switch(jso->o.c_int.cint_type) { + case json_object_int_type_int64: + if (val > 0 && jso->o.c_int.cint.c_int64 > INT64_MAX - val) { + jso->o.c_int.cint.c_uint64 = (uint64_t)jso->o.c_int.cint.c_int64 + (uint64_t)val; + jso->o.c_int.cint_type = json_object_int_type_uint64; + } else if (val < 0 && jso->o.c_int.cint.c_int64 < INT64_MIN - val) { + jso->o.c_int.cint.c_int64 = INT64_MIN; + } else { + jso->o.c_int.cint.c_int64 += val; + } + return 1; + case json_object_int_type_uint64: + if (val > 0 && jso->o.c_int.cint.c_uint64 > UINT64_MAX - (uint64_t)val) { + jso->o.c_int.cint.c_uint64 = UINT64_MAX; + } else if (val < 0 && jso->o.c_int.cint.c_uint64 < (uint64_t)(-val)) { + jso->o.c_int.cint.c_int64 = (int64_t)jso->o.c_int.cint.c_uint64 + val; + jso->o.c_int.cint_type = json_object_int_type_int64; + } else if (val < 0 && jso->o.c_int.cint.c_uint64 >= (uint64_t)(-val)) { + jso->o.c_int.cint.c_uint64 = jso->o.c_int.cint.c_uint64 - (uint64_t)(-val); + } else { + jso->o.c_int.cint.c_uint64 += val; + } + return 1; + default: return 0; - if (val > 0 && jso->o.c_int.cint.c_int64 > INT64_MAX - val) { - jso->o.c_int.cint.c_int64 = INT64_MAX; - } else if (val < 0 && jso->o.c_int.cint.c_int64 < INT64_MIN - val) { - jso->o.c_int.cint.c_int64 = INT64_MIN; - } else { - jso->o.c_int.cint.c_int64 += val; } - return 1; } int json_object_uint_inc(struct json_object *jso, uint64_t val) { - if (!jso || jso->o_type != json_type_int || jso->o.c_int.cint_type != json_object_int_type_uint64) + if (!jso || jso->o_type != json_type_int) + return 0; + switch(jso->o.c_int.cint_type) { + case json_object_int_type_int64: + if ((uint64_t)jso->o.c_int.cint.c_uint64 + val> UINT64_MAX) { + jso->o.c_int.cint.c_uint64 = UINT64_MAX; + jso->o.c_int.cint_type = json_object_int_type_uint64; + } else if ((uint64_t)jso->o.c_int.cint.c_uint64 + val < INT64_MAX) { + jso->o.c_int.cint.c_int64 += (int64_t)val; + } else { + jso->o.c_int.cint.c_uint64 =(uint64_t) jso->o.c_int.cint.c_uint64 + val; + jso->o.c_int.cint_type = json_object_int_type_uint64; + } + return 1; + case json_object_int_type_uint64: + if (jso->o.c_int.cint.c_uint64 > UINT64_MAX - val) { + jso->o.c_int.cint.c_uint64 = UINT64_MAX; + } else { + jso->o.c_int.cint.c_uint64 += val; + } + return 1; + default: return 0; - if (jso->o.c_int.cint.c_uint64 > UINT64_MAX - val) { - jso->o.c_int.cint.c_uint64 = UINT64_MAX; - } else { - jso->o.c_int.cint.c_uint64 += val; } - return 1; } /* json_object_double */ @@ -1056,12 +1089,12 @@ double json_object_get_double(const struct json_object *jso) return jso->o.c_double; case json_type_int: switch(jso->o.c_int.cint_type) { - case json_object_int_type_int64: + case json_object_int_type_int64: return jso->o.c_int.cint.c_int64; case json_object_int_type_uint64: return jso->o.c_int.cint.c_uint64; - default: - return 0.0; + default: + return 0.0; } case json_type_boolean: return jso->o.c_boolean; @@ -1441,14 +1474,27 @@ int json_object_equal(struct json_object* jso1, struct json_object* jso2) return (jso1->o.c_double == jso2->o.c_double); case json_type_int: - if ((jso1->o.c_int.cint_type == json_object_int_type_int64) - && (jso2->o.c_int.cint_type == json_object_int_type_int64)) - return (jso1->o.c_int.cint.c_int64 == jso2->o.c_int.cint.c_int64); - else if ((jso1->o.c_int.cint_type == json_object_int_type_uint64) - && (jso2->o.c_int.cint_type == json_object_int_type_uint64)) - return (jso1->o.c_int.cint.c_uint64 == jso2->o.c_int.cint.c_uint64); - else + if (jso1->o.c_int.cint_type == json_object_int_type_int64) { + if (jso2->o.c_int.cint_type == json_object_int_type_int64) + return (jso1->o.c_int.cint.c_int64 == jso2->o.c_int.cint.c_int64); + if (jso2->o.c_int.cint_type == json_object_int_type_uint64) { + if (jso1->o.c_int.cint.c_int64 < 0) + return 0; + return ((uint64_t)jso1->o.c_int.cint.c_int64 == jso2->o.c_int.cint.c_uint64); + } return 0; + } + if (jso1->o.c_int.cint_type == json_object_int_type_uint64) { + if (jso2->o.c_int.cint_type == json_object_int_type_uint64) + return (jso1->o.c_int.cint.c_uint64 == jso2->o.c_int.cint.c_uint64); + if (jso2->o.c_int.cint_type == json_object_int_type_int64){ + if (jso2->o.c_int.cint.c_int64 < 0) + return 0; + return (jso1->o.c_int.cint.c_uint64 == (uint64_t)jso2->o.c_int.cint.c_int64); + } + return 0; + } + return 0; case json_type_string: return (jso1->o.c_string.len == jso2->o.c_string.len && diff --git a/json_object.h b/json_object.h index 2fa9b3b..297a2e8 100644 --- a/json_object.h +++ b/json_object.h @@ -181,12 +181,6 @@ typedef enum json_type { json_type_string } json_type; -/* json object int type, support extension*/ -typedef enum json_object_int_type { - json_object_int_type_int64, - json_object_int_type_uint64 -}json_object_int_type; - /* reference counting functions */ /** diff --git a/json_object_private.h b/json_object_private.h index cf7867e..3bda3df 100644 --- a/json_object_private.h +++ b/json_object_private.h @@ -24,6 +24,12 @@ extern "C" { typedef void (json_object_private_delete_fn)(struct json_object *o); +/* json object int type, support extension*/ +typedef enum json_object_int_type { + json_object_int_type_int64, + json_object_int_type_uint64 +}json_object_int_type; + struct json_object { enum json_type o_type; diff --git a/tests/test_compare.c b/tests/test_compare.c index 13ad3ea..cbb7ccc 100644 --- a/tests/test_compare.c +++ b/tests/test_compare.c @@ -15,9 +15,11 @@ int main() struct json_object *int1 = json_object_new_int(0); struct json_object *int2 = json_object_new_int(1); struct json_object *int3 = json_object_new_int(1); + struct json_object *int4 = json_object_new_int(-1); struct json_object *uint1 = json_object_new_uint64(0); struct json_object *uint2 = json_object_new_uint64(1); struct json_object *uint3 = json_object_new_uint64(1); + struct json_object *uint4 = json_object_new_uint64((uint64_t)INT64_MAX + 100); if (!json_object_equal(int1, int2)) printf("JSON integer comparison is correct\n"); @@ -49,12 +51,54 @@ int main() else printf("JSON same usigned integer comparison failed\n"); + if (json_object_equal(int2, uint2)) + printf("JSON integer & usigned integer comparison is correct\n"); + else + printf("JSON integer & usigned integer comparison failed\n"); + + if (!json_object_equal(int2, uint4)) + printf("JSON integer & usigned integer comparison is correct\n"); + else + printf("JSON integer & usigned integer comparison failed\n"); + + if (!json_object_equal(int4, uint2)) + printf("JSON integer & usigned integer comparison is correct\n"); + else + printf("JSON integer & usigned integer comparison failed\n"); + + if (!json_object_equal(int4, uint4)) + printf("JSON integer & usigned integer comparison is correct\n"); + else + printf("JSON integer & usigned integer comparison failed\n"); + + if (json_object_equal(uint2, int2)) + printf("JSON usigned integer & integer comparison is correct\n"); + else + printf("JSON usigned integer & integer comparison failed\n"); + + if (!json_object_equal(uint2, int4)) + printf("JSON usigned integer & integer comparison is correct\n"); + else + printf("JSON usigned integer & integer comparison failed\n"); + + if (!json_object_equal(uint4, int2)) + printf("JSON usigned integer & integer comparison is correct\n"); + else + printf("JSON usigned integer & integer comparison failed\n"); + + if (!json_object_equal(uint4, int4)) + printf("JSON usigned integer & integer comparison is correct\n"); + else + printf("JSON usigned integer & integer comparison failed\n"); + json_object_put(int1); json_object_put(int2); json_object_put(int3); + json_object_put(int4); json_object_put(uint1); json_object_put(uint2); json_object_put(uint3); + json_object_put(uint4); /* string tests */ struct json_object *str1 = json_object_new_string("TESTSTRING"); diff --git a/tests/test_compare.expected b/tests/test_compare.expected index a183aab..a08fab9 100644 --- a/tests/test_compare.expected +++ b/tests/test_compare.expected @@ -4,6 +4,14 @@ JSON same integer comparison is correct JSON usigned integer comparison is correct JSON same usigned object comparison is correct JSON same usigned integer comparison is correct +JSON integer & usigned integer comparison is correct +JSON integer & usigned integer comparison is correct +JSON integer & usigned integer comparison is correct +JSON integer & usigned integer comparison is correct +JSON usigned integer & integer comparison is correct +JSON usigned integer & integer comparison is correct +JSON usigned integer & integer comparison is correct +JSON usigned integer & integer comparison is correct Comparing equal strings is correct Comparing different strings is correct Comparing equal doubles is correct diff --git a/tests/test_int_add.c b/tests/test_int_add.c index 8b02e79..bd76ac5 100644 --- a/tests/test_int_add.c +++ b/tests/test_int_add.c @@ -25,13 +25,27 @@ int main(int argc, char **argv) tmp = json_object_new_int64(321321321); json_object_int_inc(tmp, 321321321); assert(json_object_get_int(tmp) == 642642642); + json_object_uint_inc(tmp, 321321321U); + assert(json_object_get_int(tmp) == 963963963); json_object_put(tmp); printf("INT64 ADD PASSED\n"); tmp = json_object_new_int64(INT64_MAX); json_object_int_inc(tmp, 100); assert(json_object_get_int64(tmp) == INT64_MAX); + assert(json_object_get_uint64(tmp) == (uint64_t)INT64_MAX + 100U); json_object_int_inc(tmp, -100); - assert(json_object_get_int64(tmp) != INT64_MAX); + assert(json_object_get_int64(tmp) == INT64_MAX); + assert(json_object_get_uint64(tmp) == (uint64_t)INT64_MAX); + json_object_put(tmp); + tmp = json_object_new_int64(100); + json_object_uint_inc(tmp, 100); + assert(json_object_get_int64(tmp) == 200); + json_object_uint_inc(tmp, (uint64_t)INT64_MAX); + assert(json_object_get_int64(tmp) == INT64_MAX); + assert(json_object_get_uint64(tmp) == (uint64_t)INT64_MAX+200); + json_object_uint_inc(tmp, UINT64_MAX); + assert(json_object_get_int64(tmp) == INT64_MAX); + assert(json_object_get_uint64(tmp) == UINT64_MAX); json_object_put(tmp); printf("INT64 ADD OVERFLOW PASSED\n"); tmp = json_object_new_int64(INT64_MIN); @@ -45,14 +59,28 @@ int main(int argc, char **argv) json_object_uint_inc(tmp, 321321321); assert(json_object_get_uint64(tmp) == 642642642); json_object_put(tmp); + // uint64 + negative int64--> negative int64 + tmp = json_object_new_uint64(400); + json_object_int_inc(tmp, -200); + assert(json_object_get_int64(tmp) == 200); + assert(json_object_get_uint64(tmp) == 200); + json_object_put(tmp); printf("UINT64 ADD PASSED\n"); tmp = json_object_new_uint64(UINT64_MAX); json_object_uint_inc(tmp, 100); assert(json_object_get_uint64(tmp) == UINT64_MAX); - json_object_uint_inc(tmp, -100); - assert(json_object_get_uint64(tmp) != INT64_MAX); + json_object_put(tmp); + tmp = json_object_new_uint64(UINT64_MAX - 100); + json_object_uint_inc(tmp, 200); + assert(json_object_get_uint64(tmp) == UINT64_MAX); json_object_put(tmp); printf("UINT64 ADD OVERFLOW PASSED\n"); + tmp = json_object_new_uint64(100); + json_object_int_inc(tmp, -200); + assert(json_object_get_int64(tmp) == -100); + assert(json_object_get_uint64(tmp) == 0); + json_object_put(tmp); + printf("UINT64 ADD UNDERFLOW PASSED\n"); printf("PASSED\n"); return 0; diff --git a/tests/test_int_add.expected b/tests/test_int_add.expected index 144233a..f9348d4 100644 --- a/tests/test_int_add.expected +++ b/tests/test_int_add.expected @@ -6,4 +6,5 @@ INT64 ADD OVERFLOW PASSED INT64 ADD UNDERFLOW PASSED UINT64 ADD PASSED UINT64 ADD OVERFLOW PASSED +UINT64 ADD UNDERFLOW PASSED PASSED From 6359b798479d379a3202e02c6a938d9b40c0d856 Mon Sep 17 00:00:00 2001 From: dota17 Date: Fri, 28 Feb 2020 11:18:48 +0800 Subject: [PATCH 4/4] update json_object.c and testcase, delete json_object_uint_inc() --- json_object.c | 67 +++++++++++-------------------------- json_object.h | 14 -------- tests/test_int_add.c | 25 -------------- tests/test_int_add.expected | 1 - 4 files changed, 19 insertions(+), 88 deletions(-) diff --git a/json_object.c b/json_object.c index bd820d2..57d4093 100644 --- a/json_object.c +++ b/json_object.c @@ -594,8 +594,10 @@ json_bool json_object_get_boolean(const struct json_object *jso) switch(jso->o.c_int.cint_type) { case json_object_int_type_int64: return (jso->o.c_int.cint.c_int64 != 0); - default: + case json_object_int_type_uint64: return (jso->o.c_int.cint.c_uint64 != 0); + default: + assert(0); } case json_type_double: return (jso->o.c_double != 0); @@ -624,11 +626,9 @@ static int json_object_int_to_json_string(struct json_object* jso, /* room for 19 digits, the sign char, and a null term */ char sbuf[21]; if (jso->o.c_int.cint_type == json_object_int_type_int64) - snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int.cint.c_int64); - else if (jso->o.c_int.cint_type == json_object_int_type_uint64) - snprintf(sbuf, sizeof(sbuf), "%" PRIu64, jso->o.c_int.cint.c_uint64); + snprintf(sbuf, sizeof(sbuf), "%" PRId64, jso->o.c_int.cint.c_int64); else - return 0; + snprintf(sbuf, sizeof(sbuf), "%" PRIu64, jso->o.c_int.cint.c_uint64); return printbuf_memappend (pb, sbuf, strlen(sbuf)); } @@ -653,7 +653,7 @@ int32_t json_object_get_int(const struct json_object *jso) o_type = jso->o_type; if (jso->o.c_int.cint_type == json_object_int_type_int64) { cint64 = jso->o.c_int.cint.c_int64; - } else if (jso->o.c_int.cint_type == json_object_int_type_uint64) { + } else { if (jso->o.c_int.cint.c_uint64 >= INT64_MAX) cint64 = INT64_MAX; cint64 = (int64_t)jso->o.c_int.cint.c_uint64; @@ -734,7 +734,7 @@ int64_t json_object_get_int64(const struct json_object *jso) return INT64_MAX; return (int64_t)jso->o.c_int.cint.c_uint64; default: - return 0; + assert(0); } case json_type_double: // INT64_MAX can't be exactly represented as a double @@ -772,7 +772,7 @@ uint64_t json_object_get_uint64(const struct json_object *jso) case json_object_int_type_uint64: return jso->o.c_int.cint.c_uint64; default: - return 0; + assert(0); } case json_type_double: // UINT64_MAX can't be exactly represented as a double @@ -830,40 +830,13 @@ int json_object_int_inc(struct json_object *jso, int64_t val) { jso->o.c_int.cint.c_int64 = (int64_t)jso->o.c_int.cint.c_uint64 + val; jso->o.c_int.cint_type = json_object_int_type_int64; } else if (val < 0 && jso->o.c_int.cint.c_uint64 >= (uint64_t)(-val)) { - jso->o.c_int.cint.c_uint64 = jso->o.c_int.cint.c_uint64 - (uint64_t)(-val); + jso->o.c_int.cint.c_uint64 -= (uint64_t)(-val); } else { jso->o.c_int.cint.c_uint64 += val; } return 1; default: - return 0; - } -} - -int json_object_uint_inc(struct json_object *jso, uint64_t val) { - if (!jso || jso->o_type != json_type_int) - return 0; - switch(jso->o.c_int.cint_type) { - case json_object_int_type_int64: - if ((uint64_t)jso->o.c_int.cint.c_uint64 + val> UINT64_MAX) { - jso->o.c_int.cint.c_uint64 = UINT64_MAX; - jso->o.c_int.cint_type = json_object_int_type_uint64; - } else if ((uint64_t)jso->o.c_int.cint.c_uint64 + val < INT64_MAX) { - jso->o.c_int.cint.c_int64 += (int64_t)val; - } else { - jso->o.c_int.cint.c_uint64 =(uint64_t) jso->o.c_int.cint.c_uint64 + val; - jso->o.c_int.cint_type = json_object_int_type_uint64; - } - return 1; - case json_object_int_type_uint64: - if (jso->o.c_int.cint.c_uint64 > UINT64_MAX - val) { - jso->o.c_int.cint.c_uint64 = UINT64_MAX; - } else { - jso->o.c_int.cint.c_uint64 += val; - } - return 1; - default: - return 0; + assert(0); } } @@ -1094,8 +1067,8 @@ double json_object_get_double(const struct json_object *jso) case json_object_int_type_uint64: return jso->o.c_int.cint.c_uint64; default: - return 0.0; - } + assert(0); + } case json_type_boolean: return jso->o.c_boolean; case json_type_string: @@ -1475,26 +1448,22 @@ int json_object_equal(struct json_object* jso1, struct json_object* jso2) case json_type_int: if (jso1->o.c_int.cint_type == json_object_int_type_int64) { - if (jso2->o.c_int.cint_type == json_object_int_type_int64) + if (jso2->o.c_int.cint_type == json_object_int_type_int64) { return (jso1->o.c_int.cint.c_int64 == jso2->o.c_int.cint.c_int64); - if (jso2->o.c_int.cint_type == json_object_int_type_uint64) { + } else { if (jso1->o.c_int.cint.c_int64 < 0) return 0; return ((uint64_t)jso1->o.c_int.cint.c_int64 == jso2->o.c_int.cint.c_uint64); } - return 0; - } - if (jso1->o.c_int.cint_type == json_object_int_type_uint64) { - if (jso2->o.c_int.cint_type == json_object_int_type_uint64) + } else { + if (jso2->o.c_int.cint_type == json_object_int_type_uint64) { return (jso1->o.c_int.cint.c_uint64 == jso2->o.c_int.cint.c_uint64); - if (jso2->o.c_int.cint_type == json_object_int_type_int64){ + } else { if (jso2->o.c_int.cint.c_int64 < 0) return 0; return (jso1->o.c_int.cint.c_uint64 == (uint64_t)jso2->o.c_int.cint.c_int64); } - return 0; } - return 0; case json_type_string: return (jso1->o.c_string.len == jso2->o.c_string.len && @@ -1563,6 +1532,8 @@ int json_c_shallow_copy_default(json_object *src, json_object *parent, const cha case json_object_int_type_uint64: *dst = json_object_new_uint64(src->o.c_int.cint.c_uint64); break; + default: + assert(0); } break; diff --git a/json_object.h b/json_object.h index 297a2e8..0b8a302 100644 --- a/json_object.h +++ b/json_object.h @@ -752,20 +752,6 @@ JSON_EXPORT int json_object_set_int(struct json_object *obj,int new_value); */ JSON_EXPORT int json_object_int_inc(struct json_object *obj, int64_t val); -/** Increment a json_type_uint object by the given amount, which may be negative. - * - * If the type of obj is not json_type_uint then 0 is returned with no further - * action taken. - * If the addition would result in a overflow, the object value - * is set to UINT64_MAX. - * Neither overflow nor underflow affect the return value. - * - * @param obj the json_object instance - * @param val the value to add - * @returns 1 if the increment succeded, 0 otherwise - */ -JSON_EXPORT int json_object_uint_inc(struct json_object *obj, uint64_t val); - /** Get the int value of a json_object * * The type is coerced to a int64 if the passed object is not a int64. diff --git a/tests/test_int_add.c b/tests/test_int_add.c index bd76ac5..82f9d99 100644 --- a/tests/test_int_add.c +++ b/tests/test_int_add.c @@ -25,8 +25,6 @@ int main(int argc, char **argv) tmp = json_object_new_int64(321321321); json_object_int_inc(tmp, 321321321); assert(json_object_get_int(tmp) == 642642642); - json_object_uint_inc(tmp, 321321321U); - assert(json_object_get_int(tmp) == 963963963); json_object_put(tmp); printf("INT64 ADD PASSED\n"); tmp = json_object_new_int64(INT64_MAX); @@ -37,16 +35,6 @@ int main(int argc, char **argv) assert(json_object_get_int64(tmp) == INT64_MAX); assert(json_object_get_uint64(tmp) == (uint64_t)INT64_MAX); json_object_put(tmp); - tmp = json_object_new_int64(100); - json_object_uint_inc(tmp, 100); - assert(json_object_get_int64(tmp) == 200); - json_object_uint_inc(tmp, (uint64_t)INT64_MAX); - assert(json_object_get_int64(tmp) == INT64_MAX); - assert(json_object_get_uint64(tmp) == (uint64_t)INT64_MAX+200); - json_object_uint_inc(tmp, UINT64_MAX); - assert(json_object_get_int64(tmp) == INT64_MAX); - assert(json_object_get_uint64(tmp) == UINT64_MAX); - json_object_put(tmp); printf("INT64 ADD OVERFLOW PASSED\n"); tmp = json_object_new_int64(INT64_MIN); json_object_int_inc(tmp, -100); @@ -55,10 +43,6 @@ int main(int argc, char **argv) assert(json_object_get_int64(tmp) != INT64_MIN); json_object_put(tmp); printf("INT64 ADD UNDERFLOW PASSED\n"); - tmp = json_object_new_uint64(321321321); - json_object_uint_inc(tmp, 321321321); - assert(json_object_get_uint64(tmp) == 642642642); - json_object_put(tmp); // uint64 + negative int64--> negative int64 tmp = json_object_new_uint64(400); json_object_int_inc(tmp, -200); @@ -66,15 +50,6 @@ int main(int argc, char **argv) assert(json_object_get_uint64(tmp) == 200); json_object_put(tmp); printf("UINT64 ADD PASSED\n"); - tmp = json_object_new_uint64(UINT64_MAX); - json_object_uint_inc(tmp, 100); - assert(json_object_get_uint64(tmp) == UINT64_MAX); - json_object_put(tmp); - tmp = json_object_new_uint64(UINT64_MAX - 100); - json_object_uint_inc(tmp, 200); - assert(json_object_get_uint64(tmp) == UINT64_MAX); - json_object_put(tmp); - printf("UINT64 ADD OVERFLOW PASSED\n"); tmp = json_object_new_uint64(100); json_object_int_inc(tmp, -200); assert(json_object_get_int64(tmp) == -100); diff --git a/tests/test_int_add.expected b/tests/test_int_add.expected index f9348d4..b2cbdb3 100644 --- a/tests/test_int_add.expected +++ b/tests/test_int_add.expected @@ -5,6 +5,5 @@ INT64 ADD PASSED INT64 ADD OVERFLOW PASSED INT64 ADD UNDERFLOW PASSED UINT64 ADD PASSED -UINT64 ADD OVERFLOW PASSED UINT64 ADD UNDERFLOW PASSED PASSED