~ubuntu-branches/ubuntu/trusty/nordugrid-arc/trusty-proposed

« back to all changes in this revision

Viewing changes to src/hed/dmc/dq2/cJSON/cJSON.c

  • Committer: Package Import Robot
  • Author(s): Mattias Ellert
  • Date: 2013-11-29 13:39:10 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20131129133910-altaxrfowczzl2ev
Tags: 4.0.0-1
4.0.0 Release (Closes: #715131) (LP: #1049798)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <float.h>
 
31
#include <limits.h>
 
32
#include <ctype.h>
 
33
#include "cJSON.h"
 
34
 
 
35
static const char *ep;
 
36
 
 
37
const char *cJSON_GetErrorPtr(void) {return ep;}
 
38
 
 
39
static int cJSON_strcasecmp(const char *s1,const char *s2)
 
40
{
 
41
        if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
 
42
        for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0)    return 0;
 
43
        return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
 
44
}
 
45
 
 
46
static void *(*cJSON_malloc)(size_t sz) = malloc;
 
47
static void (*cJSON_free)(void *ptr) = free;
 
48
 
 
49
static char* cJSON_strdup(const char* str)
 
50
{
 
51
      size_t len;
 
52
      char* copy;
 
53
 
 
54
      len = strlen(str) + 1;
 
55
      if (!(copy = (char*)cJSON_malloc(len))) return 0;
 
56
      memcpy(copy,str,len);
 
57
      return copy;
 
58
}
 
59
 
 
60
void cJSON_InitHooks(cJSON_Hooks* hooks)
 
61
{
 
62
    if (!hooks) { /* Reset hooks */
 
63
        cJSON_malloc = malloc;
 
64
        cJSON_free = free;
 
65
        return;
 
66
    }
 
67
 
 
68
        cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
 
69
        cJSON_free       = (hooks->free_fn)?hooks->free_fn:free;
 
70
}
 
71
 
 
72
/* Internal constructor. */
 
73
static cJSON *cJSON_New_Item(void)
 
74
{
 
75
        cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
 
76
        if (node) memset(node,0,sizeof(cJSON));
 
77
        return node;
 
78
}
 
79
 
 
80
/* Delete a cJSON structure. */
 
81
void cJSON_Delete(cJSON *c)
 
82
{
 
83
        cJSON *next;
 
84
        while (c)
 
85
        {
 
86
                next=c->next;
 
87
                if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
 
88
                if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
 
89
                if (c->string) cJSON_free(c->string);
 
90
                cJSON_free(c);
 
91
                c=next;
 
92
        }
 
93
}
 
94
 
 
95
/* Parse the input text to generate a number, and populate the result into item. */
 
96
static const char *parse_number(cJSON *item,const char *num)
 
97
{
 
98
        double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
 
99
 
 
100
        if (*num=='-') sign=-1,num++;   /* Has sign? */
 
101
        if (*num=='0') num++;                   /* is zero */
 
102
        if (*num>='1' && *num<='9')     do      n=(n*10.0)+(*num++ -'0');       while (*num>='0' && *num<='9'); /* Number? */
 
103
        if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;            do      n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}      /* Fractional part? */
 
104
        if (*num=='e' || *num=='E')             /* Exponent? */
 
105
        {       num++;if (*num=='+') num++;     else if (*num=='-') signsubscale=-1,num++;              /* With sign? */
 
106
                while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');   /* Number? */
 
107
        }
 
108
 
 
109
        n=sign*n*pow(10.0,(scale+subscale*signsubscale));       /* number = +/- number.fraction * 10^+/- exponent */
 
110
        
 
111
        item->valuedouble=n;
 
112
        item->valueint=(int)n;
 
113
        item->type=cJSON_Number;
 
114
        return num;
 
115
}
 
116
 
 
117
/* Render the number nicely from the given item into a string. */
 
118
static char *print_number(cJSON *item)
 
