2 * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
4 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
5 * Michael Clark <michael@metaparadigm.com>
6 * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
8 * This library is free software; you can redistribute it and/or modify
9 * it under the terms of the MIT license. See COPYING for details.
25 #include "arraylist.h"
26 #include "json_inttypes.h"
27 #include "json_object.h"
28 #include "json_object_private.h"
29 #include "json_util.h"
30 #include "math_compat.h"
32 #if !defined(HAVE_STRDUP) && defined(_MSC_VER)
33 /* MSC has the version as _strdup */
34 # define strdup _strdup
35 #elif !defined(HAVE_STRDUP)
36 # error You do not have strdup on your system.
37 #endif /* HAVE_STRDUP */
39 #if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
40 /* MSC has the version as _snprintf */
41 # define snprintf _snprintf
42 #elif !defined(HAVE_SNPRINTF)
43 # error You do not have snprintf on your system.
44 #endif /* HAVE_SNPRINTF */
46 // Don't define this. It's not thread-safe.
47 /* #define REFCOUNT_DEBUG 1 */
49 const char *json_number_chars
= "0123456789.+-eE";
50 const char *json_hex_chars
= "0123456789abcdefABCDEF";
52 static void json_object_generic_delete(struct json_object
* jso
);
53 static struct json_object
* json_object_new(enum json_type o_type
);
55 static json_object_to_json_string_fn json_object_object_to_json_string
;
56 static json_object_to_json_string_fn json_object_boolean_to_json_string
;
57 static json_object_to_json_string_fn json_object_int_to_json_string
;
58 static json_object_to_json_string_fn json_object_double_to_json_string
;
59 static json_object_to_json_string_fn json_object_string_to_json_string
;
60 static json_object_to_json_string_fn json_object_array_to_json_string
;
63 /* ref count debugging */
67 static struct lh_table
*json_object_table
;
69 static void json_object_init(void) __attribute__ ((constructor
));
70 static void json_object_init(void) {
71 MC_DEBUG("json_object_init: creating object table\n");
72 json_object_table
= lh_kptr_table_new(128, "json_object_table", NULL
);
75 static void json_object_fini(void) __attribute__ ((destructor
));
76 static void json_object_fini(void) {
79 if (json_object_table
->count
) {
80 MC_DEBUG("json_object_fini: %d referenced objects at exit\n",
81 json_object_table
->count
);
82 lh_foreach(json_object_table
, ent
) {
83 struct json_object
* obj
= (struct json_object
*)ent
->v
;
84 MC_DEBUG("\t%s:%p\n", json_type_to_name(obj
->o_type
), obj
);
88 MC_DEBUG("json_object_fini: freeing object table\n");
89 lh_table_free(json_object_table
);
91 #endif /* REFCOUNT_DEBUG */
96 static int json_escape_str(struct printbuf
*pb
, char *str
, int len
)
98 int pos
= 0, start_offset
= 0;
111 if(pos
- start_offset
> 0)
112 printbuf_memappend(pb
, str
+ start_offset
, pos
- start_offset
);
113 if(c
== '\b') printbuf_memappend(pb
, "\\b", 2);
114 else if(c
== '\n') printbuf_memappend(pb
, "\\n", 2);
115 else if(c
== '\r') printbuf_memappend(pb
, "\\r", 2);
116 else if(c
== '\t') printbuf_memappend(pb
, "\\t", 2);
117 else if(c
== '\f') printbuf_memappend(pb
, "\\f", 2);
118 else if(c
== '"') printbuf_memappend(pb
, "\\\"", 2);
119 else if(c
== '\\') printbuf_memappend(pb
, "\\\\", 2);
120 else if(c
== '/') printbuf_memappend(pb
, "\\/", 2);
121 start_offset
= ++pos
;
125 if(pos
- start_offset
> 0)
126 printbuf_memappend(pb
, str
+ start_offset
, pos
- start_offset
);
127 sprintbuf(pb
, "\\u00%c%c",
128 json_hex_chars
[c
>> 4],
129 json_hex_chars
[c
& 0xf]);
130 start_offset
= ++pos
;
134 if(pos
- start_offset
> 0)
135 printbuf_memappend(pb
, str
+ start_offset
, pos
- start_offset
);
140 /* reference counting */
142 extern struct json_object
* json_object_get(struct json_object
*jso
)
150 int json_object_put(struct json_object
*jso
)
157 if (jso
->_user_delete
)
158 jso
->_user_delete(jso
, jso
->_userdata
);
167 /* generic object construction and destruction parts */
169 static void json_object_generic_delete(struct json_object
* jso
)
171 #ifdef REFCOUNT_DEBUG
172 MC_DEBUG("json_object_delete_%s: %p\n",
173 json_type_to_name(jso
->o_type
), jso
);
174 lh_table_delete(json_object_table
, jso
);
175 #endif /* REFCOUNT_DEBUG */
176 printbuf_free(jso
->_pb
);
180 static struct json_object
* json_object_new(enum json_type o_type
)
182 struct json_object
*jso
;
184 jso
= (struct json_object
*)calloc(sizeof(struct json_object
), 1);
185 if(!jso
) return NULL
;
186 jso
->o_type
= o_type
;
188 jso
->_delete
= &json_object_generic_delete
;
189 #ifdef REFCOUNT_DEBUG
190 lh_table_insert(json_object_table
, jso
, jso
);
191 MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso
->o_type
), jso
);
192 #endif /* REFCOUNT_DEBUG */
197 /* type checking functions */
199 int json_object_is_type(struct json_object
*jso
, enum json_type type
)
202 return (type
== json_type_null
);
203 return (jso
->o_type
== type
);
206 enum json_type
json_object_get_type(struct json_object
*jso
)
209 return json_type_null
;
213 /* set a custom conversion to string */
215 void json_object_set_serializer(json_object
*jso
,
216 json_object_to_json_string_fn to_string_func
,
218 json_object_delete_fn
*user_delete
)
220 // First, clean up any previously existing user info
221 if (jso
->_user_delete
)
223 jso
->_user_delete(jso
, jso
->_userdata
);
225 jso
->_userdata
= NULL
;
226 jso
->_user_delete
= NULL
;
228 if (to_string_func
== NULL
)
230 // Reset to the standard serialization function
234 jso
->_to_json_string
= NULL
;
236 case json_type_boolean
:
237 jso
->_to_json_string
= &json_object_boolean_to_json_string
;
239 case json_type_double
:
240 jso
->_to_json_string
= &json_object_double_to_json_string
;
243 jso
->_to_json_string
= &json_object_int_to_json_string
;
245 case json_type_object
:
246 jso
->_to_json_string
= &json_object_object_to_json_string
;
248 case json_type_array
:
249 jso
->_to_json_string
= &json_object_array_to_json_string
;
251 case json_type_string
:
252 jso
->_to_json_string
= &json_object_string_to_json_string
;
258 jso
->_to_json_string
= to_string_func
;
259 jso
->_userdata
= userdata
;
260 jso
->_user_delete
= user_delete
;
264 /* extended conversion to string */
266 const char* json_object_to_json_string_ext(struct json_object
*jso
, int flags
)
271 if ((!jso
->_pb
) && !(jso
->_pb
= printbuf_new()))
274 printbuf_reset(jso
->_pb
);
276 if(jso
->_to_json_string(jso
, jso
->_pb
, 0, flags
) < 0)
279 return jso
->_pb
->buf
;
282 /* backwards-compatible conversion to string */
284 const char* json_object_to_json_string(struct json_object
*jso
)
286 return json_object_to_json_string_ext(jso
, JSON_C_TO_STRING_SPACED
);
289 static void indent(struct printbuf
*pb
, int level
, int flags
)
291 if (flags
& JSON_C_TO_STRING_PRETTY
)
293 printbuf_memset(pb
, -1, ' ', level
* 2);
297 /* json_object_object */
299 static int json_object_object_to_json_string(struct json_object
* jso
,
304 int had_children
= 0;
305 struct json_object_iter iter
;
307 sprintbuf(pb
, "{" /*}*/);
308 if (flags
& JSON_C_TO_STRING_PRETTY
)
310 json_object_object_foreachC(jso
, iter
)
315 if (flags
& JSON_C_TO_STRING_PRETTY
)
319 if (flags
& JSON_C_TO_STRING_SPACED
)
321 indent(pb
, level
+1, flags
);
323 json_escape_str(pb
, iter
.key
, strlen(iter
.key
));
324 if (flags
& JSON_C_TO_STRING_SPACED
)
325 sprintbuf(pb
, "\": ");
327 sprintbuf(pb
, "\":");
329 sprintbuf(pb
, "null");
331 iter
.val
->_to_json_string(iter
.val
, pb
, level
+1,flags
);
333 if (flags
& JSON_C_TO_STRING_PRETTY
)
337 indent(pb
,level
,flags
);
339 if (flags
& JSON_C_TO_STRING_SPACED
)
340 return sprintbuf(pb
, /*{*/ " }");
342 return sprintbuf(pb
, /*{*/ "}");
346 static void json_object_lh_entry_free(struct lh_entry
*ent
)
349 json_object_put((struct json_object
*)ent
->v
);
352 static void json_object_object_delete(struct json_object
* jso
)
354 lh_table_free(jso
->o
.c_object
);
355 json_object_generic_delete(jso
);
358 struct json_object
* json_object_new_object(void)
360 struct json_object
*jso
= json_object_new(json_type_object
);
361 if(!jso
) return NULL
;
362 jso
->_delete
= &json_object_object_delete
;
363 jso
->_to_json_string
= &json_object_object_to_json_string
;
364 jso
->o
.c_object
= lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES
,
365 NULL
, &json_object_lh_entry_free
);
369 struct lh_table
* json_object_get_object(struct json_object
*jso
)
371 if(!jso
) return NULL
;
372 switch(jso
->o_type
) {
373 case json_type_object
:
374 return jso
->o
.c_object
;
380 void json_object_object_add(struct json_object
* jso
, const char *key
,
381 struct json_object
*val
)
383 // We lookup the entry and replace the value, rather than just deleting
384 // and re-adding it, so the existing key remains valid.
385 json_object
*existing_value
= NULL
;
386 struct lh_entry
*existing_entry
;
387 existing_entry
= lh_table_lookup_entry(jso
->o
.c_object
, (void*)key
);
390 lh_table_insert(jso
->o
.c_object
, strdup(key
), val
);
393 existing_value
= (void *)existing_entry
->v
;
395 json_object_put(existing_value
);
396 existing_entry
->v
= val
;
399 int json_object_object_length(struct json_object
*jso
)
401 return lh_table_length(jso
->o
.c_object
);
404 struct json_object
* json_object_object_get(struct json_object
* jso
, const char *key
)
406 struct json_object
*result
= NULL
;
407 json_object_object_get_ex(jso
, key
, &result
);
411 json_bool
json_object_object_get_ex(struct json_object
* jso
, const char *key
, struct json_object
**value
)
421 case json_type_object
:
422 return lh_table_lookup_ex(jso
->o
.c_object
, (void*)key
, (void**)value
);
430 void json_object_object_del(struct json_object
* jso
, const char *key
)
432 lh_table_delete(jso
->o
.c_object
, key
);
436 /* json_object_boolean */
438 static int json_object_boolean_to_json_string(struct json_object
* jso
,
443 if(jso
->o
.c_boolean
) return sprintbuf(pb
, "true");
444 else return sprintbuf(pb
, "false");
447 struct json_object
* json_object_new_boolean(json_bool b
)
449 struct json_object
*jso
= json_object_new(json_type_boolean
);
450 if(!jso
) return NULL
;
451 jso
->_to_json_string
= &json_object_boolean_to_json_string
;
452 jso
->o
.c_boolean
= b
;
456 json_bool
json_object_get_boolean(struct json_object
*jso
)
458 if(!jso
) return FALSE
;
459 switch(jso
->o_type
) {
460 case json_type_boolean
:
461 return jso
->o
.c_boolean
;
463 return (jso
->o
.c_int64
!= 0);
464 case json_type_double
:
465 return (jso
->o
.c_double
!= 0);
466 case json_type_string
:
467 return (jso
->o
.c_string
.len
!= 0);
474 /* json_object_int */
476 static int json_object_int_to_json_string(struct json_object
* jso
,
481 return sprintbuf(pb
, "%"PRId64
, jso
->o
.c_int64
);
484 struct json_object
* json_object_new_int(int32_t i
)
486 struct json_object
*jso
= json_object_new(json_type_int
);
487 if(!jso
) return NULL
;
488 jso
->_to_json_string
= &json_object_int_to_json_string
;
493 int32_t json_object_get_int(struct json_object
*jso
)
496 enum json_type o_type
;
500 o_type
= jso
->o_type
;
501 cint64
= jso
->o
.c_int64
;
503 if (o_type
== json_type_string
)
506 * Parse strings into 64-bit numbers, then use the
507 * 64-to-32-bit number handling below.
509 if (json_parse_int64(jso
->o
.c_string
.str
, &cint64
) != 0)
510 return 0; /* whoops, it didn't work. */
511 o_type
= json_type_int
;
516 /* Make sure we return the correct values for out of range numbers. */
517 if (cint64
<= INT32_MIN
)
519 else if (cint64
>= INT32_MAX
)
522 return (int32_t)cint64
;
523 case json_type_double
:
524 return (int32_t)jso
->o
.c_double
;
525 case json_type_boolean
:
526 return jso
->o
.c_boolean
;
532 struct json_object
* json_object_new_int64(int64_t i
)
534 struct json_object
*jso
= json_object_new(json_type_int
);
535 if(!jso
) return NULL
;
536 jso
->_to_json_string
= &json_object_int_to_json_string
;
541 int64_t json_object_get_int64(struct json_object
*jso
)
546 switch(jso
->o_type
) {
548 return jso
->o
.c_int64
;
549 case json_type_double
:
550 return (int64_t)jso
->o
.c_double
;
551 case json_type_boolean
:
552 return jso
->o
.c_boolean
;
553 case json_type_string
:
554 if (json_parse_int64(jso
->o
.c_string
.str
, &cint
) == 0) return cint
;
561 /* json_object_double */
563 static int json_object_double_to_json_string(struct json_object
* jso
,
568 char buf
[128], *p
, *q
;
570 /* Although JSON RFC does not support
571 NaN or Infinity as numeric values
572 ECMA 262 section 9.8.1 defines
573 how to handle these cases as strings */
574 if(isnan(jso
->o
.c_double
))
575 size
= snprintf(buf
, sizeof(buf
), "NaN");
576 else if(isinf(jso
->o
.c_double
))
577 if(jso
->o
.c_double
> 0)
578 size
= snprintf(buf
, sizeof(buf
), "Infinity");
580 size
= snprintf(buf
, sizeof(buf
), "-Infinity");
582 size
= snprintf(buf
, sizeof(buf
), "%.17g", jso
->o
.c_double
);
584 p
= strchr(buf
, ',');
588 p
= strchr(buf
, '.');
590 if (p
&& (flags
& JSON_C_TO_STRING_NOZERO
)) {
591 /* last useful digit, always keep 1 zero */
593 for (q
=p
; *q
; q
++) {
596 /* drop trailing zeroes */
600 printbuf_memappend(pb
, buf
, size
);
604 struct json_object
* json_object_new_double(double d
)
606 struct json_object
*jso
= json_object_new(json_type_double
);
609 jso
->_to_json_string
= &json_object_double_to_json_string
;
614 struct json_object
* json_object_new_double_s(double d
, const char *ds
)
616 struct json_object
*jso
= json_object_new_double(d
);
620 json_object_set_serializer(jso
, json_object_userdata_to_json_string
,
621 strdup(ds
), json_object_free_userdata
);
625 int json_object_userdata_to_json_string(struct json_object
*jso
,
626 struct printbuf
*pb
, int level
, int flags
)
628 int userdata_len
= strlen(jso
->_userdata
);
629 printbuf_memappend(pb
, jso
->_userdata
, userdata_len
);
633 void json_object_free_userdata(struct json_object
*jso
, void *userdata
)
638 double json_object_get_double(struct json_object
*jso
)
644 switch(jso
->o_type
) {
645 case json_type_double
:
646 return jso
->o
.c_double
;
648 return jso
->o
.c_int64
;
649 case json_type_boolean
:
650 return jso
->o
.c_boolean
;
651 case json_type_string
:
653 cdouble
= strtod(jso
->o
.c_string
.str
,&errPtr
);
655 /* if conversion stopped at the first character, return 0.0 */
656 if (errPtr
== jso
->o
.c_string
.str
)
660 * Check that the conversion terminated on something sensible
662 * For example, { "pay" : 123AB } would parse as 123.
668 * If strtod encounters a string which would exceed the
669 * capacity of a double, it returns +/- HUGE_VAL and sets
670 * errno to ERANGE. But +/- HUGE_VAL is also a valid result
671 * from a conversion, so we need to check errno.
673 * Underflow also sets errno to ERANGE, but it returns 0 in
674 * that case, which is what we will return anyway.
676 * See CERT guideline ERR30-C
678 if ((HUGE_VAL
== cdouble
|| -HUGE_VAL
== cdouble
) &&
688 /* json_object_string */
690 static int json_object_string_to_json_string(struct json_object
* jso
,
696 json_escape_str(pb
, jso
->o
.c_string
.str
, jso
->o
.c_string
.len
);
701 static void json_object_string_delete(struct json_object
* jso
)
703 free(jso
->o
.c_string
.str
);
704 json_object_generic_delete(jso
);
707 struct json_object
* json_object_new_string(const char *s
)
709 struct json_object
*jso
= json_object_new(json_type_string
);
710 if(!jso
) return NULL
;
711 jso
->_delete
= &json_object_string_delete
;
712 jso
->_to_json_string
= &json_object_string_to_json_string
;
713 jso
->o
.c_string
.str
= strdup(s
);
714 jso
->o
.c_string
.len
= strlen(s
);
718 struct json_object
* json_object_new_string_len(const char *s
, int len
)
720 struct json_object
*jso
= json_object_new(json_type_string
);
721 if(!jso
) return NULL
;
722 jso
->_delete
= &json_object_string_delete
;
723 jso
->_to_json_string
= &json_object_string_to_json_string
;
724 jso
->o
.c_string
.str
= (char*)malloc(len
+ 1);
725 memcpy(jso
->o
.c_string
.str
, (void *)s
, len
);
726 jso
->o
.c_string
.str
[len
] = '\0';
727 jso
->o
.c_string
.len
= len
;
731 const char* json_object_get_string(struct json_object
*jso
)
733 if(!jso
) return NULL
;
734 switch(jso
->o_type
) {
735 case json_type_string
:
736 return jso
->o
.c_string
.str
;
738 return json_object_to_json_string(jso
);
742 int json_object_get_string_len(struct json_object
*jso
) {
744 switch(jso
->o_type
) {
745 case json_type_string
:
746 return jso
->o
.c_string
.len
;
753 /* json_object_array */
755 static int json_object_array_to_json_string(struct json_object
* jso
,
760 int had_children
= 0;
763 if (flags
& JSON_C_TO_STRING_PRETTY
)
765 for(ii
=0; ii
< json_object_array_length(jso
); ii
++)
767 struct json_object
*val
;
771 if (flags
& JSON_C_TO_STRING_PRETTY
)
775 if (flags
& JSON_C_TO_STRING_SPACED
)
777 indent(pb
, level
+ 1, flags
);
778 val
= json_object_array_get_idx(jso
, ii
);
780 sprintbuf(pb
, "null");
782 val
->_to_json_string(val
, pb
, level
+1, flags
);
784 if (flags
& JSON_C_TO_STRING_PRETTY
)
788 indent(pb
,level
,flags
);
791 if (flags
& JSON_C_TO_STRING_SPACED
)
792 return sprintbuf(pb
, " ]");
794 return sprintbuf(pb
, "]");
797 static void json_object_array_entry_free(void *data
)
799 json_object_put((struct json_object
*)data
);
802 static void json_object_array_delete(struct json_object
* jso
)
804 array_list_free(jso
->o
.c_array
);
805 json_object_generic_delete(jso
);
808 struct json_object
* json_object_new_array(void)
810 struct json_object
*jso
= json_object_new(json_type_array
);
811 if(!jso
) return NULL
;
812 jso
->_delete
= &json_object_array_delete
;
813 jso
->_to_json_string
= &json_object_array_to_json_string
;
814 jso
->o
.c_array
= array_list_new(&json_object_array_entry_free
);
818 struct array_list
* json_object_get_array(struct json_object
*jso
)
820 if(!jso
) return NULL
;
821 switch(jso
->o_type
) {
822 case json_type_array
:
823 return jso
->o
.c_array
;
829 void json_object_array_sort(struct json_object
*jso
, int(*sort_fn
)(const void *, const void *))
831 array_list_sort(jso
->o
.c_array
, sort_fn
);
834 int json_object_array_length(struct json_object
*jso
)
836 return array_list_length(jso
->o
.c_array
);
839 int json_object_array_add(struct json_object
*jso
,struct json_object
*val
)
841 return array_list_add(jso
->o
.c_array
, val
);
844 int json_object_array_put_idx(struct json_object
*jso
, int idx
,
845 struct json_object
*val
)
847 return array_list_put_idx(jso
->o
.c_array
, idx
, val
);
850 struct json_object
* json_object_array_get_idx(struct json_object
*jso
,
853 return (struct json_object
*)array_list_get_idx(jso
->o
.c_array
, idx
);