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 591 : static int json_escape_str(struct printbuf *pb, char *str)
87 : {
88 591 : int pos = 0, start_offset = 0;
89 : unsigned char c;
90 : do {
91 4352 : c = str[pos];
92 4352 : switch(c) {
93 : case '\0':
94 591 : 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 3759 : 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 3759 : } else pos++;
122 : }
123 4352 : } while(c);
124 591 : if(pos - start_offset > 0)
125 591 : printbuf_memappend(pb, str + start_offset, pos - start_offset);
126 591 : return 0;
127 : }
128 :
129 :
130 : /* reference counting */
131 :
132 19870 : extern struct json_object* json_object_get(struct json_object *jso)
133 : {
134 19870 : if(jso) {
135 19768 : jso->_ref_count++;
136 : }
137 19870 : return jso;
138 : }
139 :
140 60399 : extern void json_object_put(struct json_object *jso)
141 : {
142 60399 : if(jso) {
143 40345 : jso->_ref_count--;
144 40345 : if(!jso->_ref_count) jso->_delete(jso);
145 : }
146 60399 : }
147 :
148 :
149 : /* generic object construction and destruction parts */
150 :
151 20577 : 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 20577 : printbuf_free(jso->_pb);
159 20577 : free(jso);
160 20577 : }
161 :
162 20577 : static struct json_object* json_object_new(enum json_type o_type)
163 : {
164 : struct json_object *jso;
165 :
166 20577 : jso = (struct json_object*)calloc(sizeof(struct json_object), 1);
167 20577 : if(!jso) return NULL;
168 20577 : jso->o_type = o_type;
169 20577 : jso->_ref_count = 1;
170 20577 : 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 20577 : 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 6726 : enum json_type json_object_get_type(struct json_object *jso)
187 : {
188 6726 : return jso->o_type;
189 : }
190 :
191 :
192 : /* json_object_to_json_string */
193 :
194 542 : const char* json_object_to_json_string(struct json_object *jso)
195 : {
196 542 : if(!jso) return "null";
197 542 : if(!jso->_pb) {
198 542 : if((jso->_pb = printbuf_new()) == NULL) return NULL;
199 : } else {
200 0 : printbuf_reset(jso->_pb);
201 : }
202 542 : if(jso->_to_json_string(jso, jso->_pb) < 0) return NULL;
203 542 : return jso->_pb->buf;
204 : }
205 :
206 :
207 : /* json_object_object */
208 :
209 123 : static int json_object_object_to_json_string(struct json_object* jso,
210 : struct printbuf *pb)
211 : {
212 123 : int i=0;
213 : struct json_object_iter iter;
214 123 : iter.key = NULL;
215 123 : 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 572 : json_object_object_foreachC(jso, iter) {
220 449 : if(i) sprintbuf(pb, ",");
221 449 : sprintbuf(pb, " \"");
222 449 : json_escape_str(pb, iter.key);
223 449 : sprintbuf(pb, "\": ");
224 449 : if(iter.val == NULL) sprintbuf(pb, "null");
225 449 : else iter.val->_to_json_string(iter.val, pb);
226 449 : i++;
227 : }
228 :
229 123 : return sprintbuf(pb, " }");
230 : }
231 :
232 5372 : static void json_object_lh_entry_free(struct lh_entry *ent)
233 : {
234 5372 : free(ent->k);
235 5372 : json_object_put((struct json_object*)ent->v);
236 5372 : }
237 :
238 1405 : static void json_object_object_delete(struct json_object* jso)
239 : {
240 1405 : lh_table_free(jso->o.c_object);
241 1405 : json_object_generic_delete(jso);
242 1405 : }
243 :
244 1405 : struct json_object* json_object_new_object(void)
245 : {
246 1405 : struct json_object *jso = json_object_new(json_type_object);
247 1405 : if(!jso) return NULL;
248 1405 : jso->_delete = &json_object_object_delete;
249 1405 : jso->_to_json_string = &json_object_object_to_json_string;
250 1405 : jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES,
251 : NULL, &json_object_lh_entry_free);
252 1405 : return jso;
253 : }
254 :
255 3846 : struct lh_table* json_object_get_object(struct json_object *jso)
256 : {
257 3846 : if(!jso) return NULL;
258 3846 : switch(jso->o_type) {
259 : case json_type_object:
260 3846 : return jso->o.c_object;
261 : default:
262 0 : return NULL;
263 : }
264 : }
265 :
266 5372 : void json_object_object_add(struct json_object* jso, const char *key,
267 : struct json_object *val)
268 : {
269 5372 : lh_table_delete(jso->o.c_object, key);
270 5372 : lh_table_insert(jso->o.c_object, strdup(key), val);
271 5372 : }
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 10499 : struct json_object* json_object_new_double(double d)
490 : {
491 10499 : struct json_object *jso = json_object_new(json_type_double);
492 10499 : if(!jso) return NULL;
493 10499 : jso->_to_json_string = &json_object_double_to_json_string;
494 10499 : jso->o.c_double = d;
495 10499 : jso->_precision = -1; /* GDAL addition */
496 10499 : 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 4097 : double json_object_get_double(struct json_object *jso)
512 : {
513 4097 : if(!jso) return 0.0;
514 4097 : switch(jso->o_type) {
515 : case json_type_double:
516 4094 : 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 142 : static int json_object_string_to_json_string(struct json_object* jso,
532 : struct printbuf *pb)
533 : {
534 142 : sprintbuf(pb, "\"");
535 142 : json_escape_str(pb, jso->o.c_string);
536 142 : sprintbuf(pb, "\"");
537 142 : return 0;
538 : }
539 :
540 2401 : static void json_object_string_delete(struct json_object* jso)
541 : {
542 2401 : free(jso->o.c_string);
543 2401 : json_object_generic_delete(jso);
544 2401 : }
545 :
546 2401 : struct json_object* json_object_new_string(const char *s)
547 : {
548 2401 : struct json_object *jso = json_object_new(json_type_string);
549 2401 : if(!jso) return NULL;
550 2401 : jso->_delete = &json_object_string_delete;
551 2401 : jso->_to_json_string = &json_object_string_to_json_string;
552 2401 : jso->o.c_string = strdup(s);
553 2401 : 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 1525 : const char* json_object_get_string(struct json_object *jso)
567 : {
568 1525 : if(!jso) return NULL;
569 1446 : switch(jso->o_type) {
570 : case json_type_string:
571 955 : 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 14985 : static void json_object_array_entry_free(void *data)
598 : {
599 14985 : json_object_put((struct json_object*)data);
600 14985 : }
601 :
602 5259 : static void json_object_array_delete(struct json_object* jso)
603 : {
604 5259 : array_list_free(jso->o.c_array);
605 5259 : json_object_generic_delete(jso);
606 5259 : }
607 :
608 5259 : struct json_object* json_object_new_array(void)
609 : {
610 5259 : struct json_object *jso = json_object_new(json_type_array);
611 5259 : if(!jso) return NULL;
612 5259 : jso->_delete = &json_object_array_delete;
613 5259 : jso->_to_json_string = &json_object_array_to_json_string;
614 5259 : jso->o.c_array = array_list_new(&json_object_array_entry_free);
615 5259 : 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 2808 : int json_object_array_length(struct json_object *jso)
630 : {
631 2808 : return array_list_length(jso->o.c_array);
632 : }
633 :
634 15036 : int json_object_array_add(struct json_object *jso,struct json_object *val)
635 : {
636 15036 : 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 6923 : struct json_object* json_object_array_get_idx(struct json_object *jso,
646 : int idx)
647 : {
648 6923 : return (struct json_object*)array_list_get_idx(jso->o.c_array, idx);
649 : }
650 :
|