119
{
 
120
        char *str;
 
121
        double d=item->valuedouble;
 
122
        if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
 
123
        {
 
124
                str=(char*)cJSON_malloc(21);    /* 2^64+1 can be represented in 21 chars. */
 
125
                if (str) sprintf(str,"%d",item->valueint);
 
126
        }
 
127
        else
 
128
        {
 
129
                str=(char*)cJSON_malloc(64);    /* This is a nice tradeoff. */
 
130
                if (str)
 
131
                {
 
132
                        if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
 
133
                        else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)                       sprintf(str,"%e",d);
 
134
                        else                                                                                            sprintf(str,"%f",d);
 
135
                }
 
136
        }
 
137
        return str;
 
138
}
 
139
 
 
140
static unsigned parse_hex4(const char *str)
 
141
{
 
142
        unsigned h=0;
 
143
        if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
 
144
        h=h<<4;str++;
 
145
        if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
 
146
        h=h<<4;str++;
 
147
        if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
 
148
        h=h<<4;str++;
 
149
        if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
 
150
        return h;
 
151
}
 
152
 
 
153
/* Parse the input text into an unescaped cstring, and populate item. */
 
154
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
 
155
static const char *parse_string(cJSON *item,const char *str)
 
156
{
 
157
        const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
 
158
        if (*str!='\"') {ep=str;return 0;}      /* not a string! */
 
159
        
 
160
        while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;  /* Skip escaped quotes. */
 
161
        
 
162
        out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
 
163
        if (!out) return 0;
 
164
        
 
165
        ptr=str+1;ptr2=out;
 
166
        while (*ptr!='\"' && *ptr)
 
167
        {
 
168
                if (*ptr!='\\') *ptr2++=*ptr++;
 
169
                else
 
170
                {
 
171
                        ptr++;
 
172
                        switch (*ptr)
 
173
                        {
 
174
                                case 'b': *ptr2++='\b'; break;
 
175
                                case 'f': *ptr2++='\f'; break;
 
176
                                case 'n': *ptr2++='\n'; break;
 
177
                                case 'r': *ptr2++='\r'; break;
 
178
                                case 't': *ptr2++='\t'; break;
 
179
                                case 'u':        /* transcode utf16 to utf8. */
 
180
                                        uc=parse_hex4(ptr+1);ptr+=4;    /* get the unicode char. */
 
181
 
 
182
                                        if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)        break;  /* check for invalid.   */
 
183
 
 
184
                                        if (uc>=0xD800 && uc<=0xDBFF)   /* UTF16 surrogate pairs.       */
 
185
                                        {
 
186
                                                if (ptr[1]!='\\' || ptr[2]!='u')        break;  /* missing second-half of surrogate.    */
 
187
                                                uc2=parse_hex4(ptr+3);ptr+=6;
 
188
                                                if (uc2<0xDC00 || uc2>0xDFFF)           break;  /* invalid second-half of surrogate.    */
 
189
                                                uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
 
190
                                        }
 
191
 
 
192
                                        len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
 
193
                                        
 
194
                                        switch (len) {
 
195
                                                case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
 
196
                                                case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
 
197
                                                case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
 
198
                                                case 1: *--ptr2 =(uc | firstByteMark[len]);
 
199
                                        }
 
200
                                        ptr2+=len;
 
201
                                        break;
 
202
                                default:  *ptr2++=*ptr; break;
 
203
                        }
 
204
                        ptr++;
 
205
                }
 
206
        }
 
207
        *ptr2=0;
 
208
        if (*ptr=='\"') ptr++;
 
209
        item->valuestring=out;
 
210
        item->type=cJSON_String;
 
211
        return ptr;
 
212
}
 
213
 
 
214
/* Render the cstring provided to an escaped version that can be printed. */
 
215
static char *print_string_ptr(const char *str)
 
