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