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


csm
Author(s): Andrea Censi
autogenerated on Tue May 11 2021 02:18:23