216
{
 
217
        const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
 
218
        
 
219
        if (!str) return cJSON_strdup("");
 
220
        ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
 
221
        
 
222
        out=(char*)cJSON_malloc(len+3);
 
223
        if (!out) return 0;
 
224
 
 
225
        ptr2=out;ptr=str;
 
226
        *ptr2++='\"';
 
227
        while (*ptr)
 
228
        {
 
229
                if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
 
230
                else
 
231
                {
 
232
                        *ptr2++='\\';
 
233
                        switch (token=*ptr++)
 
234
                        {
 
235
                                case '\\':      *ptr2++='\\';   break;
 
236
                                case '\"':      *ptr2++='\"';   break;
 
237
                                case '\b':      *ptr2++='b';    break;
 
238
                                case '\f':      *ptr2++='f';    break;
 
239
                                case '\n':      *ptr2++='n';    break;
 
240
                                case '\r':      *ptr2++='r';    break;
 
241
                                case '\t':      *ptr2++='t';    break;
 
242
                                default: sprintf(ptr2,"u%04x",token);ptr2+=5;   break;  /* escape and print */
 
243
                        }
 
244
                }
 
245
        }
 
246
        *ptr2++='\"';*ptr2++=0;
 
247
        return out;
 
248
}
 
249
/* Invote print_string_ptr (which is useful) on an item. */
 
250
static char *print_string(cJSON *item)  {return print_string_ptr(item->valuestring);}
 
251
 
 
252
/* Predeclare these prototypes. */
 
253
static const char *parse_value(cJSON *item,const char *value);
 
254
static char *print_value(cJSON *item,int depth,int fmt);
 
255
static const char *parse_array(cJSON *item,const char *value);
 
256
static char *print_array(cJSON *item,int depth,int fmt);
 
257
static const char *parse_object(cJSON *item,const char *value);
 
258
static char *print_object(cJSON *item,int depth,int fmt);
 
259
 
 
260
/* Utility to jump whitespace and cr/lf */
 
261
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
 
262
 
 
263
/* Parse an object - create a new root, and populate. */
 
264
cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
 
265
{
 
266
        const char *end=0;
 
267
        cJSON *c=cJSON_New_Item();
 
268
        ep=0;
 
269
        if (!c) return 0;       /* memory fail */
 
270
 
 
271
        end=parse_value(c,skip(value));
 
272
        if (!end)       {cJSON_Delete(c);return 0;}     /* parse failure. ep is set. */
 
273
 
 
274
        /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
 
275
        if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
 
276
        if (return_parse_end) *return_parse_end=end;
 
277
        return c;
 
278
}
 
279
/* Default options for cJSON_Parse */
 
280
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
 
281
 
 
282
/* Render a cJSON item/entity/structure to text. */
 
283
char *cJSON_Print(cJSON *item)                          {return print_value(item,0,1);}
 
284
char *cJSON_PrintUnformatted(cJSON *item)       {return print_value(item,0,0);}
 
285
 
 
286
/* Parser core - when encountering text, process appropriately. */
 
287
static const char *parse_value(cJSON *item,const char *value)
 
288
{
 
289
        if (!value)                                             return 0;       /* Fail on null. */
 
290
        if (!strncmp(value,"null",4))   { item->type=cJSON_NULL;  return value+4; }
 
291
        if (!strncmp(value,"false",5))  { item->type=cJSON_False; return value+5; }
 
292
        if (!strncmp(value,"true",4))   { item->type=cJSON_True; item->valueint=1;      return value+4; }
 
293
        if (*value=='\"')                               { return parse_string(item,value); }
 
294
        if (*value=='-' || (*value>='0' && *value<='9'))        { return parse_number(item,value); }
 
295
        if (*value=='[')                                { return parse_array(item,value); }
 
296
        if (*value=='{')                                { return parse_object(item,value); }
 
297
 
 
298
        ep=value;return 0;      /* failure. */
 
299
}
 
300
 
 
301
/* Render a value to text. */
 
302
static char *print_value(cJSON *item,int depth,int fmt)
 
