root/src/json-lib/json_object.c

Revision f632f7d9a1b4222c469abf2fc43923fe4868fe37, 12.7 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 years ago)

provide overflow detection and recover for json_objects and leverage that in the lua stuff

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