~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/plugins/contrib/wxCrafterCB/wxcLib/cJSON.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

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() {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()
 
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
        /* Could use sscanf for this? */
 
101
        if (*num=='-') sign=-1,num++;   /* Has sign? */
 
102
        if (*num=='0') num++;                   /* is zero */
 
103
        if (*num>='1' && *num<='9')     do      n=(n*10.0)+(*num++ -'0');       while (*num>='0' && *num<='9'); /* Number? */
 
104
        if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;            do      n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}      /* Fractional part? */
 
105
        if (*num=='e' || *num=='E')             /* Exponent? */
 
106
        {       num++;if (*num=='+') num++;     else if (*num=='-') signsubscale=-1,num++;              /* With sign? */
 
107
                while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');   /* Number? */
 
108
        }
 
109
 
 
110
        n=sign*n*pow(10.0,(scale+subscale*signsubscale));       /* number = +/- number.fraction * 10^+/- exponent */
 
111
        
 
112
        item->valuedouble=n;
 
113
        item->valueint=(int)n;
 
114
        item->type=cJSON_Number;
 
115
        return num;
 
116
}
 
117
 
 
118
/* Render the number nicely from the given item into a string. */
 
119
static char *print_number(cJSON *item)
 
120
{
 
121
        char *str;
 
122
        double d=item->valuedouble;
 
123
        if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
 
124
        {
 
125
                str=(char*)cJSON_malloc(21);    /* 2^64+1 can be represented in 21 chars. */
 
126
                if (str) sprintf(str,"%d",item->valueint);
 
127
        }
 
128
        else
 
129
        {
 
130
                str=(char*)cJSON_malloc(64);    /* This is a nice tradeoff. */
 
131
                if (str)
 
132
                {
 
133
                        if (fabs(floor(d)-d)<=DBL_EPSILON)                      sprintf(str,"%.0f",d);
 
134
                        else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)       sprintf(str,"%e",d);
 
135
                        else                                                                            sprintf(str,"%f",d);
 
136
                }
 
137
        }
 
138
        return str;
 
139
}
 
140
 
 
141
/* Parse the input text into an unescaped cstring, and populate item. */
 
142
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
 
143
static const char *parse_string(cJSON *item,const char *str)
 
144
{
 
145
        const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
 
146
        if (*str!='\"') {ep=str;return 0;}      /* not a string! */
 
147
        
 
148
        while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;  /* Skip escaped quotes. */
 
149
        
 
150
        out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
 
151
        if (!out) return 0;
 
152
        
 
153
        ptr=str+1;ptr2=out;
 
154
        while (*ptr!='\"' && *ptr)
 
155
        {
 
156
                if (*ptr!='\\') *ptr2++=*ptr++;
 
157
                else
 
158
                {
 
159
                        ptr++;
 
160
                        switch (*ptr)
 
161
                        {
 
162
                                case 'b': *ptr2++='\b'; break;
 
163
                                case 'f': *ptr2++='\f'; break;
 
164
                                case 'n': *ptr2++='\n'; break;
 
165
                                case 'r': *ptr2++='\r'; break;
 
166
                                case 't': *ptr2++='\t'; break;
 
167
                                case 'u':        /* transcode utf16 to utf8. */
 
168
                                        sscanf(ptr+1,"%4x",&uc);ptr+=4; /* get the unicode char. */
 
169
 
 
170
                                        if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)        break;  // check for invalid.
 
171
 
 
172
                                        if (uc>=0xD800 && uc<=0xDBFF)   // UTF16 surrogate pairs.
 
173
                                        {
 
174
                                                if (ptr[1]!='\\' || ptr[2]!='u')        break;  // missing second-half of surrogate.
 
175
                                                sscanf(ptr+3,"%4x",&uc2);ptr+=6;
 
176
                                                if (uc2<0xDC00 || uc2>0xDFFF)           break;  // invalid second-half of surrogate.
 
177
                                                uc=0x10000 | ((uc&0x3FF)<<10) | (uc2&0x3FF);
 
178
                                        }
 
179
 
 
180
                                        len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
 
181
                                        
 
182
                                        switch (len) {
 
183
                                                case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
 
184
                                                case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
 
185
                                                case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
 
186
                                                case 1: *--ptr2 =(uc | firstByteMark[len]);
 
187
                                        }
 
188
                                        ptr2+=len;
 
189
                                        break;
 
190
                                default:  *ptr2++=*ptr; break;
 
191
                        }
 
192
                        ptr++;
 
193
                }
 
194
        }
 