303
{
 
304
        char *out=0;
 
305
        if (!item) return 0;
 
306
        switch ((item->type)&255)
 
307
        {
 
308
                case cJSON_NULL:        out=cJSON_strdup("null");       break;
 
309
                case cJSON_False:       out=cJSON_strdup("false");break;
 
310
                case cJSON_True:        out=cJSON_strdup("true"); break;
 
311
                case cJSON_Number:      out=print_number(item);break;
 
312
                case cJSON_String:      out=print_string(item);break;
 
313
                case cJSON_Array:       out=print_array(item,depth,fmt);break;
 
314
                case cJSON_Object:      out=print_object(item,depth,fmt);break;
 
315
        }
 
316
        return out;
 
317
}
 
318
 
 
319
/* Build an array from input text. */
 
320
static const char *parse_array(cJSON *item,const char *value)
 
321
{
 
322
        cJSON *child;
 
323
        if (*value!='[')        {ep=value;return 0;}    /* not an array! */
 
324
 
 
325
        item->type=cJSON_Array;
 
326
        value=skip(value+1);
 
327
        if (*value==']') return value+1;        /* empty array. */
 
328
 
 
329
        item->child=child=cJSON_New_Item();
 
330
        if (!item->child) return 0;              /* memory fail */
 
331
        value=skip(parse_value(child,skip(value)));     /* skip any spacing, get the value. */
 
332
        if (!value) return 0;
 
333
 
 
334
        while (*value==',')
 
335
        {
 
336
                cJSON *new_item;
 
337
                if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */
 
338
                child->next=new_item;new_item->prev=child;child=new_item;
 
339
                value=skip(parse_value(child,skip(value+1)));
 
340
                if (!value) return 0;   /* memory fail */
 
341
        }
 
342
 
 
343
        if (*value==']') return value+1;        /* end of array */
 
344
        ep=value;return 0;      /* malformed. */
 
345
}
 
346
 
 
347
/* Render an array to text */
 
348
static char *print_array(cJSON *item,int depth,int fmt)
 
349
{
 
350
        char **entries;
 
351
        char *out=0,*ptr,*ret;int len=5;
 
352
        cJSON *child=item->child;
 
353
        int numentries=0,i=0,fail=0;
 
354
        
 
355
        /* How many entries in the array? */
 
356
        while (child) numentries++,child=child->next;
 
357
        /* Explicitly handle numentries==0 */
 
358
        if (!numentries)
 
359
        {
 
360
                out=(char*)cJSON_malloc(3);
 
361
                if (out) strcpy(out,"[]");
 
362
                return out;
 
363
        }
 
364
        /* Allocate an array to hold the values for each */
 
365
        entries=(char**)cJSON_malloc(numentries*sizeof(char*));
 
366
        if (!entries) return 0;
 
367
        memset(entries,0,numentries*sizeof(char*));
 
368
        /* Retrieve all the results: */
 
369
        child=item->child;
 
370
        while (child && !fail)
 
371
        {
 
372
                ret=print_value(child,depth+1,fmt);
 
373
                entries[i++]=ret;
 
374
                if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
 
375
                child=child->next;
 
376
        }
 
377
        
 
378
        /* If we didn't fail, try to malloc the output string */
 
379
        if (!fail) out=(char*)cJSON_malloc(len);
 
380
        /* If that fails, we fail. */
 
381
        if (!out) fail=1;
 
382
 
 
383
        /* Handle failure. */
 
384
        if (fail)
 
385
        {
 
386
                for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
 
387
                cJSON_free(entries);
 
388
                return 0;
 
389
        }
 
390
        
 
391
        /* Compose the output array. */
 
392
        *out='[';
 
393
        ptr=out+1;*ptr=0;
 
394
        for (i=0;i<numentries;i++)
 
395
        {
 
396
                strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
 
397
                if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
 
398
                cJSON_free(entries[i]);
 
399
        }
 
400
        cJSON_free(entries);
 
401
        *ptr++=']';*ptr++=0;
 
402
        return out;     
 
403
}
 
404
 
 
405
/* Build an object from the text. */
 
406
static const char *parse_object(cJSON *item,const char *value)
 
