FreeSWITCH API Documentation  1.7.0
switch_json.c
Go to the documentation of this file.
1 /*
2  Copyright (c) 2009 Dave Gamble
3 
4  Permission is hereby granted, free of charge, to any person obtaining a copy
5  of this software and associated documentation files (the "Software"), to deal
6  in the Software without restriction, including without limitation the rights
7  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  copies of the Software, and to permit persons to whom the Software is
9  furnished to do so, subject to the following conditions:
10 
11  The above copyright notice and this permission notice shall be included in
12  all copies or substantial portions of the Software.
13 
14  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  THE SOFTWARE.
21 */
22 
23 /* cJSON */
24 /* JSON parser in C. */
25 
26 #include <string.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <stdlib.h>
30 #include <limits.h>
31 #include <ctype.h>
32 #include "switch.h"
33 #include "switch_json.h"
34 #include <float.h>
35 
36 static const char *ep;
37 
38 SWITCH_DECLARE(const char *)cJSON_GetErrorPtr() {return ep;}
39 
40 static int cJSON_strcasecmp(const char *s1,const char *s2)
41 {
42  if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
43  for(; tolower(*(const unsigned char *)s1) == tolower(*(const unsigned char *)s2); ++s1, ++s2) if(*s1 == 0) return 0;
44  return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
45 }
46 
47 static void *glue_malloc(size_t theSize)
48 {
49  return(malloc(theSize));
50 }
51 
52 static void glue_free(void *thePtr)
53 {
54  free(thePtr);
55 }
56 
57 static void *(*cJSON_malloc)(size_t sz) = glue_malloc;
58 static void (*cJSON_free)(void *ptr) = glue_free;
59 
60 static char* cJSON_strdup(const char* str)
61 {
62  size_t len;
63  char* copy;
64  const char *s = str ? str : "";
65 
66  len = strlen(s) + 1;
67  if (!(copy = (char*)cJSON_malloc(len))) return 0;
68  memcpy(copy,s,len);
69  return copy;
70 }
71 
73 {
74  if (!hooks) { /* Reset hooks */
75  cJSON_malloc = malloc;
76  cJSON_free = free;
77  return;
78  }
79 
80  cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
81  cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
82 }
83 
84 /* Internal constructor. */
86 {
87  cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
88  if (node) memset(node,0,sizeof(cJSON));
89  return node;
90 }
91 
92 /* Delete a cJSON structure. */
94 {
95  cJSON *next;
96  while (c)
97  {
98  next=c->next;
99  if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
100  if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
101  if (c->string) cJSON_free(c->string);
102  cJSON_free(c);
103  c=next;
104  }
105 }
106 
107 /* Parse the input text to generate a number, and populate the result into item. */
108 static const char *parse_number(cJSON *item,const char *num)
109 {
110  double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
111 
112  /* Could use sscanf for this? */
113  if (*num=='-') sign=-1,num++; /* Has sign? */
114  if (*num=='0') num++; /* is zero */
115  if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
116  if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
117  if (*num=='e' || *num=='E') /* Exponent? */
118  { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
119  while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
120  }
121 
122  n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
123 
124  item->valuedouble=n;
125  item->valueint=(int)n;
126  item->type=cJSON_Number;
127  return num;
128 }
129 
130 /* Render the number nicely from the given item into a string. */
131 static char *print_number(cJSON *item)
132 {
133  char *str;
134  double d=item->valuedouble;
135  if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
136  {
137  str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
138  if (str) sprintf(str,"%d",item->valueint);
139  }
140  else
141  {
142  str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
143  if (str)
144  {
145  if (fabs(floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
146  else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
147  else sprintf(str,"%f",d);
148  }
149  }
150  return str;
151 }
152 
153 #define is_hexdigit(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
154 static int scan_unicode(const char *ptr, unsigned int *uc)
155 {
156  if (!is_hexdigit(*(ptr)) || !is_hexdigit(*(ptr+1)) || !is_hexdigit(*(ptr+2)) || !is_hexdigit(*(ptr+3))) return -1;
157  return sscanf(ptr, "%4x", uc);
158 }
159 
160 /* Parse the input text into an unescaped cstring, and populate item. */
161 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
162 static const char *parse_string(cJSON *item,const char *str)
163 {
164  const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
165  if (*str!='\"') {ep=str;return 0;} /* not a string! */
166 
167  while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
168 
169  out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
170  if (!out) return 0;
171 
172  ptr=str+1;ptr2=out;
173  while (*ptr!='\"' && *ptr)
174  {
175  if (*ptr!='\\') *ptr2++=*ptr++;
176  else
177  {
178  ptr++;
179  switch (*ptr)
180  {
181  case 'b': *ptr2++='\b'; break;
182  case 'f': *ptr2++='\f'; break;
183  case 'n': *ptr2++='\n'; break;
184  case 'r': *ptr2++='\r'; break;
185  case 't': *ptr2++='\t'; break;
186  case 'u': /* transcode utf16 to utf8. */
187  if (scan_unicode(ptr+1, &uc) < 1) break;
188  ptr+=4; /* get the unicode char. */
189 
190  if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; // check for invalid.
191 
192  if (uc>=0xD800 && uc<=0xDBFF) // UTF16 surrogate pairs.
193  {
194  if (ptr[1]!='\\' || ptr[2]!='u') break; // missing second-half of surrogate.
195  if (scan_unicode(ptr+3,&uc2) < 1) break;
196  ptr+=6;
197  if (uc2<0xDC00 || uc2>0xDFFF) break; // invalid second-half of surrogate.
198  uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF);
199  }
200 
201  len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
202 
203  switch (len) {
204  case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
205  case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
206  case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
207  case 1: *--ptr2 =(char)(uc | firstByteMark[len]);
208  }
209  ptr2+=len;
210  break;
211  default: *ptr2++=*ptr; break;
212  }
213  if (*ptr) ptr++;
214  }
215  }
216  *ptr2=0;
217  if (*ptr=='\"') ptr++;
218  item->valuestring=out;
219  item->type=cJSON_String;
220  return ptr;
221 }
222 
223 /* Render the cstring provided to an escaped version that can be printed. */
224 static char *print_string_ptr(const char *str)
225 {
226  const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
227 
228  if (!str) return cJSON_strdup("");
229  ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
230 
231  out=(char*)cJSON_malloc(len+3);
232  if (!out) return 0;
233 
234  ptr2=out;ptr=str;
235  *ptr2++='\"';
236  while (*ptr)
237  {
238  if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
239  else
240  {
241  *ptr2++='\\';
242  switch (token=*ptr++)
243  {
244  case '\\': *ptr2++='\\'; break;
245  case '\"': *ptr2++='\"'; break;
246  case '\b': *ptr2++='b'; break;
247  case '\f': *ptr2++='f'; break;
248  case '\n': *ptr2++='n'; break;
249  case '\r': *ptr2++='r'; break;
250  case '\t': *ptr2++='t'; break;
251  default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
252  }
253  }
254  }
255  *ptr2++='\"';*ptr2++=0;
256  return out;
257 }
258 /* Invote print_string_ptr (which is useful) on an item. */
259 static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
260 
261 /* Predeclare these prototypes. */
262 static const char *parse_value(cJSON *item,const char *value);
263 static char *print_value(cJSON *item,int depth,int fmt);
264 static const char *parse_array(cJSON *item,const char *value);
265 static char *print_array(cJSON *item,int depth,int fmt);
266 static const char *parse_object(cJSON *item,const char *value);
267 static char *print_object(cJSON *item,int depth,int fmt);
268 
269 /* Utility to jump whitespace and cr/lf */
270 static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
271 
272 /* Parse an object - create a new root, and populate. */
273 SWITCH_DECLARE(cJSON *)cJSON_Parse(const char *value)
274 {
275  cJSON *c=cJSON_New_Item();
276  ep=0;
277  if (!c) return 0; /* memory fail */
278 
279  if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
280  return c;
281 }
282 
283 /* Render a cJSON item/entity/structure to text. */
284 SWITCH_DECLARE(char *)cJSON_Print(cJSON *item) {return print_value(item,0,1);}
285 SWITCH_DECLARE(char *)cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
286 
287 /* Parser core - when encountering text, process appropriately. */
288 static const char *parse_value(cJSON *item,const char *value)
289 {
290  if (!value) return 0; /* Fail on null. */
291  if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
292  if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
293  if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
294  if (*value=='\"') { return parse_string(item,value); }
295  if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
296  if (*value=='[') { return parse_array(item,value); }
297  if (*value=='{') { return parse_object(item,value); }
298 
299  ep=value;return 0; /* failure. */
300 }
301 
302 /* Render a value to text. */
303 static char *print_value(cJSON *item,int depth,int fmt)
304 {
305  char *out=0;
306  if (!item) return 0;
307  switch ((item->type)&255)
308  {
309  case cJSON_NULL: out=cJSON_strdup("null"); break;
310  case cJSON_False: out=cJSON_strdup("false");break;
311  case cJSON_True: out=cJSON_strdup("true"); break;
312  case cJSON_Number: out=print_number(item);break;
313  case cJSON_String: out=print_string(item);break;
314  case cJSON_Array: out=print_array(item,depth,fmt);break;
315  case cJSON_Object: out=print_object(item,depth,fmt);break;
316  }
317  return out;
318 }
319 
320 /* Build an array from input text. */
321 static const char *parse_array(cJSON *item,const char *value)
322 {
323  cJSON *child;
324  if (*value!='[') {ep=value;return 0;} /* not an array! */
325 
326  item->type=cJSON_Array;
327  value=skip(value+1);
328  if (*value==']') return value+1; /* empty array. */
329 
330  item->child=child=cJSON_New_Item();
331  if (!item->child) return 0; /* memory fail */
332  value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
333  if (!value) return 0;
334 
335  while (*value==',')
336  {
337  cJSON *new_item;
338  if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
339  child->next=new_item;new_item->prev=child;child=new_item;
340  value=skip(parse_value(child,skip(value+1)));
341  if (!value) return 0; /* memory fail */
342  }
343 
344  if (*value==']') return value+1; /* end of array */
345  ep=value;return 0; /* malformed. */
346 }
347 
348 /* Render an array to text */
349 static char *print_array(cJSON *item,int depth,int fmt)
350 {
351  char **entries;
352  char *out=0,*ptr,*ret;
353  size_t len=5;
354  cJSON *child=item->child;
355  int numentries=0,i=0,fail=0;
356 
357  /* How many entries in the array? */
358  while (child) numentries++,child=child->next;
359  /* Allocate an array to hold the values for each */
360  entries=(char**)cJSON_malloc(numentries*sizeof(char*));
361  if (!entries) return 0;
362  memset(entries,0,numentries*sizeof(char*));
363  /* Retrieve all the results: */
364  child=item->child;
365  while (child && !fail)
366  {
367  ret=print_value(child,depth+1,fmt);
368  entries[i++]=ret;
369  if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
370  child=child->next;
371  }
372 
373  /* If we didn't fail, try to malloc the output string */
374  if (!fail) out=(char*)cJSON_malloc(len);
375  /* If that fails, we fail. */
376  if (!out) fail=1;
377 
378  /* Handle failure. */
379  if (fail)
380  {
381  for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
382  cJSON_free(entries);
383  return 0;
384  }
385 
386  /* Compose the output array. */
387  *out='[';
388  ptr=out+1;*ptr=0;
389  for (i=0;i<numentries;i++)
390  {
391  strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
392  if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
393  cJSON_free(entries[i]);
394  }
395  cJSON_free(entries);
396  *ptr++=']';*ptr++=0;
397  return out;
398 }
399 
400 /* Build an object from the text. */
401 static const char *parse_object(cJSON *item,const char *value)
402 {
403  cJSON *child;
404  if (*value!='{') {ep=value;return 0;} /* not an object! */
405 
406  item->type=cJSON_Object;
407  value=skip(value+1);
408  if (*value=='}') return value+1; /* empty array. */
409 
410  item->child=child=cJSON_New_Item();
411  if (!item->child) return 0;
412  value=skip(parse_string(child,skip(value)));
413  if (!value) return 0;
414  child->string=child->valuestring;child->valuestring=0;
415  if (*value!=':') {ep=value;return 0;} /* fail! */
416  value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
417  if (!value) return 0;
418 
419  while (*value==',')
420  {
421  cJSON *new_item;
422  if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
423  child->next=new_item;new_item->prev=child;child=new_item;
424  value=skip(parse_string(child,skip(value+1)));
425  if (!value) return 0;
426  child->string=child->valuestring;child->valuestring=0;
427  if (*value!=':') {ep=value;return 0;} /* fail! */
428  value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
429  if (!value) return 0;
430  }
431 
432  if (*value=='}') return value+1; /* end of array */
433  ep=value;return 0; /* malformed. */
434 }
435 
436 /* Render an object to text. */
437 static char *print_object(cJSON *item,int depth,int fmt)
438 {
439  char **entries=0,**names=0;
440  char *out=0,*ptr,*ret,*str;int i=0,j;
441  size_t len=7;
442  cJSON *child=item->child;
443  int numentries=0,fail=0;
444  /* Count the number of entries. */
445  while (child) numentries++,child=child->next;
446  /* Allocate space for the names and the objects */
447  entries=(char**)cJSON_malloc(numentries*sizeof(char*));
448  if (!entries) return 0;
449  names=(char**)cJSON_malloc(numentries*sizeof(char*));
450  if (!names) {cJSON_free(entries);return 0;}
451  memset(entries,0,sizeof(char*)*numentries);
452  memset(names,0,sizeof(char*)*numentries);
453 
454  /* Collect all the results into our arrays: */
455  child=item->child;depth++;if (fmt) len+=depth;
456  while (child)
457  {
458  names[i]=str=print_string_ptr(child->string);
459  entries[i++]=ret=print_value(child,depth,fmt);
460  if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
461  child=child->next;
462  }
463 
464  /* Try to allocate the output string */
465  if (!fail) out=(char*)cJSON_malloc(len);
466  if (!out) fail=1;
467 
468  /* Handle failure */
469  if (fail)
470  {
471  for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
472  cJSON_free(names);cJSON_free(entries);
473  return 0;
474  }
475 
476  /* Compose the output: */
477  *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
478  for (i=0;i<numentries;i++)
479  {
480  if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
481  strcpy(ptr,names[i]);ptr+=strlen(names[i]);
482  *ptr++=':';if (fmt) *ptr++='\t';
483  strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
484  if (i!=numentries-1) *ptr++=',';
485  if (fmt) *ptr++='\n';*ptr=0;
486  cJSON_free(names[i]);cJSON_free(entries[i]);
487  }
488 
489  cJSON_free(names);cJSON_free(entries);
490  if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
491  *ptr++='}';*ptr++=0;
492  return out;
493 }
494 
495 /* Get Array size/item / object item. */
496 SWITCH_DECLARE(int) cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
497 SWITCH_DECLARE(cJSON *)cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
498 SWITCH_DECLARE(cJSON *)cJSON_GetObjectItem(const cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
499 
500 
501 SWITCH_DECLARE(const char *)cJSON_GetObjectCstr(const cJSON *object, const char *string)
502 {
503  cJSON *cj = cJSON_GetObjectItem(object, string);
504 
505  if (!cj || cj->type != cJSON_String || !cj->valuestring) return NULL;
506 
507  return cj->valuestring;
508 }
509 
510 
511 
512 
513 /* Utility for array list handling. */
514 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
515 /* Utility for handling references. */
516 static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
517 
518 /* Add item to array/object. */
519 SWITCH_DECLARE(void) cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
520 SWITCH_DECLARE(void) cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
522 SWITCH_DECLARE(void) cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
523 
524 SWITCH_DECLARE(cJSON *)cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
525  if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
527 SWITCH_DECLARE(cJSON *)cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
528 SWITCH_DECLARE(void) cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
529 
530 /* Replace array/object items with new ones. */
531 SWITCH_DECLARE(void) cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
532  newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
533  if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
534 SWITCH_DECLARE(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
535 
536 /* Create basic types: */
537 SWITCH_DECLARE(cJSON *)cJSON_CreateNull() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
538 SWITCH_DECLARE(cJSON *)cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
540 SWITCH_DECLARE(cJSON *)cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
541 SWITCH_DECLARE(cJSON *)cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
542 SWITCH_DECLARE(cJSON *)cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
545 
546 /* Create Arrays: */
547 SWITCH_DECLARE(cJSON *)cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
548 SWITCH_DECLARE(cJSON *)cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
549 SWITCH_DECLARE(cJSON *)cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
550 SWITCH_DECLARE(cJSON *)cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
551 
552 /* Duplication */
554 {
555  cJSON *newitem,*cptr,*nptr=0,*newchild;
556  /* Bail on bad ptr */
557  if (!item) return 0;
558  /* Create new item */
559  newitem=cJSON_New_Item();
560  if (!newitem) return 0;
561  /* Copy over all vars */
562  newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
563  if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
564  if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
565  /* If non-recursive, then we're done! */
566  if (!recurse) return newitem;
567  /* Walk the ->next chain for the child. */
568  cptr=item->child;
569  while (cptr) {
570  newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
571  if (!newchild) {cJSON_Delete(newitem);return 0;}
572  if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
573  else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
574  cptr=cptr->next;
575  }
576  return newitem;
577 }
578 
579 
581 {
582  va_list ap;
583  char *str;
584  cJSON *item;
585 
586  va_start(ap, fmt);
587  str = switch_vmprintf(fmt, ap);
588  va_end(ap);
589 
590  if (!str) return NULL;
591 
592  if ((item = cJSON_New_Item())) {
593  item->type=cJSON_String;
594  item->valuestring = str;
595  } else {
596  free(str);
597  }
598 
599  return item;
600 }
601 
602 /* For Emacs:
603  * Local Variables:
604  * mode:c
605  * indent-tabs-mode:t
606  * tab-width:4
607  * c-basic-offset:4
608  * End:
609  * For VIM:
610  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
611  */
#define cJSON_True
Definition: switch_json.h:33
static void(* cJSON_free)(void *ptr)
Definition: switch_json.c:58
int cJSON_GetArraySize(cJSON *array)
Definition: switch_json.c:496
cJSON * cJSON_CreateString(const char *string)
Definition: switch_json.c:542
static const char * parse_string(cJSON *item, const char *str)
Definition: switch_json.c:162
void cJSON_DeleteItemFromObject(cJSON *object, const char *string)
Definition: switch_json.c:528
struct switch_jb_node_s * next
#define cJSON_Object
Definition: switch_json.h:38
static const char * parse_value(cJSON *item, const char *value)
Definition: switch_json.c:288
cJSON * cJSON_DetachItemFromArray(cJSON *array, int which)
Definition: switch_json.c:524
cJSON * cJSON_GetObjectItem(const cJSON *object, const char *string)
Definition: switch_json.c:498
#define fail()
Definition: tone2wav.c:70
static cJSON * cJSON_New_Item()
Definition: switch_json.c:85
int valueint
Definition: switch_json.h:50
char * valuestring
Definition: switch_json.h:49
static char * print_array(cJSON *item, int depth, int fmt)
Definition: switch_json.c:349
cJSON * cJSON_CreateIntArray(int *numbers, int count)
Definition: switch_json.c:547
void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
Definition: switch_json.c:534
void cJSON_DeleteItemFromArray(cJSON *array, int which)
Definition: switch_json.c:526
cJSON * cJSON_GetArrayItem(cJSON *array, int item)
Definition: switch_json.c:497
void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
Definition: switch_json.c:531
static cJSON * create_reference(cJSON *item)
Definition: switch_json.c:516
static char * cJSON_strdup(const char *str)
Definition: switch_json.c:60
void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
Definition: switch_json.c:522
static void * glue_malloc(size_t theSize)
Definition: switch_json.c:47
if((uint32_t)(unpack->cur-unpack->buf) > unpack->buflen)
struct cJSON * child
Definition: switch_json.h:45
char * string
Definition: switch_json.h:53
const char * cJSON_GetObjectCstr(const cJSON *object, const char *string)
Definition: switch_json.c:501
switch_byte_t in
const char * cJSON_GetErrorPtr()
Definition: switch_json.c:38
#define cJSON_False
Definition: switch_json.h:32
cJSON * cJSON_CreateObject()
Definition: switch_json.c:544
void cJSON_Delete(cJSON *c)
Definition: switch_json.c:93
struct cJSON * next
Definition: switch_json.h:44
cJSON * cJSON_CreateBool(int b)
Definition: switch_json.c:540
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
Definition: switch_json.c:521
cJSON * cJSON_CreateFalse()
Definition: switch_json.c:539
static void glue_free(void *thePtr)
Definition: switch_json.c:52
static const char * parse_number(cJSON *item, const char *num)
Definition: switch_json.c:108
#define cJSON_IsReference
Definition: switch_json.h:40
static void suffix_object(cJSON *prev, cJSON *item)
Definition: switch_json.c:514
static int scan_unicode(const char *ptr, unsigned int *uc)
Definition: switch_json.c:154
cJSON * cJSON_CreateStringPrintf(const char *fmt,...)
Definition: switch_json.c:580
cJSON * cJSON_CreateDoubleArray(double *numbers, int count)
Definition: switch_json.c:549
#define cJSON_Array
Definition: switch_json.h:37
static char * print_value(cJSON *item, int depth, int fmt)
Definition: switch_json.c:303
cJSON * cJSON_CreateNull()
Definition: switch_json.c:537
static char * print_string_ptr(const char *str)
Definition: switch_json.c:224
#define cJSON_Number
Definition: switch_json.h:35
static const char * ep
Definition: switch_json.c:36
cJSON * cJSON_Parse(const char *value)
Definition: switch_json.c:273
cJSON * cJSON_CreateTrue()
Definition: switch_json.c:538
void cJSON_AddItemToArray(cJSON *array, cJSON *item)
Definition: switch_json.c:519
void cJSON_InitHooks(cJSON_Hooks *hooks)
Definition: switch_json.c:72
cJSON * cJSON_Duplicate(cJSON *item, int recurse)
Definition: switch_json.c:553
Main Library Header.
#define SWITCH_DECLARE(type)
struct cJSON * prev
Definition: switch_json.h:44
struct switch_jb_node_s * prev
static const char * skip(const char *in)
Definition: switch_json.c:270
cJSON * cJSON_CreateFloatArray(float *numbers, int count)
Definition: switch_json.c:548
static void *(* cJSON_malloc)(size_t sz)
Definition: switch_json.c:57
char * cJSON_Print(cJSON *item)
Definition: switch_json.c:284
#define cJSON_String
Definition: switch_json.h:36
static const char * parse_object(cJSON *item, const char *value)
Definition: switch_json.c:401
char * cJSON_PrintUnformatted(cJSON *item)
Definition: switch_json.c:285
int type
Definition: switch_json.h:47
static char * print_string(cJSON *item)
Definition: switch_json.c:259
cJSON * cJSON_CreateArray()
Definition: switch_json.c:543
static const unsigned char firstByteMark[7]
Definition: switch_json.c:161
static const char * parse_array(cJSON *item, const char *value)
Definition: switch_json.c:321
static char * print_object(cJSON *item, int depth, int fmt)
Definition: switch_json.c:437
cJSON * cJSON_CreateStringArray(const char **strings, int count)
Definition: switch_json.c:550
#define cJSON_NULL
Definition: switch_json.h:34
static char * print_number(cJSON *item)
Definition: switch_json.c:131
double valuedouble
Definition: switch_json.h:51
memset(buf, 0, buflen)
char * switch_vmprintf(const char *zFormat, va_list ap)
#define is_hexdigit(c)
Definition: switch_json.c:153
cJSON * cJSON_CreateNumber(double num)
Definition: switch_json.c:541
cJSON * cJSON_DetachItemFromObject(cJSON *object, const char *string)
Definition: switch_json.c:527
static int cJSON_strcasecmp(const char *s1, const char *s2)
Definition: switch_json.c:40
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
Definition: switch_json.c:520