195
        *ptr2=0;
 
196
        if (*ptr=='\"') ptr++;
 
197
        item->valuestring=out;
 
198
        item->type=cJSON_String;
 
199
        return ptr;
 
200
}
 
201
 
 
202
/* Render the cstring provided to an escaped version that can be printed. */
 
203
static char *print_string_ptr(const char *str)
 
204
{
 
205
        const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
 
206
        
 
207
        if (!str) return cJSON_strdup("");
 
208
        ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
 
209
        
 
210
        out=(char*)cJSON_malloc(len+3);
 
211
        if (!out) return 0;
 
212
 
 
213
        ptr2=out;ptr=str;
 
214
        *ptr2++='\"';
 
215
        while (*ptr)
 
216
        {
 
217
                if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
 
218
                else
 
219
                {
 
220
                        *ptr2++='\\';
 
221
                        switch (token=*ptr++)
 
222
                        {
 
223
                                case '\\':      *ptr2++='\\';   break;
 
224
                                case '\"':      *ptr2++='\"';   break;
 
225
                                case '\b':      *ptr2++='b';    break;
 
226
                                case '\f':      *ptr2++='f';    break;
 
227
                                case '\n':      *ptr2++='n';    break;
 
228
                                case '\r':      *ptr2++='r';    break;
 
229
                                case '\t':      *ptr2++='t';    break;
 
230
                                default: sprintf(ptr2,"u%04x",token);ptr2+=5;   break;  /* escape and print */
 
231
                        }
 
232
                }
 
233
        }
 
234
        *ptr2++='\"';*ptr2++=0;
 
235
        return out;
 
236
}
 
237
/* Invote print_string_ptr (which is useful) on an item. */
 
238
static char *print_string(cJSON *item)  {return print_string_ptr(item->valuestring);}
 
239
 
 
240
/* Predeclare these prototypes. */
 
241
static const char *parse_value(cJSON *item,const char *value);
 
242
static char *print_value(cJSON *item,int depth,int fmt);
 
243
static const char *parse_array(cJSON *item,const char *value);
 
244
static char *print_array(cJSON *item,int depth,int fmt);
 
245
static const char *parse_object(cJSON *item,const char *value);
 
246
static char *print_object(cJSON *item,int depth,int fmt);
 
247
 
 
248
/* Utility to jump whitespace and cr/lf */
 
249
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
 
250
 
 
251
/* Parse an object - create a new root, and populate. */
 
252
cJSON *cJSON_Parse(const char *value)
 
253
{
 
254
        cJSON *c=cJSON_New_Item();
 
255
        ep=0;
 
256
        if (!c) return 0;       /* memory fail */
 
257
 
 
258
        if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;}
 
259
        return c;
 
260
}
 
261
 
 
262
/* Render a cJSON item/entity/structure to text. */
 
263
char *cJSON_Print(cJSON *item)                          {return print_value(item,0,1);}
 
264
char *cJSON_PrintUnformatted(cJSON *item)       {return print_value(item,0,0);}
 
265
 
 
266
/* Parser core - when encountering text, process appropriately. */
 
267
static const char *parse_value(cJSON *item,const char *value)
 
268
{
 
269
        if (!value)                                             return 0;       /* Fail on null. */
 
270
        if (!strncmp(value,"null",4))   { item->type=cJSON_NULL;  return value+4; }
 
271
        if (!strncmp(value,"false",5))  { item->type=cJSON_False; return value+5; }
 
272
        if (!strncmp(value,"true",4))   { item->type=cJSON_True; item->valueint=1;      return value+4; }
 
273
        if (*value=='\"')                               { return parse_string(item,value); }
 
274
        if (*value=='-' || (*value>='0' && *value<='9'))        { return parse_number(item,value); }
 
275
        if (*value=='[')                                { return parse_array(item,value); }
 
276
        if (*value=='{')                                { return parse_object(item,value); }
 
277
 
 
278
        ep=value;return 0;      /* failure. */
 
279
}
 
280
 
 
281
/* Render a value to text. */
 
282
static char *print_value(cJSON *item,int depth,int fmt)
 
283
{
 
284
        char *out=0;
 
285
        if (!item) return 0;
 
286
        switch ((item->type)&255)
 
287
        {
 
288
                case cJSON_NULL:        out=cJSON_strdup("null");       break;
 
289
                case cJSON_False:       out=cJSON_strdup("false");break;
 
290
                case cJSON_True:        out=cJSON_strdup("true"); break;
 
291
                case cJSON_Number:      out=print_number(item);break;
 
292
                case cJSON_String:      out=print_string(item);break;
 
293
                case cJSON_Array:       out=print_array(item,depth,fmt);break;
 
294
                case cJSON_Object:      out=print_object(item,depth,fmt);break;
 
295
        }
 
296
        return out;
 
297
}
 