407
{
 
408
        cJSON *child;
 
409
        if (*value!='{')        {ep=value;return 0;}    /* not an object! */
 
410
        
 
411
        item->type=cJSON_Object;
 
412
        value=skip(value+1);
 
413
        if (*value=='}') return value+1;        /* empty array. */
 
414
        
 
415
        item->child=child=cJSON_New_Item();
 
416
        if (!item->child) return 0;
 
417
        value=skip(parse_string(child,skip(value)));
 
418
        if (!value) return 0;
 
419
        child->string=child->valuestring;child->valuestring=0;
 
420
        if (*value!=':') {ep=value;return 0;}   /* fail! */
 
421
        value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
 
422
        if (!value) return 0;
 
423
        
 
424
        while (*value==',')
 
425
        {
 
426
                cJSON *new_item;
 
427
                if (!(new_item=cJSON_New_Item()))       return 0; /* memory fail */
 
428
                child->next=new_item;new_item->prev=child;child=new_item;
 
429
                value=skip(parse_string(child,skip(value+1)));
 
430
                if (!value) return 0;
 
431
                child->string=child->valuestring;child->valuestring=0;
 
432
                if (*value!=':') {ep=value;return 0;}   /* fail! */
 
433
                value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
 
434
                if (!value) return 0;
 
435
        }
 
436
        
 
437
        if (*value=='}') return value+1;        /* end of array */
 
438
        ep=value;return 0;      /* malformed. */
 
439
}
 
440
 
 
441
/* Render an object to text. */
 
442
static char *print_object(cJSON *item,int depth,int fmt)
 
443
{
 
444
        char **entries=0,**names=0;
 
445
        char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
 
446
        cJSON *child=item->child;
 
447
        int numentries=0,fail=0;
 
448
        /* Count the number of entries. */
 
449
        while (child) numentries++,child=child->next;
 
450
        /* Explicitly handle empty object case */
 
451
        if (!numentries)
 
452
        {
 
453
                out=(char*)cJSON_malloc(fmt?depth+4:3);
 
454
                if (!out)       return 0;
 
455
                ptr=out;*ptr++='{';
 
456
                if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
 
457
                *ptr++='}';*ptr++=0;
 
458
                return out;
 
459
        }
 
460
        /* Allocate space for the names and the objects */
 
461
        entries=(char**)cJSON_malloc(numentries*sizeof(char*));
 
462
        if (!entries) return 0;
 
463
        names=(char**)cJSON_malloc(numentries*sizeof(char*));
 
464
        if (!names) {cJSON_free(entries);return 0;}
 
465
        memset(entries,0,sizeof(char*)*numentries);
 
466
        memset(names,0,sizeof(char*)*numentries);
 
467
 
 
468
        /* Collect all the results into our arrays: */
 
469
        child=item->child;depth++;if (fmt) len+=depth;
 
470
        while (child)
 
471
        {
 
472
                names[i]=str=print_string_ptr(child->string);
 
473
                entries[i++]=ret=print_value(child,depth,fmt);
 
474
                if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
 
475
                child=child->next;
 
476
        }
 
477
        
 
478
        /* Try to allocate the output string */
 
479
        if (!fail) out=(char*)cJSON_malloc(len);
 
480
        if (!out) fail=1;
 
481
 
 
482
        /* Handle failure */
 
483
        if (fail)
 
484
        {
 
485
                for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
 
486
                cJSON_free(names);cJSON_free(entries);
 
487
                return 0;
 
488
        }
 
489
        
 
490
        /* Compose the output: */
 
491
        *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
 
492
        for (i=0;i<numentries;i++)
 
493
        {
 
494
                if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
 
495
                strcpy(ptr,names[i]);ptr+=strlen(names[i]);
 
496
                *ptr++=':';if (fmt) *ptr++='\t';
 
497
                strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
 
498
                if (i!=numentries-1) *ptr++=',';
 
499
                if (fmt) *ptr++='\n';*ptr=0;
 
500
                cJSON_free(names[i]);cJSON_free(entries[i]);
 
501
        }
 
502
        
 
503
        cJSON_free(names);cJSON_free(entries);
 
504
        if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
 
505
        *ptr++='}';*ptr++=0;
 
506
        return out;     
 
507
}
 
