Skip to content

Commit 3c3b592

Browse files
committed
add uint64 data to json-c
1 parent 518f337 commit 3c3b592

24 files changed

+430
-36
lines changed

CMakeLists.txt

+11
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ endif()
142142

143143
if (MSVC)
144144
check_symbol_exists(strtoll "stdlib.h" HAVE_STRTOLL)
145+
check_symbol_exists(strtoull "stdlib.h" HAVE_STRTOULL)
145146

146147
set(json_c_strtoll "strtoll")
147148
if (NOT HAVE_STRTOLL)
@@ -153,6 +154,16 @@ if (MSVC)
153154
# could do the same for strtoull, if needed
154155
endif()
155156
endif()
157+
158+
set(json_c_strtoull "strtoull")
159+
if (NOT HAVE_STRTOULL)
160+
# Use _strtoui64 if strtoull is not available.
161+
check_symbol_exists(_strtoui64 "stdlib.h" __have_strtoui64)
162+
if (__have_strtoui64)
163+
set(HAVE_STRTOULL 1)
164+
set(json_c_strtoull "_strtoui64")
165+
endif()
166+
endif()
156167
endif()
157168

158169

cmake/config.h.in

+2
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@
137137

138138
#cmakedefine HAVE_STRTOLL
139139
#cmakedefine strtoll @json_c_strtoll@
140+
#cmakedefine HAVE_STRTOULL
141+
#cmakedefine strtoull @json_c_strtoull@
140142

141143
/* Have __thread */
142144
#cmakedefine HAVE___THREAD

config.h.win32

+2
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@
115115

116116
#cmakedefine HAVE_STRTOLL
117117
#cmakedefine strtoll @cmake_strtoll@
118+
#cmakedefine HAVE_STRTOULL
119+
#cmakedefine strtoull @cmake_strtoull@
118120

119121
/* Define to 1 if you have the <syslog.h> header file. */
120122
#undef HAVE_SYSLOG_H

configure.ac

