blob: facb824fb84b0af3c278ba856468b47172a5ce7d [file] [log] [blame]
Michael Clarkf0d08882007-03-13 08:26:18 +00001/*
Michael Clarka850f8e2007-03-13 08:26:26 +00002 * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
Michael Clarkf0d08882007-03-13 08:26:18 +00003 *
Michael Clarkf6a6e482007-03-13 08:26:23 +00004 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
Michael Clarkf0d08882007-03-13 08:26:18 +00005 * Michael Clark <michael@metaparadigm.com>
Keith Derrick69175862012-04-12 11:44:13 -07006 * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
Michael Clarkf0d08882007-03-13 08:26:18 +00007 *
Michael Clarkf6a6e482007-03-13 08:26:23 +00008 * 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.
Michael Clarkf0d08882007-03-13 08:26:18 +000010 *
11 */
12
Michael Clark4504df72007-03-13 08:26:20 +000013#include "config.h"
14
Michael Clarkf0d08882007-03-13 08:26:18 +000015#include <stdio.h>
16#include <stdlib.h>
Michael Clarkc8f4a6e2007-12-07 02:44:24 +000017#include <stddef.h>
Michael Clarkf0d08882007-03-13 08:26:18 +000018#include <string.h>
19
20#include "debug.h"
21#include "printbuf.h"
22#include "linkhash.h"
23#include "arraylist.h"
Michael Clarkc4dceae2010-10-06 16:39:20 +000024#include "json_inttypes.h"
Michael Clarkf0d08882007-03-13 08:26:18 +000025#include "json_object.h"
26#include "json_object_private.h"
Michael Clarkc4dceae2010-10-06 16:39:20 +000027#include "json_util.h"
Michael Clarkf0d08882007-03-13 08:26:18 +000028
Mateusz Loskota6f39a32012-05-21 23:22:36 +010029#if !defined(HAVE_STRDUP) && defined(_MSC_VER)
30 /* MSC has the version as _strdup */
31# define strdup _strdup
32#elif !defined(HAVE_STRDUP)
33# error You do not have strdup on your system.
34#endif /* HAVE_STRDUP */
35
36#if !defined(HAVE_STRNDUP)
Michael Clark837240f2007-03-13 08:26:25 +000037 char* strndup(const char* str, size_t n);
38#endif /* !HAVE_STRNDUP */
39
Anatol Belskied819fb2013-06-04 20:18:05 +020040#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
41 /* MSC has the version as _snprintf */
42# define snprintf _snprintf
43#elif !defined(HAVE_SNPRINTF)
44# error You do not have snprintf on your system.
45#endif /* HAVE_SNPRINTF */
46
Keith Derrick69175862012-04-12 11:44:13 -070047// Don't define this. It's not thread-safe.
Christopher Watfordc5cbf822009-06-30 03:40:53 +000048/* #define REFCOUNT_DEBUG 1 */
Michael Clarkf0d08882007-03-13 08:26:18 +000049
Michael Clark68cafad2009-01-06 22:56:57 +000050const char *json_number_chars = "0123456789.+-eE";
Federico Culloca7ec34c92011-10-30 12:13:15 +010051const char *json_hex_chars = "0123456789abcdefABCDEF";
Michael Clarkf0d08882007-03-13 08:26:18 +000052
Michael Clark266a3fd2009-02-25 01:55:31 +000053static void json_object_generic_delete(struct json_object* jso);
Michael Clarkf0d08882007-03-13 08:26:18 +000054static struct json_object* json_object_new(enum json_type o_type);
55
Eric Haszlakiewicz38f421a2012-09-02 15:21:56 -050056static json_object_to_json_string_fn json_object_object_to_json_string;
57static json_object_to_json_string_fn json_object_boolean_to_json_string;
58static json_object_to_json_string_fn json_object_int_to_json_string;
59static json_object_to_json_string_fn json_object_double_to_json_string;
60static json_object_to_json_string_fn json_object_string_to_json_string;
61static json_object_to_json_string_fn json_object_array_to_json_string;
62
Michael Clarkf0d08882007-03-13 08:26:18 +000063
64/* ref count debugging */
65
66#ifdef REFCOUNT_DEBUG
67
68static struct lh_table *json_object_table;
69
Michael Clark14862b12007-12-07 02:50:42 +000070static void json_object_init(void) __attribute__ ((constructor));
71static void json_object_init(void) {
Michael Clarkdfaf6702007-10-25 02:26:00 +000072 MC_DEBUG("json_object_init: creating object table\n");
Michael Clarkf0d08882007-03-13 08:26:18 +000073 json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
74}
75
Michael Clark14862b12007-12-07 02:50:42 +000076static void json_object_fini(void) __attribute__ ((destructor));
77static void json_object_fini(void) {
Michael Clarkf0d08882007-03-13 08:26:18 +000078 struct lh_entry *ent;
Michael Clarkdfaf6702007-10-25 02:26:00 +000079 if(MC_GET_DEBUG()) {
80 if (json_object_table->count) {
81 MC_DEBUG("json_object_fini: %d referenced objects at exit\n",
82 json_object_table->count);
83 lh_foreach(json_object_table, ent) {
84 struct json_object* obj = (struct json_object*)ent->v;
Eric Haszlakiewicz886c4fb2011-05-03 20:40:49 +000085 MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj);
Michael Clarkdfaf6702007-10-25 02:26:00 +000086 }
Michael Clarkf0d08882007-03-13 08:26:18 +000087 }
88 }
Michael Clarkdfaf6702007-10-25 02:26:00 +000089 MC_DEBUG("json_object_fini: freeing object table\n");
Michael Clarkf0d08882007-03-13 08:26:18 +000090 lh_table_free(json_object_table);
91}
Michael Clark4504df72007-03-13 08:26:20 +000092#endif /* REFCOUNT_DEBUG */
Michael Clarkf0d08882007-03-13 08:26:18 +000093
94
95/* string escaping */
96
Jehiah Czebotarac601b52011-01-14 17:23:06 +000097static int json_escape_str(struct printbuf *pb, char *str, int len)
Michael Clarkf0d08882007-03-13 08:26:18 +000098{
99 int pos = 0, start_offset = 0;
Michael Clark837240f2007-03-13 08:26:25 +0000100 unsigned char c;
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000101 while (len--) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000102 c = str[pos];
103 switch(c) {
104 case '\b':
105 case '\n':
106 case '\r':
107 case '\t':
Abioy7eaa8492012-12-24 22:22:05 +0800108 case '\f':
Michael Clark4504df72007-03-13 08:26:20 +0000109 case '"':
Michael Clarka850f8e2007-03-13 08:26:26 +0000110 case '\\':
111 case '/':
Michael Clarkf0d08882007-03-13 08:26:18 +0000112 if(pos - start_offset > 0)
113 printbuf_memappend(pb, str + start_offset, pos - start_offset);
114 if(c == '\b') printbuf_memappend(pb, "\\b", 2);
115 else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
116 else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
117 else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
Abioy7eaa8492012-12-24 22:22:05 +0800118 else if(c == '\f') printbuf_memappend(pb, "\\f", 2);
Michael Clark4504df72007-03-13 08:26:20 +0000119 else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
Michael Clarka850f8e2007-03-13 08:26:26 +0000120 else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
121 else if(c == '/') printbuf_memappend(pb, "\\/", 2);
Michael Clarkf0d08882007-03-13 08:26:18 +0000122 start_offset = ++pos;
123 break;
124 default:
Michael Clark837240f2007-03-13 08:26:25 +0000125 if(c < ' ') {
Michael Clarkf0d08882007-03-13 08:26:18 +0000126 if(pos - start_offset > 0)
127 printbuf_memappend(pb, str + start_offset, pos - start_offset);
128 sprintbuf(pb, "\\u00%c%c",
129 json_hex_chars[c >> 4],
130 json_hex_chars[c & 0xf]);
131 start_offset = ++pos;
Michael Clark837240f2007-03-13 08:26:25 +0000132 } else pos++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000133 }
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000134 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000135 if(pos - start_offset > 0)
136 printbuf_memappend(pb, str + start_offset, pos - start_offset);
137 return 0;
138}
139
140
141/* reference counting */
142
Michael Clark266a3fd2009-02-25 01:55:31 +0000143extern struct json_object* json_object_get(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000144{
Michael Clark266a3fd2009-02-25 01:55:31 +0000145 if(jso) {
146 jso->_ref_count++;
Michael Clarkf0d08882007-03-13 08:26:18 +0000147 }
Michael Clark266a3fd2009-02-25 01:55:31 +0000148 return jso;
Michael Clarkf0d08882007-03-13 08:26:18 +0000149}
150
Eric Haszlakiewicz5f4739e2012-10-18 17:10:09 -0500151int json_object_put(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000152{
Eric Haszlakiewicz38f421a2012-09-02 15:21:56 -0500153 if(jso)
154 {
155 jso->_ref_count--;
156 if(!jso->_ref_count)
157 {
158 if (jso->_user_delete)
159 jso->_user_delete(jso, jso->_userdata);
160 jso->_delete(jso);
Eric Haszlakiewicz5f4739e2012-10-18 17:10:09 -0500161 return 1;
Eric Haszlakiewicz38f421a2012-09-02 15:21:56 -0500162 }
163 }
Eric Haszlakiewicz5f4739e2012-10-18 17:10:09 -0500164 return 0;
Michael Clarkf0d08882007-03-13 08:26:18 +0000165}
166
167
168/* generic object construction and destruction parts */
169
Michael Clark266a3fd2009-02-25 01:55:31 +0000170static void json_object_generic_delete(struct json_object* jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000171{
172#ifdef REFCOUNT_DEBUG
Michael Clarkdfaf6702007-10-25 02:26:00 +0000173 MC_DEBUG("json_object_delete_%s: %p\n",
Eric Haszlakiewicz886c4fb2011-05-03 20:40:49 +0000174 json_type_to_name(jso->o_type), jso);
Michael Clark266a3fd2009-02-25 01:55:31 +0000175 lh_table_delete(json_object_table, jso);
Michael Clark4504df72007-03-13 08:26:20 +0000176#endif /* REFCOUNT_DEBUG */
Michael Clark266a3fd2009-02-25 01:55:31 +0000177 printbuf_free(jso->_pb);
178 free(jso);
Michael Clarkf0d08882007-03-13 08:26:18 +0000179}
180
181static struct json_object* json_object_new(enum json_type o_type)
182{
Michael Clarkaaec1ef2009-02-25 02:31:32 +0000183 struct json_object *jso;
184
185 jso = (struct json_object*)calloc(sizeof(struct json_object), 1);
Michael Clark266a3fd2009-02-25 01:55:31 +0000186 if(!jso) return NULL;
187 jso->o_type = o_type;
188 jso->_ref_count = 1;
189 jso->_delete = &json_object_generic_delete;
Michael Clarkf0d08882007-03-13 08:26:18 +0000190#ifdef REFCOUNT_DEBUG
Michael Clark266a3fd2009-02-25 01:55:31 +0000191 lh_table_insert(json_object_table, jso, jso);
Eric Haszlakiewicz886c4fb2011-05-03 20:40:49 +0000192 MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso);
Michael Clark4504df72007-03-13 08:26:20 +0000193#endif /* REFCOUNT_DEBUG */
Michael Clark266a3fd2009-02-25 01:55:31 +0000194 return jso;
Michael Clarkf0d08882007-03-13 08:26:18 +0000195}
196
197
198/* type checking functions */
199
Michael Clark266a3fd2009-02-25 01:55:31 +0000200int json_object_is_type(struct json_object *jso, enum json_type type)
Michael Clarkf0d08882007-03-13 08:26:18 +0000201{
Eric Haszlakiewiczaef439a2012-03-31 13:47:28 -0500202 if (!jso)
203 return (type == json_type_null);
Michael Clark266a3fd2009-02-25 01:55:31 +0000204 return (jso->o_type == type);
Michael Clarkf0d08882007-03-13 08:26:18 +0000205}
206
Michael Clark266a3fd2009-02-25 01:55:31 +0000207enum json_type json_object_get_type(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000208{
Eric Haszlakiewiczaef439a2012-03-31 13:47:28 -0500209 if (!jso)
210 return json_type_null;
Michael Clark266a3fd2009-02-25 01:55:31 +0000211 return jso->o_type;
Michael Clarkf0d08882007-03-13 08:26:18 +0000212}
213
Eric Haszlakiewicz38f421a2012-09-02 15:21:56 -0500214/* set a custom conversion to string */
215
216void json_object_set_serializer(json_object *jso,
217 json_object_to_json_string_fn to_string_func,
218 void *userdata,
219 json_object_delete_fn *user_delete)
220{
221 // First, clean up any previously existing user info
222 if (jso->_user_delete)
223 {
224 jso->_user_delete(jso, jso->_userdata);
225 }
226 jso->_userdata = NULL;
227 jso->_user_delete = NULL;
228
229 if (to_string_func == NULL)
230 {
231 // Reset to the standard serialization function
232 switch(jso->o_type)
233 {
234 case json_type_null:
235 jso->_to_json_string = NULL;
236 break;
237 case json_type_boolean:
238 jso->_to_json_string = &json_object_boolean_to_json_string;
239 break;
240 case json_type_double:
241 jso->_to_json_string = &json_object_double_to_json_string;
242 break;
243 case json_type_int:
244 jso->_to_json_string = &json_object_int_to_json_string;
245 break;
246 case json_type_object:
247 jso->_to_json_string = &json_object_object_to_json_string;
248 break;
249 case json_type_array:
250 jso->_to_json_string = &json_object_array_to_json_string;
251 break;
252 case json_type_string:
253 jso->_to_json_string = &json_object_string_to_json_string;
254 break;
255 }
256 return;
257 }
258
259 jso->_to_json_string = to_string_func;
260 jso->_userdata = userdata;
261 jso->_user_delete = user_delete;
262}
263
264
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500265/* extended conversion to string */
266
267const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
268{
269 if (!jso)
270 return "null";
271
272 if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
273 return NULL;
274
275 printbuf_reset(jso->_pb);
276
277 if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
278 return NULL;
279
280 return jso->_pb->buf;
281}
282
283/* backwards-compatible conversion to string */
Michael Clarkf0d08882007-03-13 08:26:18 +0000284
Michael Clark266a3fd2009-02-25 01:55:31 +0000285const char* json_object_to_json_string(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000286{
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500287 return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED);
Michael Clarkf0d08882007-03-13 08:26:18 +0000288}
289
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500290static void indent(struct printbuf *pb, int level, int flags)
291{
292 if (flags & JSON_C_TO_STRING_PRETTY)
293 {
294 printbuf_memset(pb, -1, ' ', level * 2);
295 }
296}
Michael Clarkf0d08882007-03-13 08:26:18 +0000297
298/* json_object_object */
299
Michael Clark266a3fd2009-02-25 01:55:31 +0000300static int json_object_object_to_json_string(struct json_object* jso,
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500301 struct printbuf *pb,
302 int level,
303 int flags)
Michael Clarkf0d08882007-03-13 08:26:18 +0000304{
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500305 int had_children = 0;
306 struct json_object_iter iter;
Michael Clark4504df72007-03-13 08:26:20 +0000307
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500308 sprintbuf(pb, "{" /*}*/);
309 if (flags & JSON_C_TO_STRING_PRETTY)
310 sprintbuf(pb, "\n");
311 json_object_object_foreachC(jso, iter)
312 {
313 if (had_children)
314 {
315 sprintbuf(pb, ",");
316 if (flags & JSON_C_TO_STRING_PRETTY)
317 sprintbuf(pb, "\n");
318 }
319 had_children = 1;
320 if (flags & JSON_C_TO_STRING_SPACED)
321 sprintbuf(pb, " ");
322 indent(pb, level+1, flags);
323 sprintbuf(pb, "\"");
324 json_escape_str(pb, iter.key, strlen(iter.key));
325 if (flags & JSON_C_TO_STRING_SPACED)
Michael Clark4504df72007-03-13 08:26:20 +0000326 sprintbuf(pb, "\": ");
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500327 else
328 sprintbuf(pb, "\":");
329 if(iter.val == NULL)
330 sprintbuf(pb, "null");
331 else
332 iter.val->_to_json_string(iter.val, pb, level+1,flags);
Michael Clark4504df72007-03-13 08:26:20 +0000333 }
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500334 if (flags & JSON_C_TO_STRING_PRETTY)
335 {
336 if (had_children)
337 sprintbuf(pb, "\n");
338 indent(pb,level,flags);
339 }
340 if (flags & JSON_C_TO_STRING_SPACED)
341 return sprintbuf(pb, /*{*/ " }");
342 else
343 return sprintbuf(pb, /*{*/ "}");
Michael Clarkf0d08882007-03-13 08:26:18 +0000344}
345
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500346
Michael Clarkf0d08882007-03-13 08:26:18 +0000347static void json_object_lh_entry_free(struct lh_entry *ent)
348{
349 free(ent->k);
350 json_object_put((struct json_object*)ent->v);
351}
352
Michael Clark266a3fd2009-02-25 01:55:31 +0000353static void json_object_object_delete(struct json_object* jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000354{
Michael Clark266a3fd2009-02-25 01:55:31 +0000355 lh_table_free(jso->o.c_object);
356 json_object_generic_delete(jso);
Michael Clarkf0d08882007-03-13 08:26:18 +0000357}
358
Michael Clarke8de0782009-02-25 01:45:00 +0000359struct json_object* json_object_new_object(void)
Michael Clarkf0d08882007-03-13 08:26:18 +0000360{
Michael Clark266a3fd2009-02-25 01:55:31 +0000361 struct json_object *jso = json_object_new(json_type_object);
362 if(!jso) return NULL;
363 jso->_delete = &json_object_object_delete;
364 jso->_to_json_string = &json_object_object_to_json_string;
365 jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES,
Michael Clarkf0d08882007-03-13 08:26:18 +0000366 NULL, &json_object_lh_entry_free);
Michael Clark266a3fd2009-02-25 01:55:31 +0000367 return jso;
Michael Clarkf0d08882007-03-13 08:26:18 +0000368}
369
Michael Clark266a3fd2009-02-25 01:55:31 +0000370struct lh_table* json_object_get_object(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000371{
Michael Clark266a3fd2009-02-25 01:55:31 +0000372 if(!jso) return NULL;
373 switch(jso->o_type) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000374 case json_type_object:
Michael Clark266a3fd2009-02-25 01:55:31 +0000375 return jso->o.c_object;
Michael Clarkf0d08882007-03-13 08:26:18 +0000376 default:
377 return NULL;
378 }
379}
380
Michael Clark266a3fd2009-02-25 01:55:31 +0000381void json_object_object_add(struct json_object* jso, const char *key,
Michael Clarkf0d08882007-03-13 08:26:18 +0000382 struct json_object *val)
383{
Eric Haszlakiewicz6988f532012-07-24 23:27:41 -0500384 // We lookup the entry and replace the value, rather than just deleting
385 // and re-adding it, so the existing key remains valid.
386 json_object *existing_value = NULL;
387 struct lh_entry *existing_entry;
388 existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key);
389 if (!existing_entry)
390 {
391 lh_table_insert(jso->o.c_object, strdup(key), val);
392 return;
393 }
394 existing_value = (void *)existing_entry->v;
395 if (existing_value)
396 json_object_put(existing_value);
397 existing_entry->v = val;
Michael Clarkf0d08882007-03-13 08:26:18 +0000398}
399
Greg Hazelcca74c62013-01-11 01:36:55 -0800400int json_object_object_length(struct json_object *jso)
401{
402 return lh_table_length(jso->o.c_object);
403}
404
Michael Clark266a3fd2009-02-25 01:55:31 +0000405struct json_object* json_object_object_get(struct json_object* jso, const char *key)
Michael Clarkf0d08882007-03-13 08:26:18 +0000406{
Eric Haszlakiewicze36e5622012-10-18 17:16:36 -0500407 struct json_object *result = NULL;
408 json_object_object_get_ex(jso, key, &result);
409 return result;
Keith Derrick69175862012-04-12 11:44:13 -0700410}
411
412json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value)
413{
Eric Haszlakiewicz5450bed2012-10-18 17:14:41 -0500414 if (value != NULL)
415 *value = NULL;
416
Eric Haszlakiewicze36e5622012-10-18 17:16:36 -0500417 if (NULL == jso)
418 return FALSE;
Keith Derrick69175862012-04-12 11:44:13 -0700419
Eric Haszlakiewicze36e5622012-10-18 17:16:36 -0500420 switch(jso->o_type)
421 {
422 case json_type_object:
423 return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value);
424 default:
425 if (value != NULL)
426 *value = NULL;
427 return FALSE;
428 }
Michael Clarkf0d08882007-03-13 08:26:18 +0000429}
430
Michael Clark266a3fd2009-02-25 01:55:31 +0000431void json_object_object_del(struct json_object* jso, const char *key)
Michael Clarkf0d08882007-03-13 08:26:18 +0000432{
Eric Haszlakiewicz5f4739e2012-10-18 17:10:09 -0500433 lh_table_delete(jso->o.c_object, key);
Michael Clarkf0d08882007-03-13 08:26:18 +0000434}
435
436
437/* json_object_boolean */
438
Michael Clark266a3fd2009-02-25 01:55:31 +0000439static int json_object_boolean_to_json_string(struct json_object* jso,
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500440 struct printbuf *pb,
441 int level,
442 int flags)
Michael Clarkf0d08882007-03-13 08:26:18 +0000443{
Michael Clark266a3fd2009-02-25 01:55:31 +0000444 if(jso->o.c_boolean) return sprintbuf(pb, "true");
Michael Clarkf0d08882007-03-13 08:26:18 +0000445 else return sprintbuf(pb, "false");
446}
447
Keith Derrick37e74672012-03-26 14:29:31 -0700448struct json_object* json_object_new_boolean(json_bool b)
Michael Clarkf0d08882007-03-13 08:26:18 +0000449{
Michael Clark266a3fd2009-02-25 01:55:31 +0000450 struct json_object *jso = json_object_new(json_type_boolean);
451 if(!jso) return NULL;
452 jso->_to_json_string = &json_object_boolean_to_json_string;
453 jso->o.c_boolean = b;
454 return jso;
Michael Clarkf0d08882007-03-13 08:26:18 +0000455}
456
Keith Derrick37e74672012-03-26 14:29:31 -0700457json_bool json_object_get_boolean(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000458{
Michael Clark266a3fd2009-02-25 01:55:31 +0000459 if(!jso) return FALSE;
460 switch(jso->o_type) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000461 case json_type_boolean:
Michael Clark266a3fd2009-02-25 01:55:31 +0000462 return jso->o.c_boolean;
Michael Clarkf0d08882007-03-13 08:26:18 +0000463 case json_type_int:
Michael Clarkc4dceae2010-10-06 16:39:20 +0000464 return (jso->o.c_int64 != 0);
Michael Clarkf0d08882007-03-13 08:26:18 +0000465 case json_type_double:
Michael Clark266a3fd2009-02-25 01:55:31 +0000466 return (jso->o.c_double != 0);
Michael Clarkf0d08882007-03-13 08:26:18 +0000467 case json_type_string:
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000468 return (jso->o.c_string.len != 0);
Michael Clarkf0d08882007-03-13 08:26:18 +0000469 default:
Michael Clark6f70e442009-04-27 08:19:27 +0000470 return FALSE;
Michael Clarkf0d08882007-03-13 08:26:18 +0000471 }
472}
473
474
475/* json_object_int */
476
Michael Clark266a3fd2009-02-25 01:55:31 +0000477static int json_object_int_to_json_string(struct json_object* jso,
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500478 struct printbuf *pb,
479 int level,
480 int flags)
Michael Clarkf0d08882007-03-13 08:26:18 +0000481{
Michael Clarkc4dceae2010-10-06 16:39:20 +0000482 return sprintbuf(pb, "%"PRId64, jso->o.c_int64);
483}
484
485struct json_object* json_object_new_int(int32_t i)
Michael Clarkf0d08882007-03-13 08:26:18 +0000486{
Michael Clark266a3fd2009-02-25 01:55:31 +0000487 struct json_object *jso = json_object_new(json_type_int);
488 if(!jso) return NULL;
489 jso->_to_json_string = &json_object_int_to_json_string;
ehaszla252669c2010-12-07 18:15:35 +0000490 jso->o.c_int64 = i;
Michael Clark266a3fd2009-02-25 01:55:31 +0000491 return jso;
Michael Clarkf0d08882007-03-13 08:26:18 +0000492}
493
Michael Clarkc4dceae2010-10-06 16:39:20 +0000494int32_t json_object_get_int(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000495{
John Arbash Meinel6a231e42012-02-01 09:27:49 +0100496 int64_t cint64;
497 enum json_type o_type;
498
Michael Clarkc4dceae2010-10-06 16:39:20 +0000499 if(!jso) return 0;
500
John Arbash Meinel6a231e42012-02-01 09:27:49 +0100501 o_type = jso->o_type;
502 cint64 = jso->o.c_int64;
Michael Clarkc4dceae2010-10-06 16:39:20 +0000503
504 if (o_type == json_type_string)
505 {
506 /*
507 * Parse strings into 64-bit numbers, then use the
508 * 64-to-32-bit number handling below.
509 */
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000510 if (json_parse_int64(jso->o.c_string.str, &cint64) != 0)
Michael Clarkc4dceae2010-10-06 16:39:20 +0000511 return 0; /* whoops, it didn't work. */
ehaszla252669c2010-12-07 18:15:35 +0000512 o_type = json_type_int;
Michael Clarkc4dceae2010-10-06 16:39:20 +0000513 }
514
Eric Haszlakiewicze2e16012011-05-03 20:39:07 +0000515 switch(o_type) {
Michael Clarkc4dceae2010-10-06 16:39:20 +0000516 case json_type_int:
Michael Clarkc4dceae2010-10-06 16:39:20 +0000517 /* Make sure we return the correct values for out of range numbers. */
518 if (cint64 <= INT32_MIN)
519 return INT32_MIN;
520 else if (cint64 >= INT32_MAX)
521 return INT32_MAX;
522 else
523 return (int32_t)cint64;
524 case json_type_double:
525 return (int32_t)jso->o.c_double;
526 case json_type_boolean:
527 return jso->o.c_boolean;
528 default:
529 return 0;
530 }
531}
532
533struct json_object* json_object_new_int64(int64_t i)
534{
ehaszla252669c2010-12-07 18:15:35 +0000535 struct json_object *jso = json_object_new(json_type_int);
Michael Clarkc4dceae2010-10-06 16:39:20 +0000536 if(!jso) return NULL;
ehaszla252669c2010-12-07 18:15:35 +0000537 jso->_to_json_string = &json_object_int_to_json_string;
Michael Clarkc4dceae2010-10-06 16:39:20 +0000538 jso->o.c_int64 = i;
539 return jso;
540}
541
542int64_t json_object_get_int64(struct json_object *jso)
543{
544 int64_t cint;
Michael Clarkf0d08882007-03-13 08:26:18 +0000545
Michael Clark266a3fd2009-02-25 01:55:31 +0000546 if(!jso) return 0;
547 switch(jso->o_type) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000548 case json_type_int:
Michael Clarkc4dceae2010-10-06 16:39:20 +0000549 return jso->o.c_int64;
Michael Clarkf0d08882007-03-13 08:26:18 +0000550 case json_type_double:
Michael Clarkc4dceae2010-10-06 16:39:20 +0000551 return (int64_t)jso->o.c_double;
Michael Clarkf0d08882007-03-13 08:26:18 +0000552 case json_type_boolean:
Michael Clark266a3fd2009-02-25 01:55:31 +0000553 return jso->o.c_boolean;
Michael Clarkf0d08882007-03-13 08:26:18 +0000554 case json_type_string:
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000555 if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint;
Michael Clarkf0d08882007-03-13 08:26:18 +0000556 default:
557 return 0;
558 }
559}
560
561
562/* json_object_double */
563
Michael Clark266a3fd2009-02-25 01:55:31 +0000564static int json_object_double_to_json_string(struct json_object* jso,
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500565 struct printbuf *pb,
566 int level,
567 int flags)
Michael Clarkf0d08882007-03-13 08:26:18 +0000568{
Remi Collet8c847962012-12-13 11:22:31 +0100569 char buf[128], *p, *q;
Remi Collet4014fe82012-12-13 11:16:03 +0100570 int size;
571
572 size = snprintf(buf, 128, "%f", jso->o.c_double);
573 p = strchr(buf, ',');
574 if (p) {
575 *p = '.';
Remi Collet8c847962012-12-13 11:22:31 +0100576 } else {
577 p = strchr(buf, '.');
578 }
Remi Collet32d149c2012-12-13 11:46:04 +0100579 if (p && (flags & JSON_C_TO_STRING_NOZERO)) {
Remi Collet8c847962012-12-13 11:22:31 +0100580 /* last useful digit, always keep 1 zero */
581 p++;
582 for (q=p ; *q ; q++) {
583 if (*q!='0') p=q;
584 }
585 /* drop trailing zeroes */
586 *(++p) = 0;
587 size = p-buf;
Remi Collet4014fe82012-12-13 11:16:03 +0100588 }
589 printbuf_memappend(pb, buf, size);
590 return size;
Michael Clarkf0d08882007-03-13 08:26:18 +0000591}
592
593struct json_object* json_object_new_double(double d)
594{
Michael Clark266a3fd2009-02-25 01:55:31 +0000595 struct json_object *jso = json_object_new(json_type_double);
596 if(!jso) return NULL;
597 jso->_to_json_string = &json_object_double_to_json_string;
598 jso->o.c_double = d;
599 return jso;
Michael Clarkf0d08882007-03-13 08:26:18 +0000600}
601
Michael Clark266a3fd2009-02-25 01:55:31 +0000602double json_object_get_double(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000603{
604 double cdouble;
605
Michael Clark266a3fd2009-02-25 01:55:31 +0000606 if(!jso) return 0.0;
607 switch(jso->o_type) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000608 case json_type_double:
Michael Clark266a3fd2009-02-25 01:55:31 +0000609 return jso->o.c_double;
Michael Clarkf0d08882007-03-13 08:26:18 +0000610 case json_type_int:
Michael Clarkc4dceae2010-10-06 16:39:20 +0000611 return jso->o.c_int64;
Michael Clarkf0d08882007-03-13 08:26:18 +0000612 case json_type_boolean:
Michael Clark266a3fd2009-02-25 01:55:31 +0000613 return jso->o.c_boolean;
Michael Clarkf0d08882007-03-13 08:26:18 +0000614 case json_type_string:
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000615 if(sscanf(jso->o.c_string.str, "%lf", &cdouble) == 1) return cdouble;
Michael Clarkf0d08882007-03-13 08:26:18 +0000616 default:
617 return 0.0;
618 }
619}
620
621
622/* json_object_string */
623
Michael Clark266a3fd2009-02-25 01:55:31 +0000624static int json_object_string_to_json_string(struct json_object* jso,
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500625 struct printbuf *pb,
626 int level,
627 int flags)
Michael Clarkf0d08882007-03-13 08:26:18 +0000628{
629 sprintbuf(pb, "\"");
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000630 json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len);
Michael Clarkf0d08882007-03-13 08:26:18 +0000631 sprintbuf(pb, "\"");
632 return 0;
633}
634
Michael Clark266a3fd2009-02-25 01:55:31 +0000635static void json_object_string_delete(struct json_object* jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000636{
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000637 free(jso->o.c_string.str);
Michael Clark266a3fd2009-02-25 01:55:31 +0000638 json_object_generic_delete(jso);
Michael Clarkf0d08882007-03-13 08:26:18 +0000639}
640
Michael Clark68cafad2009-01-06 22:56:57 +0000641struct json_object* json_object_new_string(const char *s)
Michael Clarkf0d08882007-03-13 08:26:18 +0000642{
Michael Clark266a3fd2009-02-25 01:55:31 +0000643 struct json_object *jso = json_object_new(json_type_string);
644 if(!jso) return NULL;
645 jso->_delete = &json_object_string_delete;
646 jso->_to_json_string = &json_object_string_to_json_string;
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000647 jso->o.c_string.str = strdup(s);
648 jso->o.c_string.len = strlen(s);
Michael Clark266a3fd2009-02-25 01:55:31 +0000649 return jso;
Michael Clarkf0d08882007-03-13 08:26:18 +0000650}
651
Michael Clark68cafad2009-01-06 22:56:57 +0000652struct json_object* json_object_new_string_len(const char *s, int len)
Michael Clarkf0d08882007-03-13 08:26:18 +0000653{
Michael Clark266a3fd2009-02-25 01:55:31 +0000654 struct json_object *jso = json_object_new(json_type_string);
655 if(!jso) return NULL;
656 jso->_delete = &json_object_string_delete;
657 jso->_to_json_string = &json_object_string_to_json_string;
Eric Haszlakiewicz4e4af932012-12-09 16:32:11 -0600658 jso->o.c_string.str = (char*)malloc(len + 1);
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000659 memcpy(jso->o.c_string.str, (void *)s, len);
Eric Haszlakiewicz4e4af932012-12-09 16:32:11 -0600660 jso->o.c_string.str[len] = '\0';
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000661 jso->o.c_string.len = len;
Michael Clark266a3fd2009-02-25 01:55:31 +0000662 return jso;
Michael Clarkf0d08882007-03-13 08:26:18 +0000663}
664
Michael Clark266a3fd2009-02-25 01:55:31 +0000665const char* json_object_get_string(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000666{
Michael Clark266a3fd2009-02-25 01:55:31 +0000667 if(!jso) return NULL;
668 switch(jso->o_type) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000669 case json_type_string:
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000670 return jso->o.c_string.str;
Michael Clarkf0d08882007-03-13 08:26:18 +0000671 default:
Michael Clark266a3fd2009-02-25 01:55:31 +0000672 return json_object_to_json_string(jso);
Michael Clarkf0d08882007-03-13 08:26:18 +0000673 }
674}
675
Jehiah Czebotarac601b52011-01-14 17:23:06 +0000676int json_object_get_string_len(struct json_object *jso) {
677 if(!jso) return 0;
678 switch(jso->o_type) {
679 case json_type_string:
680 return jso->o.c_string.len;
681 default:
682 return 0;
683 }
684}
685
Michael Clarkf0d08882007-03-13 08:26:18 +0000686
687/* json_object_array */
688
Michael Clark266a3fd2009-02-25 01:55:31 +0000689static int json_object_array_to_json_string(struct json_object* jso,
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500690 struct printbuf *pb,
691 int level,
692 int flags)
Michael Clarkf0d08882007-03-13 08:26:18 +0000693{
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500694 int had_children = 0;
695 int ii;
696 sprintbuf(pb, "[");
697 if (flags & JSON_C_TO_STRING_PRETTY)
698 sprintbuf(pb, "\n");
699 for(ii=0; ii < json_object_array_length(jso); ii++)
700 {
701 struct json_object *val;
702 if (had_children)
703 {
704 sprintbuf(pb, ",");
705 if (flags & JSON_C_TO_STRING_PRETTY)
706 sprintbuf(pb, "\n");
707 }
708 had_children = 1;
709 if (flags & JSON_C_TO_STRING_SPACED)
710 sprintbuf(pb, " ");
711 indent(pb, level + 1, flags);
712 val = json_object_array_get_idx(jso, ii);
713 if(val == NULL)
714 sprintbuf(pb, "null");
715 else
716 val->_to_json_string(val, pb, level+1, flags);
717 }
718 if (flags & JSON_C_TO_STRING_PRETTY)
719 {
720 if (had_children)
721 sprintbuf(pb, "\n");
722 indent(pb,level,flags);
723 }
Michael Clark4504df72007-03-13 08:26:20 +0000724
Eric Haszlakiewicz3fcffe12012-04-28 13:26:09 -0500725 if (flags & JSON_C_TO_STRING_SPACED)
726 return sprintbuf(pb, " ]");
727 else
728 return sprintbuf(pb, "]");
Michael Clarkf0d08882007-03-13 08:26:18 +0000729}
730
731static void json_object_array_entry_free(void *data)
732{
733 json_object_put((struct json_object*)data);
734}
735
Michael Clark266a3fd2009-02-25 01:55:31 +0000736static void json_object_array_delete(struct json_object* jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000737{
Michael Clark266a3fd2009-02-25 01:55:31 +0000738 array_list_free(jso->o.c_array);
739 json_object_generic_delete(jso);
Michael Clarkf0d08882007-03-13 08:26:18 +0000740}
741
Michael Clarke8de0782009-02-25 01:45:00 +0000742struct json_object* json_object_new_array(void)
Michael Clarkf0d08882007-03-13 08:26:18 +0000743{
Michael Clark266a3fd2009-02-25 01:55:31 +0000744 struct json_object *jso = json_object_new(json_type_array);
745 if(!jso) return NULL;
746 jso->_delete = &json_object_array_delete;
747 jso->_to_json_string = &json_object_array_to_json_string;
748 jso->o.c_array = array_list_new(&json_object_array_entry_free);
749 return jso;
Michael Clarkf0d08882007-03-13 08:26:18 +0000750}
751
Michael Clark266a3fd2009-02-25 01:55:31 +0000752struct array_list* json_object_get_array(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000753{
Michael Clark266a3fd2009-02-25 01:55:31 +0000754 if(!jso) return NULL;
755 switch(jso->o_type) {
Michael Clarkf0d08882007-03-13 08:26:18 +0000756 case json_type_array:
Michael Clark266a3fd2009-02-25 01:55:31 +0000757 return jso->o.c_array;
Michael Clarkf0d08882007-03-13 08:26:18 +0000758 default:
759 return NULL;
760 }
761}
762
Frederik Deweerdtc43871c2011-10-07 21:07:18 +0200763void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *))
764{
765 array_list_sort(jso->o.c_array, sort_fn);
766}
767
Michael Clark266a3fd2009-02-25 01:55:31 +0000768int json_object_array_length(struct json_object *jso)
Michael Clarkf0d08882007-03-13 08:26:18 +0000769{
Michael Clark266a3fd2009-02-25 01:55:31 +0000770 return array_list_length(jso->o.c_array);
Michael Clarkf0d08882007-03-13 08:26:18 +0000771}
772
Michael Clark266a3fd2009-02-25 01:55:31 +0000773int json_object_array_add(struct json_object *jso,struct json_object *val)
Michael Clarkf0d08882007-03-13 08:26:18 +0000774{
Michael Clark266a3fd2009-02-25 01:55:31 +0000775 return array_list_add(jso->o.c_array, val);
Michael Clarkf0d08882007-03-13 08:26:18 +0000776}
777
Michael Clark266a3fd2009-02-25 01:55:31 +0000778int json_object_array_put_idx(struct json_object *jso, int idx,
Michael Clarkf0d08882007-03-13 08:26:18 +0000779 struct json_object *val)
780{
Michael Clark266a3fd2009-02-25 01:55:31 +0000781 return array_list_put_idx(jso->o.c_array, idx, val);
Michael Clarkf0d08882007-03-13 08:26:18 +0000782}
783
Michael Clark266a3fd2009-02-25 01:55:31 +0000784struct json_object* json_object_array_get_idx(struct json_object *jso,
Michael Clarkf0d08882007-03-13 08:26:18 +0000785 int idx)
786{
Michael Clark266a3fd2009-02-25 01:55:31 +0000787 return (struct json_object*)array_list_get_idx(jso->o.c_array, idx);
Michael Clarkf0d08882007-03-13 08:26:18 +0000788}
789