508
 
 
509
/* Get Array size/item / object item. */
 
510
int    cJSON_GetArraySize(cJSON *array)                                                 {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
 
511
cJSON *cJSON_GetArrayItem(cJSON *array,int item)                                {cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
 
512
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)    {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
 
513
 
 
514
/* Utility for array list handling. */
 
515
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
 
516
/* Utility for handling references. */
 
517
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;}
 
518
 
 
519
/* Add item to array/object. */
 
520
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);}}
 
521
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
void    cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)                                                {cJSON_AddItemToArray(array,create_reference(item));}
 
523
void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)    {cJSON_AddItemToObject(object,string,create_reference(item));}
 
524
 
 
525
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)                        {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
 
526
        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
void   cJSON_DeleteItemFromArray(cJSON *array,int which)                        {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
 
528
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;}
 
529
void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
 
530
 
 
531
/* Replace array/object items with new ones. */
 
532
void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)          {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
 
533
        newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
 
534
        if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
 
535
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);}}
 
536
 
 
537
/* Create basic types: */
 
538
cJSON *cJSON_CreateNull(void)                                   {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
 
539
cJSON *cJSON_CreateTrue(void)                                   {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
 
540
cJSON *cJSON_CreateFalse(void)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
 
541
cJSON *cJSON_CreateBool(int b)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
 
542
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;}
 
543
cJSON *cJSON_CreateString(const char *string)   {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
 
544
cJSON *cJSON_CreateArray(void)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
 
545
cJSON *cJSON_CreateObject(void)                                 {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
 
546
 
 
547
/* Create Arrays: */
 
548
cJSON *cJSON_CreateIntArray(const 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;}
 
549
cJSON *cJSON_CreateFloatArray(const 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;}
 
550
cJSON *cJSON_CreateDoubleArray(const 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;}
 
551
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;}
 
552
 
 
553
/* Duplication */
 
554
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
 
555
{
 
556
        cJSON *newitem,*cptr,*nptr=0,*newchild;
 
557
        /* Bail on bad ptr */
 
558
        if (!item) return 0;
 
559
        /* Create new item */
 
560
        newitem=cJSON_New_Item();
 
561
        if (!newitem) return 0;
 
562
        /* Copy over all vars */
 
563
        newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
 
564
        if (item->valuestring)  {newitem->valuestring=cJSON_strdup(item->valuestring);  if (!newitem->valuestring)      {cJSON_Delete(newitem);return 0;}}
 
565
        if (item->string)               {newitem->string=cJSON_strdup(item->string);                    if (!newitem->string)           {cJSON_Delete(newitem);return 0;}}
 
566
        /* If non-recursive, then we're done! */
 
567
        if (!recurse) return newitem;
 
568
        /* Walk the ->next chain for the child. */
 
569
        cptr=item->child;
 
570
        while (cptr)
 
571
        {
 
572
                newchild=cJSON_Duplicate(cptr,1);               /* Duplicate (with recurse) each item in the ->next chain */
 
573
                if (!newchild) {cJSON_Delete(newitem);return 0;}
 
574
                if (nptr)       {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}        /* If newitem->child already set, then crosswire ->prev and ->next and move on */
 
575
                else            {newitem->child=newchild;nptr=newchild;}                                        /* Set newitem->child and move to it */
 
576
                cptr=cptr->next;
 
577
        }
 
578
        return newitem;
 
579
}
 
580
 
 
581
void cJSON_Minify(char *json)
 
582
{
 
583
        char *into=json;
 
584
        while (*json)
 
585
        {
 
586
                if (*json==' ') json++;
 
587
                else if (*json=='\t') json++;   // Whitespace characters.
 
588
                else if (*json=='\r') json++;
 
589
                else if (*json=='\n') json++;
 
590
                else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;      // double-slash comments, to end of line.
 
591
                else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}   // multiline comments.
 
592
                else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
 
593
                else *into++=*json++;                   // All other characters.
 
594
        }
 
595
        *into=0;        // and null-terminate.
 
596
}
 
 
b'\\ No newline at end of file'