1 : /*
2 : * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
3 : *
4 : * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
5 : * Michael Clark <michael@metaparadigm.com>
6 : *
7 : * This library is free software; you can redistribute it and/or modify
8 : * it under the terms of the MIT license. See COPYING for details.
9 : *
10 : */
11 :
12 : #include "config.h"
13 :
14 : #include <stdio.h>
15 : #include <stdlib.h>
16 : #include <string.h>
17 :
18 : #include "debug.h"
19 : #include "printbuf.h"
20 : #include "linkhash.h"
21 : #include "arraylist.h"
22 : #include "json_object.h"
23 : #include "json_object_private.h"
24 : #include "json_tokener.h"
25 :
26 : #if !HAVE_STRNDUP
27 : char* strndup(const char* str, size_t n);
28 : #endif /* !HAVE_STRNDUP */
29 :
30 : /* #define REFCOUNT_DEBUG 1 */
31 :
32 : char *json_number_chars = "0123456789.+-eE";
33 : char *json_hex_chars = "0123456789abcdef";
34 :
35 : #ifdef REFCOUNT_DEBUG
36 : static char* json_type_name[] = {
37 : "null",
38 : "boolean",
39 : "double",
40 : "int",
41 : "object",
42 : "array",
43 : "string",
44 : };
45 : #endif /* REFCOUNT_DEBUG */
46 :
47 : static void json_object_generic_delete(struct json_object* this);
48 : static struct json_object* json_object_new(enum json_type o_type);
49 :
50 :
51 : /* ref count debugging */
52 :
53 : #ifdef REFCOUNT_DEBUG
54 :
55 : static struct lh_table *json_object_table;
56 :
57 : static void json_object_init() __attribute__ ((constructor));
58 : static void json_object_init() {
59 : mc_debug("json_object_init: creating object table\n");
60 : json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
61 : }
62 :
63 : static void json_object_fini() __attribute__ ((destructor));
64 : static void json_object_fini() {
65 : struct lh_entry *ent;
66 : if(mc_get_debug() && json_object_table->count) {
67 : mc_debug("json_object_fini: %d referenced objects at exit\n",
68 : json_object_table->count);
69 : lh_foreach(json_object_table, ent) {
70 : struct json_object* obj = (struct json_object*)ent->v;
71 : mc_debug("\t%s:%p\n", json_type_name[obj->o_type], obj);
72 : }
73 : }
74 : mc_debug("json_object_fini: freeing object table\n");
75 : lh_table_free(json_object_table);
76 : }
77 : #endif /* REFCOUNT_DEBUG */
78 :
79 :
80 : /* string escaping */
81 :
82 60 : static int json_escape_str(struct printbuf *pb, char *str)
83 : {
84 60 : int pos = 0, start_offset = 0;
85 : unsigned char c;
86 : do {
87 481 : c = str[pos];
88 481 : switch(c) {
89 : case '\0':
90 60 : break;
91 : case '\b':
92 : case '\n':
93 : case '\r':
94 : case '\t':
95 : case '"':
96 : case '\\':
97 : case '/':
98 0 : if(pos - start_offset > 0)
99 0 : printbuf_memappend(pb, str + start_offset, pos - start_offset);
100 0 : if(c == '\b') printbuf_memappend(pb, "\\b", 2);
101 0 : else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
102 0 : else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
103 0 : else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
104 0 : else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
105 0 : else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
106 0 : else if(c == '/') printbuf_memappend(pb, "\\/", 2);
107 0 : start_offset = ++pos;
108 0 : break;
109 : default:
110 421 : if(c < ' ') {
111 0 : if(pos - start_offset > 0)
112 0 : printbuf_memappend(pb, str + start_offset, pos - start_offset);
113 0 : sprintbuf(pb, "\\u00%c%c",
114 0 : json_hex_chars[c >> 4],
115 0 : json_hex_chars[c & 0xf]);
116 0 : start_offset = ++pos;
117 421 : } else pos++;
118 : }
119 481 : } while(c);
120 60 : if(pos - start_offset > 0)
121 60 : printbuf_memappend(pb, str + start_offset, pos - start_offset);
122 60 : return 0;
123 : }
124 :
125 :
126 : /* reference counting */
127 :
128 315 : extern struct json_object* json_object_get(struct json_object *this)
129 : {
130 315 : if(this) {
131 315 : this->_ref_count++;
132 : }
133 315 : return this;
134 : }
135 :
136 1088 : extern void json_object_put(struct json_object *this)
137 : {
138 1088 : if(this) {
139 773 : this->_ref_count--;
140 773 : if(!this->_ref_count) this->_delete(this);
141 : }
142 1088 : }
143 :
144 :
145 : /* generic object construction and destruction parts */
146 :
147 458 : static void json_object_generic_delete(struct json_object* this)
148 : {
149 : #ifdef REFCOUNT_DEBUG
150 : mc_debug("json_object_delete_%s: %p\n",
151 : json_type_name[this->o_type], this);
152 : lh_table_delete(json_object_table, this);
153 : #endif /* REFCOUNT_DEBUG */
154 458 : printbuf_free(this->_pb);
155 458 : free(this);
156 458 : }
157 :
158 458 : static struct json_object* json_object_new(enum json_type o_type)
159 : {
160 458 : struct json_object *this = calloc(sizeof(struct json_object), 1);
161 458 : if(!this) return NULL;
162 458 : this->o_type = o_type;
163 458 : this->_ref_count = 1;
164 458 : this->_delete = &json_object_generic_delete;
165 : #ifdef REFCOUNT_DEBUG
166 : lh_table_insert(json_object_table, this, this);
167 : mc_debug("json_object_new_%s: %p\n", json_type_name[this->o_type], this);
168 : #endif /* REFCOUNT_DEBUG */
169 458 : return this;
170 : }
171 :
172 :
173 : /* type checking functions */
174 :
175 0 : int json_object_is_type(struct json_object *this, enum json_type type)
176 : {
177 0 : return (this->o_type == type);
178 : }
179 :
180 247 : enum json_type json_object_get_type(struct json_object *this)
181 : {
182 247 : return this->o_type;
183 : }
184 :
185 :
186 : /* json_object_to_json_string */
187 :
188 6 : char* json_object_to_json_string(struct json_object *this)
189 : {
190 6 : if(!this) return "null";
191 6 : if(!this->_pb) {
192 6 : if((this->_pb = printbuf_new()) == NULL) return NULL;
193 : } else {
194 0 : printbuf_reset(this->_pb);
195 : }
196 6 : if(this->_to_json_string(this, this->_pb) < 0) return NULL;
197 6 : return this->_pb->buf;
198 : }
199 :
200 :
201 : /* json_object_object */
202 :
203 18 : static int json_object_object_to_json_string(struct json_object* this,
204 : struct printbuf *pb)
205 : {
206 18 : int i=0;
207 : struct json_object_iter iter;
208 :
209 18 : iter.key = NULL;
210 18 : iter.val = NULL;
211 18 : iter.entry = NULL;
212 18 : sprintbuf(pb, "{");
213 :
214 : /* CAW: scope operator to make ANSI correctness */
215 : /* CAW: switched to json_object_object_foreachC which uses an iterator struct */
216 60 : json_object_object_foreachC(this, iter) {
217 42 : if(i) sprintbuf(pb, ",");
218 42 : sprintbuf(pb, " \"");
219 42 : json_escape_str(pb, iter.key);
220 42 : sprintbuf(pb, "\": ");
221 42 : if(iter.val == NULL) sprintbuf(pb, "null");
222 42 : else iter.val->_to_json_string(iter.val, pb);
223 42 : i++;
224 : }
225 :
226 18 : return sprintbuf(pb, " }");
227 : }
228 :
229 128 : static void json_object_lh_entry_free(struct lh_entry *ent)
230 : {
231 128 : free(ent->k);
232 128 : json_object_put((struct json_object*)ent->v);
233 128 : }
234 :
235 58 : static void json_object_object_delete(struct json_object* this)
236 : {
237 58 : lh_table_free(this->o.c_object);
238 58 : json_object_generic_delete(this);
239 58 : }
240 :
241 58 : struct json_object* json_object_new_object()
242 : {
243 58 : struct json_object *this = json_object_new(json_type_object);
244 58 : if(!this) return NULL;
245 58 : this->_delete = &json_object_object_delete;
246 58 : this->_to_json_string = &json_object_object_to_json_string;
247 58 : this->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTIRES,
248 : NULL, &json_object_lh_entry_free);
249 58 : return this;
250 : }
251 :
252 310 : struct lh_table* json_object_get_object(struct json_object *this)
253 : {
254 310 : if(!this) return NULL;
255 310 : switch(this->o_type) {
256 : case json_type_object:
257 310 : return this->o.c_object;
258 : default:
259 0 : return NULL;
260 : }
261 : }
262 :
263 128 : void json_object_object_add(struct json_object* this, const char *key,
264 : struct json_object *val)
265 : {
266 128 : lh_table_delete(this->o.c_object, (void* )key);
267 128 : lh_table_insert(this->o.c_object, strdup(key), val);
268 128 : }
269 :
270 0 : struct json_object* json_object_object_get(struct json_object* this, char *key)
271 : {
272 0 : return (struct json_object*) lh_table_lookup(this->o.c_object, key);
273 : }
274 :
275 0 : void json_object_object_del(struct json_object* this, char *key)
276 : {
277 0 : lh_table_delete(this->o.c_object, key);
278 0 : }
279 :
280 :
281 : /* json_object_boolean */
282 :
283 0 : static int json_object_boolean_to_json_string(struct json_object* this,
284 : struct printbuf *pb)
285 : {
286 0 : if(this->o.c_boolean) return sprintbuf(pb, "true");
287 0 : else return sprintbuf(pb, "false");
288 : }
289 :
290 0 : struct json_object* json_object_new_boolean(boolean b)
291 : {
292 0 : struct json_object *this = json_object_new(json_type_boolean);
293 0 : if(!this) return NULL;
294 0 : this->_to_json_string = &json_object_boolean_to_json_string;
295 0 : this->o.c_boolean = b;
296 0 : return this;
297 : }
298 :
299 0 : boolean json_object_get_boolean(struct json_object *this)
300 : {
301 0 : if(!this) return FALSE;
302 0 : switch(this->o_type) {
303 : case json_type_boolean:
304 0 : return this->o.c_boolean;
305 : case json_type_int:
306 0 : return (this->o.c_int != 0);
307 : case json_type_double:
308 0 : return (this->o.c_double != 0);
309 : case json_type_string:
310 0 : if(strlen(this->o.c_string)) return TRUE;
311 : default:
312 0 : return TRUE;
313 : }
314 : }
315 :
316 :
317 : /* json_object_int */
318 :
319 0 : static int json_object_int_to_json_string(struct json_object* this,
320 : struct printbuf *pb)
321 : {
322 0 : return sprintbuf(pb, "%d", this->o.c_int);
323 : }
324 :
325 0 : struct json_object* json_object_new_int(int i)
326 : {
327 0 : struct json_object *this = json_object_new(json_type_int);
328 0 : if(!this) return NULL;
329 0 : this->_to_json_string = &json_object_int_to_json_string;
330 0 : this->o.c_int = i;
331 0 : return this;
332 : }
333 :
334 0 : int json_object_get_int(struct json_object *this)
335 : {
336 : int cint;
337 :
338 0 : if(!this) return 0;
339 0 : switch(this->o_type) {
340 : case json_type_int:
341 0 : return this->o.c_int;
342 : case json_type_double:
343 0 : return (int)this->o.c_double;
344 : case json_type_boolean:
345 0 : return this->o.c_boolean;
346 : case json_type_string:
347 0 : if(sscanf(this->o.c_string, "%d", &cint) == 1) return cint;
348 : default:
349 0 : return 0;
350 : }
351 : }
352 :
353 :
354 : /* json_object_double */
355 :
356 64 : static int json_object_double_to_json_string(struct json_object* this,
357 : struct printbuf *pb)
358 : {
359 64 : return sprintbuf(pb, "%f", this->o.c_double);
360 : }
361 :
362 198 : struct json_object* json_object_new_double(double d)
363 : {
364 198 : struct json_object *this = json_object_new(json_type_double);
365 198 : if(!this) return NULL;
366 198 : this->_to_json_string = &json_object_double_to_json_string;
367 198 : this->o.c_double = d;
368 198 : return this;
369 : }
370 :
371 134 : double json_object_get_double(struct json_object *this)
372 : {
373 : double cdouble;
374 :
375 134 : if(!this) return 0.0;
376 134 : switch(this->o_type) {
377 : case json_type_double:
378 134 : return this->o.c_double;
379 : case json_type_int:
380 0 : return this->o.c_int;
381 : case json_type_boolean:
382 0 : return this->o.c_boolean;
383 : case json_type_string:
384 0 : if(sscanf(this->o.c_string, "%lf", &cdouble) == 1) return cdouble;
385 : default:
386 0 : return 0.0;
387 : }
388 : }
389 :
390 :
391 : /* json_object_string */
392 :
393 18 : static int json_object_string_to_json_string(struct json_object* this,
394 : struct printbuf *pb)
395 : {
396 18 : sprintbuf(pb, "\"");
397 18 : json_escape_str(pb, this->o.c_string);
398 18 : sprintbuf(pb, "\"");
399 18 : return 0;
400 : }
401 :
402 58 : static void json_object_string_delete(struct json_object* this)
403 : {
404 58 : free(this->o.c_string);
405 58 : json_object_generic_delete(this);
406 58 : }
407 :
408 58 : struct json_object* json_object_new_string(const char *s)
409 : {
410 58 : struct json_object *this = json_object_new(json_type_string);
411 58 : if(!this) return NULL;
412 58 : this->_delete = &json_object_string_delete;
413 58 : this->_to_json_string = &json_object_string_to_json_string;
414 58 : this->o.c_string = strdup(s);
415 58 : return this;
416 : }
417 :
418 0 : struct json_object* json_object_new_string_len(const char *s, int len)
419 : {
420 0 : struct json_object *this = json_object_new(json_type_string);
421 0 : if(!this) return NULL;
422 0 : this->_delete = &json_object_string_delete;
423 0 : this->_to_json_string = &json_object_string_to_json_string;
424 0 : this->o.c_string = strndup(s, len);
425 0 : return this;
426 : }
427 :
428 58 : char* json_object_get_string(struct json_object *this)
429 : {
430 58 : if(!this) return NULL;
431 58 : switch(this->o_type) {
432 : case json_type_string:
433 58 : return this->o.c_string;
434 : default:
435 0 : return json_object_to_json_string(this);
436 : }
437 : }
438 :
439 :
440 : /* json_object_array */
441 :
442 43 : static int json_object_array_to_json_string(struct json_object* this,
443 : struct printbuf *pb)
444 : {
445 : int i;
446 43 : sprintbuf(pb, "[");
447 138 : for(i=0; i < json_object_array_length(this); i++) {
448 : struct json_object *val;
449 95 : if(i) { sprintbuf(pb, ", "); }
450 43 : else { sprintbuf(pb, " "); }
451 :
452 95 : val = json_object_array_get_idx(this, i);
453 95 : if(val == NULL) { sprintbuf(pb, "null"); }
454 95 : else { val->_to_json_string(val, pb); }
455 : }
456 43 : return sprintbuf(pb, " ]");
457 : }
458 :
459 310 : static void json_object_array_entry_free(void *data)
460 : {
461 310 : json_object_put((struct json_object*)data);
462 310 : }
463 :
464 144 : static void json_object_array_delete(struct json_object* this)
465 : {
466 144 : array_list_free(this->o.c_array);
467 144 : json_object_generic_delete(this);
468 144 : }
469 :
470 144 : struct json_object* json_object_new_array()
471 : {
472 144 : struct json_object *this = json_object_new(json_type_array);
473 144 : if(!this) return NULL;
474 144 : this->_delete = &json_object_array_delete;
475 144 : this->_to_json_string = &json_object_array_to_json_string;
476 144 : this->o.c_array = array_list_new(&json_object_array_entry_free);
477 144 : return this;
478 : }
479 :
480 0 : struct array_list* json_object_get_array(struct json_object *this)
481 : {
482 0 : if(!this) return NULL;
483 0 : switch(this->o_type) {
484 : case json_type_array:
485 0 : return this->o.c_array;
486 : default:
487 0 : return NULL;
488 : }
489 : }
490 :
491 245 : int json_object_array_length(struct json_object *this)
492 : {
493 245 : return array_list_length(this->o.c_array);
494 : }
495 :
496 310 : int json_object_array_add(struct json_object *this,struct json_object *val)
497 : {
498 310 : return array_list_add(this->o.c_array, val);
499 : }
500 :
501 0 : int json_object_array_put_idx(struct json_object *this, int idx,
502 : struct json_object *val)
503 : {
504 0 : return array_list_put_idx(this->o.c_array, idx, val);
505 : }
506 :
507 316 : struct json_object* json_object_array_get_idx(struct json_object *this,
508 : int idx)
509 : {
510 316 : return (struct json_object*)array_list_get_idx(this->o.c_array, idx);
511 : }
512 :
|