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/
23 #include "libjson/debug.h"
24 #include "libjson/printbuf.h"
25 #include "libjson/linkhash.h"
26 #include "libjson/arraylist.h"
27 #include "libjson/json_object.h"
28 #include "libjson/ossupport.h"
29 #include "libjson/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;
96 if(pos - start_offset > 0)
97 printbuf_memappend(pb, str + start_offset, pos - start_offset);
98 if(c == '\b') printbuf_memappend(pb, "\\b", 2);
99 else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
100 else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
101 else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
102 else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
103 start_offset = ++pos;
107 if(pos - start_offset > 0)
108 printbuf_memappend(pb, str + start_offset, pos - start_offset);
109 sprintbuf(pb, "\\u00%c%c",
110 json_hex_chars[c >> 4],
111 json_hex_chars[c & 0xf]);
112 start_offset = ++pos;
116 if(pos - start_offset > 0)
117 printbuf_memappend(pb, str + start_offset, pos - start_offset);
122 /* reference counting */
124 extern struct json_object* json_object_get(struct json_object *this)
132 extern void json_object_put(struct json_object *this)
136 if(!this->_ref_count) this->_delete(this);
141 /* generic object construction and destruction parts */
143 static void json_object_generic_delete(struct json_object* this)
145 #ifdef REFCOUNT_DEBUG
146 mc_debug("json_object_delete_%s: %p\n",
147 json_type_name[this->o_type], this);
148 lh_table_delete(json_object_table, this);
150 printbuf_free(this->_pb);
154 static struct json_object* json_object_new(enum json_type o_type)
156 struct json_object *this = calloc(sizeof(struct json_object), 1);
157 if(!this) return NULL;
158 this->o_type = o_type;
159 this->_ref_count = 1;
160 this->_delete = &json_object_generic_delete;
161 #ifdef REFCOUNT_DEBUG
162 lh_table_insert(json_object_table, this, this);
163 mc_debug("json_object_new_%s: %p\n", json_type_name[this->o_type], this);
169 /* type checking functions */
171 int json_object_is_type(struct json_object *this, enum json_type type)
173 return (this->o_type == type);
176 enum json_type json_object_get_type(struct json_object *this)
182 /* json_object_to_json_string */
184 char* json_object_to_json_string(struct json_object *this)
186 if(!this) return "null";
188 if(!(this->_pb = printbuf_new())) return NULL;
190 printbuf_reset(this->_pb);
192 if(this->_to_json_string(this, this->_pb) < 0) return NULL;
193 return this->_pb->buf;
197 /* json_object_object */
199 static int json_object_object_to_json_string(struct json_object* this,
204 json_object_object_foreach(this, key, val) {
205 if(i) sprintbuf(pb, ",");
206 sprintbuf(pb, " \"");
207 json_escape_str(pb, key);
208 sprintbuf(pb, "\": ");
209 if(val == NULL) sprintbuf(pb, "null");
210 else val->_to_json_string(val, pb);
213 return sprintbuf(pb, " }");
216 static void json_object_lh_entry_free(struct lh_entry *ent)
219 json_object_put((struct json_object*)ent->v);
222 static void json_object_object_delete(struct json_object* this)
224 lh_table_free(this->o.c_object);
225 json_object_generic_delete(this);
228 struct json_object* json_object_new_object()
230 struct json_object *this = json_object_new(json_type_object);
231 if(!this) return NULL;
232 this->_delete = &json_object_object_delete;
233 this->_to_json_string = &json_object_object_to_json_string;
234 this->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTIRES,
235 NULL, &json_object_lh_entry_free);
239 struct lh_table* json_object_get_object(struct json_object *this)
241 if(!this) return NULL;
242 switch(this->o_type) {
243 case json_type_object:
244 return this->o.c_object;
250 void json_object_object_add(struct json_object* this, char *key,
251 struct json_object *val)
253 lh_table_delete(this->o.c_object, key);
254 lh_table_insert(this->o.c_object, strdup(key), val);
257 struct json_object* json_object_object_get(struct json_object* this, char *key)
259 return (struct json_object*) lh_table_lookup(this->o.c_object, key);
262 void json_object_object_del(struct json_object* this, char *key)
264 lh_table_delete(this->o.c_object, key);
268 /* json_object_boolean */
270 static int json_object_boolean_to_json_string(struct json_object* this,
273 if(this->o.c_boolean) return sprintbuf(pb, "true");
274 else return sprintbuf(pb, "false");
277 struct json_object* json_object_new_boolean(boolean b)
279 struct json_object *this = json_object_new(json_type_boolean);
280 if(!this) return NULL;
281 this->_to_json_string = &json_object_boolean_to_json_string;
282 this->o.c_boolean = b;
286 boolean json_object_get_boolean(struct json_object *this)
288 if(!this) return FALSE;
289 switch(this->o_type) {
290 case json_type_boolean:
291 return this->o.c_boolean;
293 return (this->o.c_int != 0);
294 case json_type_double:
295 return (this->o.c_double != 0);
296 case json_type_string:
297 if(strlen(this->o.c_string)) return TRUE;
304 /* json_object_int */
306 static int json_object_int_to_json_string(struct json_object* this,
309 return sprintbuf(pb, "%d", this->o.c_int);
312 struct json_object* json_object_new_int(int i)
314 struct json_object *this = json_object_new(json_type_int);
315 if(!this) return NULL;
316 this->_to_json_string = &json_object_int_to_json_string;
321 int json_object_get_int(struct json_object *this)
326 switch(this->o_type) {
328 return this->o.c_int;
329 case json_type_double:
330 return this->o.c_double;
331 case json_type_boolean:
332 return this->o.c_boolean;
333 case json_type_string:
334 if(sscanf(this->o.c_string, "%d", &cint) == 1) return cint;
341 /* json_object_double */
343 static int json_object_double_to_json_string(struct json_object* this,
346 return sprintbuf(pb, "%lf", this->o.c_double);
349 struct json_object* json_object_new_double(double d)
351 struct json_object *this = json_object_new(json_type_double);
352 if(!this) return NULL;
353 this->_to_json_string = &json_object_double_to_json_string;
354 this->o.c_double = d;
358 double json_object_get_double(struct json_object *this)
362 if(!this) return 0.0;
363 switch(this->o_type) {
364 case json_type_double:
365 return this->o.c_double;
367 return this->o.c_int;
368 case json_type_boolean:
369 return this->o.c_boolean;
370 case json_type_string:
371 if(sscanf(this->o.c_string, "%lf", &cdouble) == 1) return cdouble;
378 /* json_object_string */
380 static int json_object_string_to_json_string(struct json_object* this,
384 json_escape_str(pb, this->o.c_string);
389 static void json_object_string_delete(struct json_object* this)
391 free(this->o.c_string);
392 json_object_generic_delete(this);
395 struct json_object* json_object_new_string(char *s)
397 struct json_object *this = json_object_new(json_type_string);
398 if(!this) return NULL;
399 this->_delete = &json_object_string_delete;
400 this->_to_json_string = &json_object_string_to_json_string;
401 this->o.c_string = strdup(s);
405 struct json_object* json_object_new_string_len(char *s, int len)
407 struct json_object *this = json_object_new(json_type_string);
408 if(!this) return NULL;
409 this->_delete = &json_object_string_delete;
410 this->_to_json_string = &json_object_string_to_json_string;
411 this->o.c_string = strndup(s, len);
415 char* json_object_get_string(struct json_object *this)
417 if(!this) return NULL;
418 switch(this->o_type) {
419 case json_type_string:
420 return this->o.c_string;
422 return json_object_to_json_string(this);
427 /* json_object_array */
429 static int json_object_array_to_json_string(struct json_object* this,
433 for(int i=0; i < json_object_array_length(this); i++) {
434 if(i) sprintbuf(pb, ", ");
435 else sprintbuf(pb, " ");
436 struct json_object *val = json_object_array_get_idx(this, i);
437 if(val == NULL) sprintbuf(pb, "null");
438 else val->_to_json_string(val, pb);
440 return sprintbuf(pb, " ]");
443 static void json_object_array_entry_free(void *data)
445 json_object_put((struct json_object*)data);
448 static void json_object_array_delete(struct json_object* this)
450 array_list_free(this->o.c_array);
451 json_object_generic_delete(this);
454 struct json_object* json_object_new_array()
456 struct json_object *this = json_object_new(json_type_array);
457 if(!this) return NULL;
458 this->_delete = &json_object_array_delete;
459 this->_to_json_string = &json_object_array_to_json_string;
460 this->o.c_array = array_list_new(&json_object_array_entry_free);
464 struct array_list* json_object_get_array(struct json_object *this)
466 if(!this) return NULL;
467 switch(this->o_type) {
468 case json_type_array:
469 return this->o.c_array;
475 int json_object_array_length(struct json_object *this)
477 return array_list_length(this->o.c_array);
480 int json_object_array_add(struct json_object *this,struct json_object *val)
482 return array_list_add(this->o.c_array, val);
485 int json_object_array_put_idx(struct json_object *this, int idx,
486 struct json_object *val)
488 return array_list_put_idx(this->o.c_array, idx, val);
491 struct json_object* json_object_array_get_idx(struct json_object *this,
494 return (struct json_object*)array_list_get_idx(this->o.c_array, idx);