4 * Copyright Metaparadigm Pte. Ltd. 2004.
5 * Michael Clark <michael@metaparadigm.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public (LGPL)
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details: http://www.gnu.org/
26 #include "arraylist.h"
27 #include "json_object.h"
28 #include "ossupport.h"
29 #include "json_object_private.h"
32 /* #define REFCOUNT_DEBUG */
34 char *json_number_chars = "0123456789.+-e";
35 char *json_hex_chars = "0123456789abcdef";
38 static char* json_type_name[] = {
49 static void json_object_generic_delete(struct json_object* this);
50 static struct json_object* json_object_new(enum json_type o_type);
53 /* ref count debugging */
57 static struct lh_table *json_object_table;
59 static void json_object_init() __attribute__ ((constructor));
60 static void json_object_init() {
61 mc_debug("json_object_init: creating object table\n");
62 json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
65 static void json_object_fini() __attribute__ ((destructor));
66 static void json_object_fini() {
68 if(mc_get_debug() && json_object_table->count) {
69 mc_debug("json_object_fini: %d referenced objects at exit\n",
70 json_object_table->count);
71 lh_foreach(json_object_table, ent) {
72 struct json_object* obj = (struct json_object*)ent->v;
73 mc_debug("\t%s:%p\n", json_type_name[obj->o_type], obj);
76 mc_debug("json_object_fini: freeing object table\n");
77 lh_table_free(json_object_table);
84 static int json_escape_str(struct printbuf *pb, char *str)
86 int pos = 0, start_offset = 0;
97 if(pos - start_offset > 0)
98 printbuf_memappend(pb, str + start_offset, pos - start_offset);
100 if(c == '\b') printbuf_memappend(pb, "\\b", 2);
101 else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
102 else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
103 else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
104 else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
106 start_offset = ++pos;
111 if(pos - start_offset > 0)
112 printbuf_memappend(pb, str + start_offset, pos - start_offset);
114 sprintbuf(pb, "\\u00%c%c",
115 json_hex_chars[c >> 4], json_hex_chars[c & 0xf]);
117 start_offset = ++pos;
123 if(pos - start_offset > 0)
124 printbuf_memappend(pb, str + start_offset, pos - start_offset);
130 /* reference counting */
132 extern struct json_object* json_object_get(struct json_object *this)
140 extern void json_object_put(struct json_object *this)
144 if(!this->_ref_count) this->_delete(this);
149 /* generic object construction and destruction parts */
151 static void json_object_generic_delete(struct json_object* this)
153 #ifdef REFCOUNT_DEBUG
154 mc_debug("json_object_delete_%s: %p\n",
155 json_type_name[this->o_type], this);
156 lh_table_delete(json_object_table, this);
158 printbuf_free(this->_pb);
162 static struct json_object* json_object_new(enum json_type o_type)
164 struct json_object *this = calloc(sizeof(struct json_object), 1);
165 if(!this) return NULL;
166 this->o_type = o_type;
167 this->_ref_count = 1;
168 this->_delete = &json_object_generic_delete;
169 #ifdef REFCOUNT_DEBUG
170 lh_table_insert(json_object_table, this, this);
171 mc_debug("json_object_new_%s: %p\n", json_type_name[this->o_type], this);
177 /* type checking functions */
179 int json_object_is_type(struct json_object *this, enum json_type type)
181 return (this->o_type == type);
184 enum json_type json_object_get_type(struct json_object *this)
190 /* json_object_to_json_string */
192 char* json_object_to_json_string(struct json_object *this)
194 if(!this) return "null";
196 if(!(this->_pb = printbuf_new())) return NULL;
198 printbuf_reset(this->_pb);
200 if(this->_to_json_string(this, this->_pb) < 0) return NULL;
201 return this->_pb->buf;
205 /* json_object_object */
207 static int json_object_object_to_json_string(struct json_object* this,
212 json_object_object_foreach(this, key, val) {
213 if(i) sprintbuf(pb, ",");
214 sprintbuf(pb, " \"");
215 json_escape_str(pb, key);
216 sprintbuf(pb, "\": ");
217 if(val == NULL) sprintbuf(pb, "null");
218 else val->_to_json_string(val, pb);
221 return sprintbuf(pb, " }");
224 static void json_object_lh_entry_free(struct lh_entry *ent)
227 json_object_put((struct json_object*)ent->v);
230 static void json_object_object_delete(struct json_object* this)
232 lh_table_free(this->o.c_object);
233 json_object_generic_delete(this);
236 struct json_object* json_object_new_object()
238 struct json_object *this = json_object_new(json_type_object);
239 if(!this) return NULL;
240 this->_delete = &json_object_object_delete;
241 this->_to_json_string = &json_object_object_to_json_string;
242 this->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTIRES,
243 NULL, &json_object_lh_entry_free);
247 struct lh_table* json_object_get_object(struct json_object *this)
249 if(!this) return NULL;
250 switch(this->o_type) {
251 case json_type_object:
252 return this->o.c_object;
258 void json_object_object_add(struct json_object* this, char *key,
259 struct json_object *val)
261 lh_table_delete(this->o.c_object, key);
262 lh_table_insert(this->o.c_object, strdup(key), val);
265 struct json_object* json_object_object_get(struct json_object* this, char *key)
267 return (struct json_object*) lh_table_lookup(this->o.c_object, key);
270 void json_object_object_del(struct json_object* this, char *key)
272 lh_table_delete(this->o.c_object, key);
276 /* json_object_boolean */
278 static int json_object_boolean_to_json_string(struct json_object* this,
281 if(this->o.c_boolean) return sprintbuf(pb, "true");
282 else return sprintbuf(pb, "false");
285 struct json_object* json_object_new_boolean(boolean b)
287 struct json_object *this = json_object_new(json_type_boolean);
288 if(!this) return NULL;
289 this->_to_json_string = &json_object_boolean_to_json_string;
290 this->o.c_boolean = b;
294 boolean json_object_get_boolean(struct json_object *this)
296 if(!this) return FALSE;
297 switch(this->o_type) {
298 case json_type_boolean:
299 return this->o.c_boolean;
301 return (this->o.c_int != 0);
302 case json_type_double:
303 return (this->o.c_double != 0);
304 case json_type_string:
305 if(strlen(this->o.c_string)) return TRUE;
312 /* json_object_int */
314 static int json_object_int_to_json_string(struct json_object* this,
317 return sprintbuf(pb, "%d", this->o.c_int);
320 struct json_object* json_object_new_int(int i)
322 struct json_object *this = json_object_new(json_type_int);
323 if(!this) return NULL;
324 this->_to_json_string = &json_object_int_to_json_string;
329 int json_object_get_int(struct json_object *this)
334 switch(this->o_type) {
336 return this->o.c_int;
337 case json_type_double:
338 return this->o.c_double;
339 case json_type_boolean:
340 return this->o.c_boolean;
341 case json_type_string:
342 if(sscanf(this->o.c_string, "%d", &cint) == 1) return cint;
349 /* json_object_double */
351 static int json_object_double_to_json_string(struct json_object* this,
354 return sprintbuf(pb, "%lf", this->o.c_double);
357 struct json_object* json_object_new_double(double d)
359 struct json_object *this = json_object_new(json_type_double);
360 if(!this) return NULL;
361 this->_to_json_string = &json_object_double_to_json_string;
362 this->o.c_double = d;
366 double json_object_get_double(struct json_object *this)
370 if(!this) return 0.0;
371 switch(this->o_type) {
372 case json_type_double:
373 return this->o.c_double;
375 return this->o.c_int;
376 case json_type_boolean:
377 return this->o.c_boolean;
378 case json_type_string:
379 if(sscanf(this->o.c_string, "%lf", &cdouble) == 1) return cdouble;
386 /* json_object_string */
388 static int json_object_string_to_json_string(struct json_object* this,
392 json_escape_str(pb, this->o.c_string);
397 static void json_object_string_delete(struct json_object* this)
399 free(this->o.c_string);
400 json_object_generic_delete(this);
403 struct json_object* json_object_new_string(char *s)
405 struct json_object *this = json_object_new(json_type_string);
406 if(!this) return NULL;
407 this->_delete = &json_object_string_delete;
408 this->_to_json_string = &json_object_string_to_json_string;
409 this->o.c_string = strdup(s);
413 struct json_object* json_object_new_string_len(char *s, int len)
415 struct json_object *this = json_object_new(json_type_string);
416 if(!this) return NULL;
417 this->_delete = &json_object_string_delete;
418 this->_to_json_string = &json_object_string_to_json_string;
419 this->o.c_string = strndup(s, len);
423 char* json_object_get_string(struct json_object *this)
425 if(!this) return NULL;
426 switch(this->o_type) {
427 case json_type_string:
428 return this->o.c_string;
430 return json_object_to_json_string(this);
435 /* json_object_array */
437 static int json_object_array_to_json_string(struct json_object* this,
441 for(int i=0; i < json_object_array_length(this); i++) {
442 if(i) sprintbuf(pb, ", ");
443 else sprintbuf(pb, " ");
444 struct json_object *val = json_object_array_get_idx(this, i);
445 if(val == NULL) sprintbuf(pb, "null");
446 else val->_to_json_string(val, pb);
448 return sprintbuf(pb, " ]");
451 static void json_object_array_entry_free(void *data)
453 json_object_put((struct json_object*)data);
456 static void json_object_array_delete(struct json_object* this)
458 array_list_free(this->o.c_array);
459 json_object_generic_delete(this);
462 struct json_object* json_object_new_array()
464 struct json_object *this = json_object_new(json_type_array);
465 if(!this) return NULL;
466 this->_delete = &json_object_array_delete;
467 this->_to_json_string = &json_object_array_to_json_string;
468 this->o.c_array = array_list_new(&json_object_array_entry_free);
472 struct array_list* json_object_get_array(struct json_object *this)
474 if(!this) return NULL;
475 switch(this->o_type) {
476 case json_type_array:
477 return this->o.c_array;
483 int json_object_array_length(struct json_object *this)
485 return array_list_length(this->o.c_array);
488 int json_object_array_add(struct json_object *this,struct json_object *val)
490 return array_list_add(this->o.c_array, val);
493 int json_object_array_put_idx(struct json_object *this, int idx,
494 struct json_object *val)
496 return array_list_put_idx(this->o.c_array, idx, val);
499 struct json_object* json_object_array_get_idx(struct json_object *this,
502 return (struct json_object*)array_list_get_idx(this->o.c_array, idx);