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 586 : static int json_escape_str(struct printbuf *pb, char *str)
87 : {
88 586 : int pos = 0, start_offset = 0;
89 : unsigned char c;
90 : do {
91 4299 : c = str[pos];
92 4299 : switch(c) {
93 : case '\0':
94 586 : break;
95 : case '\b':
96 : case '\n':
97 : case '\r':
98 : case '\t':
99 : case '"':
100 : case '\\':
101 : case '/':
102 2 : if(pos - start_offset > 0)
103 2 : printbuf_memappend(pb, str + start_offset, pos - start_offset);
104 2 : if(c == '\b') printbuf_memappend(pb, "\\b", 2);
105 2 : else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
106 2 : else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
107 2 : else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
108 2 : 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 2 : start_offset = ++pos;
112 2 : break;
113 : default:
114 3711 : 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 0 : json_hex_chars[c >> 4],
119 0 : json_hex_chars[c & 0xf]);
120 0 : start_offset = ++pos;
121 3711 : } else pos++;
122 : }
123 4299 : } while(c);
124 586 : if(pos - start_offset > 0)
125 586 : printbuf_memappend(pb, str + start_offset, pos - start_offset);
126 586 : return 0;
127 : }
128 :
129 :
130 : /* reference counting */
131 :
132 19832 : extern struct json_object* json_object_get(struct json_object *jso)
133 : {
134 19832 : if(jso) {
135 19730 : jso->_ref_count++;
136 : }
137 19832 : return jso;
138 : }
139 :
140 60281 : extern void json_object_put(struct json_object *jso)
141 : {
142 60281 : if(jso) {
143 40265 : jso->_ref_count--;
144 40265 : if(!jso->_ref_count) jso->_delete(jso);
145 : }
146 60281 : }
147 :
148 :
149 : /* generic object construction and destruction parts */
150 :
151 20535 : static void json_object_generic_delete(struct json_object* jso)
152 : {
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 20535 : printbuf_free(jso->_pb);
159 20535 : free(jso);
160 20535 : }
161 :
162 20535 : static struct json_object* json_object_new(enum json_type o_type)
163 : {
164 : struct json_object *jso;
165 :
166 20535 : jso = (struct json_object*)calloc(sizeof(struct json_object), 1);
167 20535 : if(!jso) return NULL;
168 20535 : jso->o_type = o_type;
169 20535 : jso->_ref_count = 1;
170 20535 : 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 20535 : return jso;
176 : }
177 :
178 :
179 : /* type checking functions */
180 :
181 409 : int json_object_is_type(struct json_object *jso, enum json_type type)
182 : {
183 409 : return (jso->o_type == type);
184 : }
185 :
186 6714 : enum json_type json_object_get_type(struct json_object *jso)
187 : {
188 6714 : return jso->o_type;
189 : }
190 :
191 :
192 : /* json_object_to_json_string */
193 :
194 541 : const char* json_object_to_json_string(struct json_object *jso)
195 : {
196 541 : if(!jso) return "null";
197 541 : if(!jso->_pb) {
198 541 : if((jso->_pb = printbuf_new()) == NULL) return NULL;
199 : } else {
200 0 : printbuf_reset(jso->_pb);
201 : }
202 541 : if(jso->_to_json_string(jso, jso->_pb) < 0) return NULL;
203 541 : return jso->_pb->buf;
204 : }
205 :
206 :
207 : /* json_object_object */
208 :
209 121 : static int json_object_object_to_json_string(struct json_object* jso,
210 : struct printbuf *pb)
211 : {
212 121 : int i=0;
213 : struct json_object_iter iter;
214 121 : iter.key = NULL;
215 121 : sprintbuf(pb, "{");
216 :
217 : /* CAW: scope operator to make ANSI correctness */
218 : /* CAW: switched to json_object_object_foreachC which uses an iterator struct */
219 567 : json_object_object_foreachC(jso, iter) {
220 446 : if(i) sprintbuf(pb, ",");
221 446 : sprintbuf(pb, " \"");
222 446 : json_escape_str(pb, iter.key);
223 446 : sprintbuf(pb, "\": ");
224 446 : if(iter.val == NULL) sprintbuf(pb, "null");
225 446 : else iter.val->_to_json_string(iter.val, pb);
226 446 : i++;
227 : }
228 :
229 121 : return sprintbuf(pb, " }");
230 : }
231 :
232 5350 : static void json_object_lh_entry_free(struct lh_entry *ent)
233 : {
234 5350 : free(ent->k);
235 5350 : json_object_put((struct json_object*)ent->v);
236 5350 : }
237 :
238 1394 : static void json_object_object_delete(struct json_object* jso)
239 : {
240 1394 : lh_table_free(jso->o.c_object);
241 1394 : json_object_generic_delete(jso);
242 1394 : }
243 :
244 1394 : struct json_object* json_object_new_object(void)
245 : {
246 1394 : struct json_object *jso = json_object_new(json_type_object);
247 1394 : if(!jso) return NULL;
248 1394 : jso->_delete = &json_object_object_delete;
249 1394 : jso->_to_json_string = &json_object_object_to_json_string;
250 1394 : jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES,
251 : NULL, &json_object_lh_entry_free);
252 1394 : return jso;
253 : }
254 :
255 3772 : struct lh_table* json_object_get_object(struct json_object *jso)
256 : {
257 3772 : if(!jso) return NULL;
258 3772 : switch(jso->o_type) {
259 : case json_type_object:
260 3772 : return jso->o.c_object;
261 : default:
262 0 : return NULL;
263 : }
264 : }
265 :
266 5350 : void json_object_object_add(struct json_object* jso, const char *key,
267 : struct json_object *val)
268 : {
269 5350 : lh_table_delete(jso->o.c_object, key);
270 5350 : lh_table_insert(jso->o.c_object, strdup(key), val);
271 5350 : }
272 :
273 1480 : struct json_object* json_object_object_get(struct json_object* jso, const char *key)
274 : {
275 1480 : return (struct json_object*) lh_table_lookup(jso->o.c_object, key);
276 : }
277 :
278 0 : void json_object_object_del(struct json_object* jso, const char *key)
279 : {
280 0 : lh_table_delete(jso->o.c_object, key);
281 0 : }
282 :
283 :
284 : /* json_object_boolean */
285 :
286 0 : static int json_object_boolean_to_json_string(struct json_object* jso,
287 : struct printbuf *pb)
288 : {
289 0 : if(jso->o.c_boolean) return sprintbuf(pb, "true");
290 0 : else return sprintbuf(pb, "false");
291 : }
292 :
293 15 : struct json_object* json_object_new_boolean(boolean b)
294 : {
295 15 : struct json_object *jso = json_object_new(json_type_boolean);
296 15 : if(!jso) return NULL;
297 15 : jso->_to_json_string = &json_object_boolean_to_json_string;
298 15 : jso->o.c_boolean = b;
299 15 : return jso;
300 : }
301 :
302 0 : boolean json_object_get_boolean(struct json_object *jso)
303 : {
304 0 : if(!jso) return FALSE;
305 0 : switch(jso->o_type) {
306 : case json_type_boolean:
307 0 : return jso->o.c_boolean;
308 : case json_type_int:
309 0 : return (jso->o.c_int != 0);
310 : case json_type_double:
311 0 : return (jso->o.c_double != 0);
312 : case json_type_string:
313 0 : return (strlen(jso->o.c_string) != 0);
314 : default:
315 0 : return FALSE;
316 : }
317 : }
318 :
319 :
320 : /* json_object_int */
321 :
322 170 : static int json_object_int_to_json_string(struct json_object* jso,
323 : struct printbuf *pb)
324 : {
325 170 : return sprintbuf(pb, "%d", jso->o.c_int);
326 : }
327 :
328 826 : struct json_object* json_object_new_int(int i)
329 : {
330 826 : struct json_object *jso = json_object_new(json_type_int);
331 826 : if(!jso) return NULL;
332 826 : jso->_to_json_string = &json_object_int_to_json_string;
333 826 : jso->o.c_int = i;
334 826 : return jso;
335 : }
336 :
337 153 : int json_object_get_int(struct json_object *jso)
338 : {
339 : int cint;
340 :
341 153 : if(!jso) return 0;
342 153 : switch(jso->o_type) {
343 : case json_type_int:
344 152 : return jso->o.c_int;
345 : case json_type_double:
346 0 : return (int)jso->o.c_double;
347 : case json_type_boolean:
348 0 : return jso->o.c_boolean;
349 : case json_type_string:
350 1 : if(sscanf(jso->o.c_string, "%d", &cint) == 1) return cint;
351 : default:
352 0 : return 0;
353 : }
354 : }
355 :
356 :
357 : /* json_object_double */
358 :
359 : /* Begin: GDAL addition */
360 : /************************************************************************/
361 : /* json_OGRFormatDouble() */
362 : /* Copied & slightly adapted from ogrutils.cpp */
363 : /************************************************************************/
364 :
365 697 : static int json_OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
366 : char chDecimalSep, int nPrecision )
367 : {
368 : int i;
369 697 : int bHasTruncated = FALSE;
370 : char szFormat[16];
371 : int ret;
372 :
373 697 : sprintf(szFormat, "%%.%df", nPrecision);
374 :
375 697 : ret = snprintf(pszBuffer, nBufferLen, szFormat, dfVal);
376 : /* Windows CRT doesn't conform with C99 and return -1 when buffer is truncated */
377 697 : if (ret >= nBufferLen || ret == -1)
378 0 : return -1;
379 :
380 : while(TRUE)
381 : {
382 717 : int nCountBeforeDot = 0;
383 717 : int iDotPos = -1;
384 717 : i = 0;
385 13807 : while( pszBuffer[i] != '\0' )
386 : {
387 13090 : if ((pszBuffer[i] == '.' || pszBuffer[i] == ',') && chDecimalSep != '\0')
388 : {
389 717 : iDotPos = i;
390 717 : pszBuffer[i] = chDecimalSep;
391 : }
392 11656 : else if (iDotPos < 0 && pszBuffer[i] != '-')
393 993 : nCountBeforeDot ++;
394 12373 : i++;
395 : }
396 :
397 : /* -------------------------------------------------------------------- */
398 : /* Trim trailing 00000x's as they are likely roundoff error. */
399 : /* -------------------------------------------------------------------- */
400 717 : if( i > 10 && iDotPos >=0 )
401 : {
402 4148 : if (/* && pszBuffer[i-1] == '1' &&*/
403 717 : pszBuffer[i-2] == '0'
404 697 : && pszBuffer[i-3] == '0'
405 685 : && pszBuffer[i-4] == '0'
406 683 : && pszBuffer[i-5] == '0'
407 683 : && pszBuffer[i-6] == '0' )
408 : {
409 683 : pszBuffer[--i] = '\0';
410 : }
411 70 : else if( i - 8 > iDotPos && /* pszBuffer[i-1] == '1' */
412 : /* && pszBuffer[i-2] == '0' && */
413 34 : (nCountBeforeDot >= 4 || pszBuffer[i-3] == '0')
414 2 : && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '0')
415 0 : && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '0')
416 0 : && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '0')
417 0 : && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '0')
418 0 : && pszBuffer[i-8] == '0'
419 0 : && pszBuffer[i-9] == '0')
420 : {
421 0 : i -= 8;
422 0 : pszBuffer[i] = '\0';
423 : }
424 : }
425 :
426 : /* -------------------------------------------------------------------- */
427 : /* Trim trailing zeros. */
428 : /* -------------------------------------------------------------------- */
429 10162 : while( i > 2 && pszBuffer[i-1] == '0' && pszBuffer[i-2] != '.' )
430 : {
431 8728 : pszBuffer[--i] = '\0';
432 : }
433 :
434 : /* -------------------------------------------------------------------- */
435 : /* Detect trailing 99999X's as they are likely roundoff error. */
436 : /* -------------------------------------------------------------------- */
437 717 : if( !bHasTruncated &&
438 : i > 10 &&
439 : iDotPos >= 0 &&
440 : nPrecision >= 15)
441 : {
442 114 : if (/*pszBuffer[i-1] == '9' && */
443 32 : pszBuffer[i-2] == '9'
444 22 : && pszBuffer[i-3] == '9'
445 20 : && pszBuffer[i-4] == '9'
446 20 : && pszBuffer[i-5] == '9'
447 20 : && pszBuffer[i-6] == '9' )
448 : {
449 20 : snprintf(pszBuffer, nBufferLen, "%.9f", dfVal);
450 20 : bHasTruncated = TRUE;
451 20 : continue;
452 : }
453 12 : else if (i - 9 > iDotPos && /*pszBuffer[i-1] == '9' && */
454 : /*pszBuffer[i-2] == '9' && */
455 0 : (nCountBeforeDot >= 4 || pszBuffer[i-3] == '9')
456 0 : && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '9')
457 0 : && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '9')
458 0 : && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '9')
459 0 : && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '9')
460 0 : && pszBuffer[i-8] == '9'
461 0 : && pszBuffer[i-9] == '9')
462 : {
463 0 : sprintf(szFormat, "%%.%df", MIN(5,12 - nCountBeforeDot));
464 0 : snprintf(pszBuffer, nBufferLen, szFormat, dfVal);
465 0 : bHasTruncated = TRUE;
466 0 : continue;
467 : }
468 : }
469 :
470 : break;
471 20 : }
472 :
473 697 : return strlen(pszBuffer);
474 : }
475 : /* End: GDAL addition */
476 :
477 697 : static int json_object_double_to_json_string(struct json_object* jso,
478 : struct printbuf *pb)
479 : {
480 : /* GDAL modified */
481 : char szBuffer[75];
482 697 : int ret = json_OGRFormatDouble( szBuffer, sizeof(szBuffer), jso->o.c_double, '.',
483 697 : (jso->_precision < 0) ? 15 : jso->_precision );
484 697 : if (ret < 0)
485 0 : return ret;
486 697 : return printbuf_memappend(pb, szBuffer, ret);
487 : }
488 :
489 10483 : struct json_object* json_object_new_double(double d)
490 : {
491 10483 : struct json_object *jso = json_object_new(json_type_double);
492 10483 : if(!jso) return NULL;
493 10483 : jso->_to_json_string = &json_object_double_to_json_string;
494 10483 : jso->o.c_double = d;
495 10483 : jso->_precision = -1; /* GDAL addition */
496 10483 : return jso;
497 : }
498 :
499 : /* Begin: GDAL addition */
500 172 : struct json_object* json_object_new_double_with_precision(double d, int nPrecision)
501 : {
502 172 : struct json_object *jso = json_object_new(json_type_double);
503 172 : if(!jso) return NULL;
504 172 : jso->_to_json_string = &json_object_double_to_json_string;
505 172 : jso->o.c_double = d;
506 172 : jso->_precision = (nPrecision < 32) ? nPrecision : 32;
507 172 : return jso;
508 : }
509 : /* End: GDAL addition */
510 :
511 4093 : double json_object_get_double(struct json_object *jso)
512 : {
513 4093 : if(!jso) return 0.0;
514 4093 : switch(jso->o_type) {
515 : case json_type_double:
516 4090 : return jso->o.c_double;
517 : case json_type_int:
518 3 : return jso->o.c_int;
519 : case json_type_boolean:
520 0 : return jso->o.c_boolean;
521 : case json_type_string:
522 0 : return CPLAtof(jso->o.c_string);
523 : default:
524 0 : return 0.0;
525 : }
526 : }
527 :
528 :
529 : /* json_object_string */
530 :
531 140 : static int json_object_string_to_json_string(struct json_object* jso,
532 : struct printbuf *pb)
533 : {
534 140 : sprintbuf(pb, "\"");
535 140 : json_escape_str(pb, jso->o.c_string);
536 140 : sprintbuf(pb, "\"");
537 140 : return 0;
538 : }
539 :
540 2392 : static void json_object_string_delete(struct json_object* jso)
541 : {
542 2392 : free(jso->o.c_string);
543 2392 : json_object_generic_delete(jso);
544 2392 : }
545 :
546 2392 : struct json_object* json_object_new_string(const char *s)
547 : {
548 2392 : struct json_object *jso = json_object_new(json_type_string);
549 2392 : if(!jso) return NULL;
550 2392 : jso->_delete = &json_object_string_delete;
551 2392 : jso->_to_json_string = &json_object_string_to_json_string;
552 2392 : jso->o.c_string = strdup(s);
553 2392 : return jso;
554 : }
555 :
556 0 : struct json_object* json_object_new_string_len(const char *s, int len)
557 : {
558 0 : struct json_object *jso = json_object_new(json_type_string);
559 0 : if(!jso) return NULL;
560 0 : jso->_delete = &json_object_string_delete;
561 0 : jso->_to_json_string = &json_object_string_to_json_string;
562 0 : jso->o.c_string = strndup(s, len);
563 0 : return jso;
564 : }
565 :
566 1519 : const char* json_object_get_string(struct json_object *jso)
567 : {
568 1519 : if(!jso) return NULL;
569 1440 : switch(jso->o_type) {
570 : case json_type_string:
571 949 : return jso->o.c_string;
572 : default:
573 491 : return json_object_to_json_string(jso);
574 : }
575 : }
576 :
577 :
578 : /* json_object_array */
579 :
580 138 : static int json_object_array_to_json_string(struct json_object* jso,
581 : struct printbuf *pb)
582 : {
583 : int i;
584 138 : sprintbuf(pb, "[");
585 420 : for(i=0; i < json_object_array_length(jso); i++) {
586 : struct json_object *val;
587 282 : if(i) { sprintbuf(pb, ", "); }
588 128 : else { sprintbuf(pb, " "); }
589 :
590 282 : val = json_object_array_get_idx(jso, i);
591 282 : if(val == NULL) { sprintbuf(pb, "null"); }
592 279 : else { val->_to_json_string(val, pb); }
593 : }
594 138 : return sprintbuf(pb, " ]");
595 : }
596 :
597 14967 : static void json_object_array_entry_free(void *data)
598 : {
599 14967 : json_object_put((struct json_object*)data);
600 14967 : }
601 :
602 5253 : static void json_object_array_delete(struct json_object* jso)
603 : {
604 5253 : array_list_free(jso->o.c_array);
605 5253 : json_object_generic_delete(jso);
606 5253 : }
607 :
608 5253 : struct json_object* json_object_new_array(void)
609 : {
610 5253 : struct json_object *jso = json_object_new(json_type_array);
611 5253 : if(!jso) return NULL;
612 5253 : jso->_delete = &json_object_array_delete;
613 5253 : jso->_to_json_string = &json_object_array_to_json_string;
614 5253 : jso->o.c_array = array_list_new(&json_object_array_entry_free);
615 5253 : return jso;
616 : }
617 :
618 0 : struct array_list* json_object_get_array(struct json_object *jso)
619 : {
620 0 : if(!jso) return NULL;
621 0 : switch(jso->o_type) {
622 : case json_type_array:
623 0 : return jso->o.c_array;
624 : default:
625 0 : return NULL;
626 : }
627 : }
628 :
629 2804 : int json_object_array_length(struct json_object *jso)
630 : {
631 2804 : return array_list_length(jso->o.c_array);
632 : }
633 :
634 15018 : int json_object_array_add(struct json_object *jso,struct json_object *val)
635 : {
636 15018 : return array_list_add(jso->o.c_array, val);
637 : }
638 :
639 0 : int json_object_array_put_idx(struct json_object *jso, int idx,
640 : struct json_object *val)
641 : {
642 0 : return array_list_put_idx(jso->o.c_array, idx, val);
643 : }
644 :
645 6915 : struct json_object* json_object_array_get_idx(struct json_object *jso,
646 : int idx)
647 : {
648 6915 : return (struct json_object*)array_list_get_idx(jso->o.c_array, idx);
649 : }
650 :
|