+1
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ AX_COMPILE_CHECK_SIZEOF(long)
200200
AX_COMPILE_CHECK_SIZEOF(long long)
201201
AX_COMPILE_CHECK_SIZEOF(size_t, [#include <stdint.h>])
202202
AX_COMPILE_CHECK_SIZEOF(int64_t, [#include <stdint.h>])
203+
AX_COMPILE_CHECK_SIZEOF(uint64_t, [#include <stdint.h>])
203204

204205
AC_CONFIG_FILES([
205206
Makefile

json_inttypes.h

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#define PRId64 "I64d"
1919
#define SCNd64 "I64d"
20+
#define PRIu64 "I64u"
2021

2122
#endif
2223

json_object.c

+95
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ static json_object_to_json_string_fn json_object_object_to_json_string;
5151
static json_object_to_json_string_fn json_object_boolean_to_json_string;
5252
static json_object_to_json_string_fn json_object_double_to_json_string_default;
5353
static json_object_to_json_string_fn json_object_int_to_json_string;
54+
static json_object_to_json_string_fn json_object_uint_to_json_string;
5455
static json_object_to_json_string_fn json_object_string_to_json_string;
5556
static json_object_to_json_string_fn json_object_array_to_json_string;
5657
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,
302303
case json_type_int:
303304
jso->_to_json_string = &json_object_int_to_json_string;
304305
break;
306+
case json_type_uint:
307+
jso->_to_json_string = &json_object_uint_to_json_string;
308+
break;
305309
case json_type_object:
306310
jso->_to_json_string = &json_object_object_to_json_string;
307311
break;
@@ -592,6 +596,8 @@ json_bool json_object_get_boolean(const struct json_object *jso)
592596
return jso->o.c_boolean;
593597
case json_type_int:
594598
return (jso->o.c_int64 != 0);
599+
case json_type_uint:
600+
return (jso->o.c_uint64 != 0);
595601
case json_type_double:
596602
return (jso->o.c_double != 0);
597603
case json_type_string:
@@ -622,6 +628,17 @@ static int json_object_int_to_json_string(struct json_object* jso,
622628
return printbuf_memappend (pb, sbuf, strlen(sbuf));
623629
}
624630

631+
static int json_object_uint_to_json_string(struct json_object* jso,
632+
struct printbuf *pb,
633+
int level,
634+
int flags)
635+
{
636+
/* room for 20 digits, and a null term */
637+
char sbuf[21];
638+
snprintf(sbuf, sizeof(sbuf), "%" PRIu64, jso->o.c_uint64);
639+
return printbuf_memappend (pb, sbuf, strlen(sbuf));
640+
}
641+
625642
struct json_object* json_object_new_int(int32_t i)
626643
{
627644
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)
661678
if (cint64 >= INT32_MAX)
662679
return INT32_MAX;
663680
return (int32_t) cint64;
681+
case json_type_uint:
682+
if (jso->o.c_uint64 >= INT32_MAX)
683+
return INT32_MAX;
684+
return (int32_t)jso->o.c_uint64;
664685
case json_type_double:
665686
if (jso->o.c_double <= INT32_MIN)
666687
return INT32_MIN;
@@ -691,6 +712,16 @@ struct json_object* json_object_new_int64(int64_t i)
691712
return jso;
692713
}
693714

715+
struct json_object* json_object_new_uint64(uint64_t i)
716+
{
717+
struct json_object *jso = json_object_new(json_type_uint);
718+
if (!jso)
719+
return NULL;
720+
jso->_to_json_string = &json_object_uint_to_json_string;
721+
jso->o.c_uint64 = i;
722+
return jso;
723+
}
724+
694725
int64_t json_object_get_int64(const struct json_object *jso)
695726
{
696727
int64_t cint;
@@ -701,6 +732,10 @@ int64_t json_object_get_int64(const struct json_object *jso)
701732
{
702733
case json_type_int:
703734
return jso->o.c_int64;
735+
case json_type_uint:
736+
if (jso->o.c_uint64 >= INT64_MAX)
737+
return INT64_MAX;
738+
return (int64_t)jso->o.c_uint64;
704739
case json_type_double:
705740
// INT64_MAX can't be exactly represented as a double
706741
// so cast to tell the compiler it's ok to round up.
@@ -720,13 +755,53 @@ int64_t json_object_get_int64(const struct json_object *jso)
720755
}
721756
}
722757

758+
uint64_t json_object_get_uint64(const struct json_object *jso)
759+
{
760+
uint64_t cuint;
761+
762+
if (!jso)
763+
return 0;
764+
switch(jso->o_type)
765+
{
766+
case json_type_int:
767+
if (jso->o.c_int64 < 0)
768+
return 0;
769+
return (uint64_t)jso->o.c_int64;
770+
case json_type_uint:
771+
return jso->o.c_uint64;
772+
case json_type_double:
773+
// UINT64_MAX can't be exactly represented as a double
774+
// so cast to tell the compiler it's ok to round up.
775+
if (jso->o.c_double >= (double)UINT64_MAX)
776+
return UINT64_MAX;
777+
if (jso->o.c_double < 0)
778+
return 0;
779+
return (uint64_t)jso->o.c_double;
780+
case json_type_boolean:
781+
return jso->o.c_boolean;
782+
case json_type_string:
783+
if (json_parse_uint64(get_string_component(jso), &cuint) == 0)
784+
return cuint;
785+
/* FALLTHRU */
786+
default:
787+
return 0;
788+
}
789+
}
790+
723791
int json_object_set_int64(struct json_object *jso,int64_t new_value){
724792
if (!jso || jso->o_type!=json_type_int)
725793
return 0;
726794
jso->o.c_int64=new_value;
727795
return 1;
728796
}
729797

798+
int json_object_set_uint64(struct json_object *jso,uint64_t new_value){
799+
if (!jso || jso->o_type!=json_type_uint)
800+
return 0;
801+
jso->o.c_uint64=new_value;
802+
return 1;
803+
}
804+
730805
int json_object_int_inc(struct json_object *jso, int64_t val) {
731806
if (!jso || jso->o_type != json_type_int)
732807
return 0;
@@ -740,6 +815,17 @@ int json_object_int_inc(struct json_object *jso, int64_t val) {
740815
return 1;
741816
}
742817

818+
int json_object_uint_inc(struct json_object *jso, uint64_t val) {
819+
if (!jso || jso->o_type != json_type_uint)
820+
return 0;
821+
if (jso->o.c_uint64 > UINT64_MAX - val) {
822+
jso->o.c_uint64 = UINT64_MAX;
823+
} else {
824+
jso->o.c_uint64 += val;
825+
}
826+
return 1;
827+
}
828+
743829
/* json_object_double */
744830

745831
#if defined(HAVE___THREAD)
@@ -962,6 +1048,8 @@ double json_object_get_double(const struct json_object *jso)
9621048
return jso->o.c_double;
9631049
case json_type_int:
9641050
return jso->o.c_int64;
1051+
case json_type_uint:
1052+
return jso->o.c_uint64;
9651053
case json_type_boolean:
9661054
return jso->o.c_boolean;
9671055
case json_type_string:
@@ -1342,6 +1430,9 @@ int json_object_equal(struct json_object* jso1, struct json_object* jso2)
13421430
case json_type_int:
13431431
return (jso1->o.c_int64 == jso2->o.c_int64);
13441432

1433+
case json_type_uint:
1434+
return (jso1->o.c_uint64 == jso2->o.c_uint64);
1435+
13451436
case json_type_string:
13461437
return (jso1->o.c_string.len == jso2->o.c_string.len &&
13471438
memcmp(get_string_component(jso1),
@@ -1405,6 +1496,10 @@ int json_c_shallow_copy_default(json_object *src, json_object *parent, const cha
14051496
*dst = json_object_new_int64(src->o.c_int64);
14061497
break;
14071498

1499+
case json_type_uint:
1500+
*dst = json_object_new_uint64(src->o.c_uint64);
1501+
break;
1502+
14081503
case json_type_string:
14091504
*dst = json_object_new_string(get_string_component(src));
14101505
break;

json_object.h

+49
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ typedef enum json_type {
176176
json_type_boolean,
177177
json_type_double,
178178
json_type_int,
179+
json_type_uint,
179180
json_type_object,
180181
json_type_array,
181182
json_type_string
@@ -210,6 +211,7 @@ JSON_EXPORT int json_object_put(struct json_object *obj);
210211
json_type_boolean,
211212
json_type_double,
212213
json_type_int,
214+
json_type_uint,
213215
json_type_object,
214216
json_type_array,
215217
json_type_string
@@ -226,6 +228,7 @@ JSON_EXPORT int json_object_is_type(const struct json_object *obj, enum json_typ
226228
json_type_boolean,
227229
json_type_double,
228230
json_type_int,
231+
json_type_uint,
229232
json_type_object,
230233
json_type_array,
231234
json_type_string
@@ -701,6 +704,13 @@ JSON_EXPORT struct json_object* json_object_new_int(int32_t i);
701704
JSON_EXPORT struct json_object* json_object_new_int64(int64_t i);
702705

703706

707+
/** Create a new empty json_object of type json_type_uint
708+
* @param i the integer
709+
* @returns a json_object of type json_type_uint
710+
*/
711+
JSON_EXPORT struct json_object* json_object_new_uint64(uint64_t i);
712+
713+
704714
/** Get the int value of a json_object
705715
*
706716
* 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);
745755
*/
746756
JSON_EXPORT int json_object_int_inc(struct json_object *obj, int64_t val);
747757

758+
/** Increment a json_type_uint object by the given amount, which may be negative.
759+
*
760+
* If the type of obj is not json_type_uint then 0 is returned with no further
761+
* action taken.
762+
* If the addition would result in a overflow, the object value
763+
* is set to UINT64_MAX.
764+
* Neither overflow nor underflow affect the return value.
765+
*
766+
* @param obj the json_object instance
767+
* @param val the value to add
768+
* @returns 1 if the increment succeded, 0 otherwise
769+
*/
770+
JSON_EXPORT int json_object_uint_inc(struct json_object *obj, uint64_t val);
748771

749772
/** Get the int value of a json_object
750773
*
@@ -761,6 +784,20 @@ JSON_EXPORT int json_object_int_inc(struct json_object *obj, int64_t val);
761784
*/
762785
JSON_EXPORT int64_t json_object_get_int64(const struct json_object *obj);
763786

787+
/** Get the uint value of a json_object
788+
*
789+
* The type is coerced to a uint64 if the passed object is not a uint64.
790+
* double objects will return their uint64 conversion. Strings will be
791+
* parsed as an uint64. If no conversion exists then 0 is returned.
792+
*
793+
* NOTE: Set errno to 0 directly before a call to this function to determine
794+
* whether or not conversion was successful (it does not clear the value for
795+
* you).
796+
*
797+
* @param obj the json_object instance
798+
* @returns an uint64
799+
*/
800+
JSON_EXPORT uint64_t json_object_get_uint64(const struct json_object *obj);
764801

765802
/** Set the int64_t value of a json_object
766803
*
@@ -774,6 +811,18 @@ JSON_EXPORT int64_t json_object_get_int64(const struct json_object *obj);
774811
*/
775812
JSON_EXPORT int json_object_set_int64(struct json_object *obj,int64_t new_value);
776813

814+
/** Set the uint64_t value of a json_object
815+
*
816+
* The type of obj is checked to be a json_type_uint and 0 is returned
817+
* if it is not without any further actions. If type of obj is json_type_uint
818+
* the object value is changed to new_value
819+
*
820+
* @param obj the json_object instance
821+
* @param new_value the value to be set
822+
* @returns 1 if value is set correctly, 0 otherwise
823+
*/
824+
JSON_EXPORT int json_object_set_uint64(struct json_object *obj,uint64_t new_value);
825+
777826
/* double type methods */
778827

779828
/** Create a new empty json_object of type json_type_double

json_object_private.h

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct json_object
3535
json_bool c_boolean;
3636
double c_double;
3737
int64_t c_int64;
38+
uint64_t c_uint64;
3839
struct lh_table *c_object;
3940
struct array_list *c_array;
4041
struct {

json_tokener.c

+21-9
Original file line numberDiff line numberDiff line change
@@ -792,21 +792,33 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
792792
}
793793
{
794794
int64_t num64;
795+
uint64_t numuint64;
795796
double numd;
796-
if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
797-
if (num64 && tok->pb->buf[0]=='0' &&
797+
if (!tok->is_double && tok->pb->buf[0] == '-'
798+
&& json_parse_int64(tok->pb->buf, &num64) == 0) {
799+
current = json_object_new_int64(num64);
800+
if(current == NULL)
801+
goto out;
802+
} else if ( !tok->is_double && tok->pb->buf[0] != '-'
803+
&& json_parse_uint64(tok->pb->buf, &numuint64) == 0) {
804+
if (numuint64 && tok->pb->buf[0]=='0' &&
798805
(tok->flags & JSON_TOKENER_STRICT)) {
799-
/* in strict mode, number must not start with 0 */
800806
tok->err = json_tokener_error_parse_number;
801807
goto out;
802808
}
803-
current = json_object_new_int64(num64);
804-
if(current == NULL)
805-
goto out;
806-
}
807-
else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
809+
if (numuint64 <= INT64_MAX){
810+
num64 = (uint64_t) numuint64;
811+
current = json_object_new_int64(num64);
812+
if(current == NULL)
813+
goto out;
814+
} else {
815+
current = json_object_new_uint64(numuint64);
816+
if(current == NULL)
817+
goto out;
818+
}
819+
} else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
808820
{
809-
current = json_object_new_double_s(numd, tok->pb->buf);
821+
current = json_object_new_double_s(numd, tok->pb->buf);
810822
if(current == NULL)
811823
goto out;
812824
} else {

0 commit comments

Comments
 (0)