298
 
 
299
/* Build an array from input text. */
 
300
static const char *parse_array(cJSON *item,const char *value)
 
301
{
 
302
        cJSON *child;
 
303
        if (*value!='[')        {ep=value;return 0;}    /* not an array! */
 
304
 
 
305
        item->type=cJSON_Array;
 
306
        value=skip(value+1);
 
307
        if (*value==']') return value+1;        /* empty array. */
 
308
 
 
309
        item->child=child=cJSON_New_Item();
 
310
        if (!item->child) return 0;              /* memory fail */
 
311
        value=skip(parse_value(child,skip(value)));     /* skip any spacing, get the value. */
 
312
        if (!value) return 0;
 
313
 
 
314
        while (*value==',')
 
315
        {
 
316
                cJSON *new_item;
 
317
                if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */
 
318
                child->next=new_item;new_item->prev=child;child=new_item;
 
319
                value=skip(parse_value(child,skip(value+1)));
 
320
                if (!value) return 0;   /* memory fail */
 
321
        }
 
322
 
 
323
        if (*value==']') return value+1;        /* end of array */
 
324
        ep=value;return 0;      /* malformed. */
 
325
}
 
326
 
 
327
/* Render an array to text */
 
328
static char *print_array(cJSON *item,int depth,int fmt)
 
329
{
 
330
        char **entries;
 
331
        char *out=0,*ptr,*ret;int len=5;
 
332
        cJSON *child=item->child;
 
333
        int numentries=0,i=0,fail=0;
 
334
        
 
335
        /* How many entries in the array? */
 
336
        while (child) numentries++,child=child->next;
 
337
        /* Allocate an array to hold the values for each */
 
338
        entries=(char**)cJSON_malloc(numentries*sizeof(char*));
 
339
        if (!entries) return 0;
 
340
        memset(entries,0,numentries*sizeof(char*));
 
341
        /* Retrieve all the results: */
 
342
        child=item->child;
 
343
        while (child && !fail)
 
344
        {
 
345
                ret=print_value(child,depth+1,fmt);
 
346
                entries[i++]=ret;
 
347
                if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
 
348
                child=child->next;
 
349
        }
 
350
        
 
351
        /* If we didn't fail, try to malloc the output string */
 
352
        if (!fail) out=(char*)cJSON_malloc(len);
 
353
        /* If that fails, we fail. */
 
354
        if (!out) fail=1;
 
355
 
 
356
        /* Handle failure. */
 
357
        if (fail)
 
358
        {
 
359
                for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
 
360
                cJSON_free(entries);
 
361
                return 0;
 
362
        }
 
363
        
 
364
        /* Compose the output array. */
 
365
        *out='[';
 
366
        ptr=out+1;*ptr=0;
 
367
        for (i=0;i<numentries;i++)
 
368
        {
 
369
                strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
 
370
                if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
 
371
                cJSON_free(entries[i]);
 
372
        }
 
373
        cJSON_free(entries);
 
374
        *ptr++=']';*ptr++=0;
 
375
        return out;     
 
376
}
 
377
 
 
378
/* Build an object from the text. */
 
379
static const char *parse_object(cJSON *item,const char *value)
 
380
{
 
381
        cJSON *child;
 
382
        if (*value!='{')        {ep=value;return 0;}    /* not an object! */
 
383
        
 
384
        item->type=cJSON_Object;
 
385
        value=skip(value+1);
 
386
        if (*value=='}') return value+1;        /* empty array. */
 
387
        
 
388
        item->child=child=cJSON_New_Item();
 
389
        if (!item->child) return 0;
 
390
        value=skip(parse_string(child,skip(value)));
 
391
        if (!value) return 0;
 
392
        child->string=child->valuestring;child->valuestring=0;
 
393
        if (*value!=':') {ep=value;return 0;}   /* fail! */
 
394
        value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
 
395
        if (!value) return 0;
 
396
        
 
397
        while (*value==',')
 
398
        {
 
399
                cJSON *new_item;
 
400
                if (!(new_item=cJSON_New_Item()))       return 0; /* memory fail */
 
401
                child->next=new_item;new_item->prev=child;child=new_item;
 
402
                value=skip(parse_string(child,skip(value+1)));
 
403
                if (!value) return 0;
 
404
                child->string=child->valuestring;child->valuestring=0;
 
405
                if (*value!=':') {ep=value;return 0;}   /* fail! */
 
406
                value=skip(parse_value(child,skip(value+1)));   /* skip any spacing, get the value. */
 
407
                if (!value) return 0;
 
408
        }
 
409
        
 
410
        if (*value=='}') return value+1;        /* end of array */
 
411
        ep=value;return 0;      /* malformed. */
 
412
}
 
413
 
 
414
/* Render an object to text. */
 
415
static char *print_object(cJSON *item,int depth,int fmt)
 
416
{
 
417
        char **entries=0,**names=0;
 
418
        char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
 
419
        cJSON *child=item->child;
 
420
        int numentries=0,fail=0;
 
421
        /* Count the number of entries. */
 
422
        while (child) numentries++,child=child->next;
 
423
        /* Allocate space for the names and the objects */
 
424
        entries=(char**)cJSON_malloc(numentries*sizeof(char*));
 
425
        if (!entries) return 0;
 
426
        names=(char**)cJSON_malloc(numentries*sizeof(char*));
 
427
        if (!names) {cJSON_free(entries);return 0;}
 
428
        memset(entries,0,sizeof(char*)*numentries);
 
429
        memset(names,0,sizeof(char*)*numentries);
 
430
 
 
431
        /* Collect all the results into our arrays: */
 
432
        child=item->child;depth++;if (fmt) len+=depth;
 
433
        while (child)
 
434
        {
 
435
                names[i]=str=print_string_ptr(child->string);
 
436
                entries[i++]=ret=print_value(child,depth,fmt);
 
437
                if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
 
438
                child=child->next;
 
439
        }
 
440
        
 
441
        /* Try to allocate the output string */
 
442
        if (!fail) out=(char*)cJSON_malloc(len);
 
443
        if (!out) fail=1;
 
444
 
 
445
        /* Handle failure */
 
446
        if (fail)
 
447
        {
 
448
                for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
 
449
                cJSON_free(names);cJSON_free(entries);
 
450
                return 0;
 
451
        }
 
452
        
 
453
        /* Compose the output: */
 
454
        *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
 
455
        for (i=0;i<numentries;i++)
 
456
        {
 
457
                if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
 
458
                strcpy(ptr,names[i]);ptr+=strlen(names[i]);
 
459
                *ptr++=':';if (fmt) *ptr++='\t';
 
460
                strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
 
461
                if (i!=numentries-1) *ptr++=',';
 
462
                if (fmt) *ptr++='\n';*ptr=0;
 
463
                cJSON_free(names[i]);cJSON_free(entries[i]);
 
464
        }
 
465
        
 
466
        cJSON_free(names);cJSON_free(entries);
 
467
        if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
 
468
        *ptr++='}';*ptr++=0;
 
469
        return out;     
 
470
}
 
471
 
 
472
/* Get Array size/item / object item. */
 
473
int    cJSON_GetArraySize(cJSON *array)                                                 {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
 
474
cJSON *cJSON_GetArrayItem(cJSON *array,int item)                                {cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
 
475
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)    {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
 
476
 
 
477
/* Utility for array list handling. */
 
478
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
 
479
/* Utility for handling references. */
 
480
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;}
 
481
 
 
482
/* Add item to array/object. */
 
483
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);}}
 
484
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);}
 
485
void    cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)                                                {cJSON_AddItemToArray(array,create_reference(item));}
 
486
void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)    {cJSON_AddItemToObject(object,string,create_reference(item));}
 
487
 
 
488
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)                        {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
 
489
        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;}
 
490
void   cJSON_DeleteItemFromArray(cJSON *array,int which)                        {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
 
491
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;}
 
492
void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
 
493
 
 
494
/* Replace array/object items with new ones. */
 
495
void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)          {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
 
496
        newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
 
497
        if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
 
498
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);}}
 
499
 
 
500
/* Create basic types: */
 
501
cJSON *cJSON_CreateNull()                                               {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
 
502
cJSON *cJSON_CreateTrue()                                               {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
 
503
cJSON *cJSON_CreateFalse()                                              {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
 
504
cJSON *cJSON_CreateBool(int b)                                  {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
 
505
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;}
 
506
cJSON *cJSON_CreateString(const char *string)   {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
 
507
cJSON *cJSON_CreateArray()                                              {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
 
508
cJSON *cJSON_CreateObject()                                             {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
 
509
 
 
510
/* Create Arrays: */
 
511
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;}
 
512
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;}
 
513
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;}
 
514
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;}