1 //////////////////////////////////////////////////////////////////////////////
2 //////////////////////////////////////////////////////////////////////////////
3 //
4 // copyright : (C) 2014 Eran Ifrah
5 // file name : cJSON.cpp
6 //
7 // -------------------------------------------------------------------------
8 //
9 // This program is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 //////////////////////////////////////////////////////////////////////////////
15 //////////////////////////////////////////////////////////////////////////////
16
17 /*
18 Copyright (c) 2009 Dave Gamble
19
20 Permission is hereby granted, free of charge, to any person obtaining a copy
21 of this software and associated documentation files (the "Software"), to deal
22 in the Software without restriction, including without limitation the rights
23 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 copies of the Software, and to permit persons to whom the Software is
25 furnished to do so, subject to the following conditions:
26
27 The above copyright notice and this permission notice shall be included in
28 all copies or substantial portions of the Software.
29
30 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 THE SOFTWARE.
37 */
38
39 /* cJSON */
40 /* JSON parser in C. */
41
42 #include <string.h>
43 #include <stdio.h>
44 #include <math.h>
45 #include <stdlib.h>
46 #include <float.h>
47 #include <limits.h>
48 #include <ctype.h>
49 #include "cJSON.h"
50
51 static const char* ep;
52 #define FMT_WHITESPACE_CHAR ' '
53
cJSON_GetErrorPtr()54 const char* cJSON_GetErrorPtr()
55 {
56 return ep;
57 }
58
cJSON_strcasecmp(const char * s1,const char * s2)59 static int cJSON_strcasecmp(const char* s1, const char* s2)
60 {
61 if(!s1)
62 return (s1 == s2) ? 0 : 1;
63 if(!s2)
64 return 1;
65 for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)
66 if(*s1 == 0)
67 return 0;
68 return tolower(*(const unsigned char*)s1) - tolower(*(const unsigned char*)s2);
69 }
70
71 static void* (*cJSON_malloc)(size_t sz) = malloc;
72 static void (*cJSON_free)(void* ptr) = free;
73
cJSON_strdup(const char * str)74 static char* cJSON_strdup(const char* str)
75 {
76 size_t len;
77 char* copy;
78
79 len = strlen(str) + 1;
80 if(!(copy = (char*)cJSON_malloc(len)))
81 return 0;
82 memcpy(copy, str, len);
83 return copy;
84 }
85
cJSON_InitHooks(cJSON_Hooks * hooks)86 void cJSON_InitHooks(cJSON_Hooks* hooks)
87 {
88 if(!hooks) { /* Reset hooks */
89 cJSON_malloc = malloc;
90 cJSON_free = free;
91 return;
92 }
93
94 cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
95 cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
96 }
97
98 /* Internal constructor. */
cJSON_New_Item()99 static cJSON* cJSON_New_Item()
100 {
101 cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
102 if(node)
103 memset(node, 0, sizeof(cJSON));
104 return node;
105 }
106
107 /* Delete a cJSON structure. */
cJSON_Delete(cJSON * c)108 void cJSON_Delete(cJSON* c)
109 {
110 cJSON* next;
111 while(c) {
112 next = c->next;
113 if(!(c->type & cJSON_IsReference) && c->child)
114 cJSON_Delete(c->child);
115 if(!(c->type & cJSON_IsReference) && c->valuestring)
116 cJSON_free(c->valuestring);
117 if(c->string)
118 cJSON_free(c->string);
119 cJSON_free(c);
120 c = next;
121 }
122 }
123
124 /* Parse the input text to generate a number, and populate the result into item. */
parse_number(cJSON * item,const char * num)125 static const char* parse_number(cJSON* item, const char* num)
126 {
127 double n = 0, sign = 1, scale = 0;
128 int subscale = 0, signsubscale = 1;
129
130 /* Could use sscanf for this? */
131 if(*num == '-')
132 sign = -1, num++; /* Has sign? */
133 if(*num == '0')
134 num++; /* is zero */
135 if(*num >= '1' && *num <= '9')
136 do
137 n = (n * 10.0) + (*num++ - '0');
138 while(*num >= '0' && *num <= '9'); /* Number? */
139 if(*num == '.' && num[1] >= '0' && num[1] <= '9') {
140 num++;
141 do
142 n = (n * 10.0) + (*num++ - '0'), scale--;
143 while(*num >= '0' && *num <= '9');
144 } /* Fractional part? */
145 if(*num == 'e' || *num == 'E') /* Exponent? */
146 {
147 num++;
148 if(*num == '+')
149 num++;
150 else if(*num == '-')
151 signsubscale = -1, num++; /* With sign? */
152 while(*num >= '0' && *num <= '9')
153 subscale = (subscale * 10) + (*num++ - '0'); /* Number? */
154 }
155
156 n = sign * n * pow(10.0, (scale + subscale * signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
157
158 item->valuedouble = n;
159 item->valueint = (int)n;
160 item->type = cJSON_Number;
161 return num;
162 }
163
164 /* Render the number nicely from the given item into a string. */
print_number(cJSON * item)165 static char* print_number(cJSON* item)
166 {
167 char* str;
168 double d = item->valuedouble;
169 if(fabs(((double)item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) {
170 str = (char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
171 if(str)
172 sprintf(str, "%d", item->valueint);
173 } else {
174 str = (char*)cJSON_malloc(64); /* This is a nice tradeoff. */
175 if(str) {
176 if(fabs(floor(d) - d) <= DBL_EPSILON)
177 sprintf(str, "%.0f", d);
178 else if(fabs(d) < 1.0e-6 || fabs(d) > 1.0e9)
179 sprintf(str, "%e", d);
180 else
181 sprintf(str, "%f", d);
182 }
183 }
184 return str;
185 }
186
187 /* Parse the input text into an unescaped cstring, and populate item. */
188 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
parse_string(cJSON * item,const char * str)189 static const char* parse_string(cJSON* item, const char* str)
190 {
191 const char* ptr = str + 1;
192 char* ptr2;
193 char* out;
194 int len = 0;
195 unsigned uc, uc2;
196 if(*str != '\"') {
197 ep = str;
198 return 0;
199 } /* not a string! */
200
201 while(*ptr != '\"' && *ptr && ++len)
202 if(*ptr++ == '\\')
203 ptr++; /* Skip escaped quotes. */
204
205 out = (char*)cJSON_malloc(len + 1); /* This is how long we need for the string, roughly. */
206 if(!out)
207 return 0;
208
209 ptr = str + 1;
210 ptr2 = out;
211 while(*ptr != '\"' && *ptr) {
212 if(*ptr != '\\')
213 *ptr2++ = *ptr++;
214 else {
215 ptr++;
216 switch(*ptr) {
217 case 'b':
218 *ptr2++ = '\b';
219 break;
220 case 'f':
221 *ptr2++ = '\f';
222 break;
223 case 'n':
224 *ptr2++ = '\n';
225 break;
226 case 'r':
227 *ptr2++ = '\r';
228 break;
229 case 't':
230 *ptr2++ = '\t';
231 break;
232 case 'u': /* transcode utf16 to utf8. */
233 sscanf(ptr + 1, "%4x", &uc);
234 ptr += 4; /* get the unicode char. */
235
236 if((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0)
237 break; // check for invalid.
238
239 if(uc >= 0xD800 && uc <= 0xDBFF) // UTF16 surrogate pairs.
240 {
241 if(ptr[1] != '\\' || ptr[2] != 'u')
242 break; // missing second-half of surrogate.
243 sscanf(ptr + 3, "%4x", &uc2);
244 ptr += 6;
245 if(uc2 < 0xDC00 || uc2 > 0xDFFF)
246 break; // invalid second-half of surrogate.
247 uc = 0x10000 | ((uc & 0x3FF) << 10) | (uc2 & 0x3FF);
248 }
249
250 len = 4;
251 if(uc < 0x80)
252 len = 1;
253 else if(uc < 0x800)
254 len = 2;
255 else if(uc < 0x10000)
256 len = 3;
257 ptr2 += len;
258
259 switch(len) {
260 case 4:
261 *--ptr2 = ((uc | 0x80) & 0xBF);
262 uc >>= 6;
263 case 3:
264 *--ptr2 = ((uc | 0x80) & 0xBF);
265 uc >>= 6;
266 case 2:
267 *--ptr2 = ((uc | 0x80) & 0xBF);
268 uc >>= 6;
269 case 1:
270 *--ptr2 = (uc | firstByteMark[len]);
271 }
272 ptr2 += len;
273 break;
274 default:
275 *ptr2++ = *ptr;
276 break;
277 }
278 ptr++;
279 }
280 }
281 *ptr2 = 0;
282 if(*ptr == '\"')
283 ptr++;
284 item->valuestring = out;
285 item->type = cJSON_String;
286 return ptr;
287 }
288
289 /* Render the cstring provided to an escaped version that can be printed. */
print_string_ptr(const char * str)290 static char* print_string_ptr(const char* str)
291 {
292 const char* ptr;
293 char* ptr2, *out;
294 int len = 0;
295 unsigned char token;
296
297 if(!str)
298 return cJSON_strdup("");
299 ptr = str;
300 while((token = *ptr) && ++len) {
301 if(strchr("\"\\\b\f\n\r\t", token))
302 len++;
303 else if(token < 32)
304 len += 5;
305 ptr++;
306 }
307
308 out = (char*)cJSON_malloc(len + 3);
309 if(!out)
310 return 0;
311
312 ptr2 = out;
313 ptr = str;
314 *ptr2++ = '\"';
315 while(*ptr) {
316 if((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
317 *ptr2++ = *ptr++;
318 else {
319 *ptr2++ = '\\';
320 switch(token = *ptr++) {
321 case '\\':
322 *ptr2++ = '\\';
323 break;
324 case '\"':
325 *ptr2++ = '\"';
326 break;
327 case '\b':
328 *ptr2++ = 'b';
329 break;
330 case '\f':
331 *ptr2++ = 'f';
332 break;
333 case '\n':
334 *ptr2++ = 'n';
335 break;
336 case '\r':
337 *ptr2++ = 'r';
338 break;
339 case '\t':
340 *ptr2++ = 't';
341 break;
342 default:
343 sprintf(ptr2, "u%04x", token);
344 ptr2 += 5;
345 break; /* escape and print */
346 }
347 }
348 }
349 *ptr2++ = '\"';
350 *ptr2++ = 0;
351 return out;
352 }
353 /* Invote print_string_ptr (which is useful) on an item. */
print_string(cJSON * item)354 static char* print_string(cJSON* item)
355 {
356 return print_string_ptr(item->valuestring);
357 }
358
359 /* Predeclare these prototypes. */
360 static const char* parse_value(cJSON* item, const char* value);
361 static char* print_value(cJSON* item, int depth, int fmt);
362 static const char* parse_array(cJSON* item, const char* value);
363 static char* print_array(cJSON* item, int depth, int fmt);
364 static const char* parse_object(cJSON* item, const char* value);
365 static char* print_object(cJSON* item, int depth, int fmt);
366
367 /* Utility to jump whitespace and cr/lf */
skip(const char * in)368 static const char* skip(const char* in)
369 {
370 while(in && *in && (unsigned char)*in <= 32)
371 in++;
372 return in;
373 }
374
375 /* Parse an object - create a new root, and populate. */
cJSON_Parse(const char * value)376 cJSON* cJSON_Parse(const char* value)
377 {
378 cJSON* c = cJSON_New_Item();
379 ep = 0;
380 if(!c)
381 return 0; /* memory fail */
382
383 if(!parse_value(c, skip(value))) {
384 cJSON_Delete(c);
385 return 0;
386 }
387 return c;
388 }
389
390 /* Render a cJSON item/entity/structure to text. */
cJSON_Print(cJSON * item)391 char* cJSON_Print(cJSON* item)
392 {
393 return print_value(item, 0, 1);
394 }
cJSON_PrintUnformatted(cJSON * item)395 char* cJSON_PrintUnformatted(cJSON* item)
396 {
397 return print_value(item, 0, 0);
398 }
399
400 /* Parser core - when encountering text, process appropriately. */
parse_value(cJSON * item,const char * value)401 static const char* parse_value(cJSON* item, const char* value)
402 {
403 if(!value)
404 return 0; /* Fail on null. */
405 if(!strncmp(value, "null", 4)) {
406 item->type = cJSON_NULL;
407 return value + 4;
408 }
409 if(!strncmp(value, "false", 5)) {
410 item->type = cJSON_False;
411 return value + 5;
412 }
413 if(!strncmp(value, "true", 4)) {
414 item->type = cJSON_True;
415 item->valueint = 1;
416 return value + 4;
417 }
418 if(*value == '\"') {
419 return parse_string(item, value);
420 }
421 if(*value == '-' || (*value >= '0' && *value <= '9')) {
422 return parse_number(item, value);
423 }
424 if(*value == '[') {
425 return parse_array(item, value);
426 }
427 if(*value == '{') {
428 return parse_object(item, value);
429 }
430
431 ep = value;
432 return 0; /* failure. */
433 }
434
435 /* Render a value to text. */
print_value(cJSON * item,int depth,int fmt)436 static char* print_value(cJSON* item, int depth, int fmt)
437 {
438 char* out = 0;
439 if(!item)
440 return 0;
441 switch((item->type) & 255) {
442 case cJSON_NULL:
443 out = cJSON_strdup("null");
444 break;
445 case cJSON_False:
446 out = cJSON_strdup("false");
447 break;
448 case cJSON_True:
449 out = cJSON_strdup("true");
450 break;
451 case cJSON_Number:
452 out = print_number(item);
453 break;
454 case cJSON_String:
455 out = print_string(item);
456 break;
457 case cJSON_Array:
458 out = print_array(item, depth, fmt);
459 break;
460 case cJSON_Object:
461 out = print_object(item, depth, fmt);
462 break;
463 }
464 return out;
465 }
466
467 /* Build an array from input text. */
parse_array(cJSON * item,const char * value)468 static const char* parse_array(cJSON* item, const char* value)
469 {
470 cJSON* child;
471 if(*value != '[') {
472 ep = value;
473 return 0;
474 } /* not an array! */
475
476 item->type = cJSON_Array;
477 value = skip(value + 1);
478 if(*value == ']')
479 return value + 1; /* empty array. */
480
481 item->child = child = cJSON_New_Item();
482 if(!item->child)
483 return 0; /* memory fail */
484 value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */
485 if(!value)
486 return 0;
487
488 while(*value == ',') {
489 cJSON* new_item;
490 if(!(new_item = cJSON_New_Item()))
491 return 0; /* memory fail */
492 child->next = new_item;
493 new_item->prev = child;
494 child = new_item;
495 value = skip(parse_value(child, skip(value + 1)));
496 if(!value)
497 return 0; /* memory fail */
498 }
499
500 if(*value == ']')
501 return value + 1; /* end of array */
502 ep = value;
503 return 0; /* malformed. */
504 }
505
506 /* Render an array to text */
print_array(cJSON * item,int depth,int fmt)507 static char* print_array(cJSON* item, int depth, int fmt)
508 {
509 char** entries;
510 char* out = 0, *ptr, *ret;
511 int len = 5;
512 cJSON* child = item->child;
513 int numentries = 0, i = 0, fail = 0;
514
515 /* How many entries in the array? */
516 while(child)
517 numentries++, child = child->next;
518 /* Allocate an array to hold the values for each */
519 entries = (char**)cJSON_malloc(numentries * sizeof(char*));
520 if(!entries)
521 return 0;
522 memset(entries, 0, numentries * sizeof(char*));
523 /* Retrieve all the results: */
524 child = item->child;
525 while(child && !fail) {
526 ret = print_value(child, depth + 1, fmt);
527 entries[i++] = ret;
528 if(ret)
529 len += strlen(ret) + 2 + (fmt ? 1 : 0);
530 else
531 fail = 1;
532 child = child->next;
533 }
534
535 /* If we didn't fail, try to malloc the output string */
536 if(!fail)
537 out = (char*)cJSON_malloc(len);
538 /* If that fails, we fail. */
539 if(!out)
540 fail = 1;
541
542 /* Handle failure. */
543 if(fail) {
544 for(i = 0; i < numentries; i++)
545 if(entries[i])
546 cJSON_free(entries[i]);
547 cJSON_free(entries);
548 return 0;
549 }
550
551 /* Compose the output array. */
552 *out = '[';
553 ptr = out + 1;
554 *ptr = 0;
555 for(i = 0; i < numentries; i++) {
556 strcpy(ptr, entries[i]);
557 ptr += strlen(entries[i]);
558 if(i != numentries - 1) {
559 *ptr++ = ',';
560 if(fmt)
561 *ptr++ = ' ';
562 *ptr = 0;
563 }
564 cJSON_free(entries[i]);
565 }
566 cJSON_free(entries);
567 *ptr++ = ']';
568 *ptr++ = 0;
569 return out;
570 }
571
572 /* Build an object from the text. */
parse_object(cJSON * item,const char * value)573 static const char* parse_object(cJSON* item, const char* value)
574 {
575 cJSON* child;
576 if(*value != '{') {
577 ep = value;
578 return 0;
579 } /* not an object! */
580
581 item->type = cJSON_Object;
582 value = skip(value + 1);
583 if(*value == '}')
584 return value + 1; /* empty array. */
585
586 item->child = child = cJSON_New_Item();
587 if(!item->child)
588 return 0;
589 value = skip(parse_string(child, skip(value)));
590 if(!value)
591 return 0;
592 child->string = child->valuestring;
593 child->valuestring = 0;
594 if(*value != ':') {
595 ep = value;
596 return 0;
597 } /* fail! */
598 value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
599 if(!value)
600 return 0;
601
602 while(*value == ',') {
603 cJSON* new_item;
604 if(!(new_item = cJSON_New_Item()))
605 return 0; /* memory fail */
606 child->next = new_item;
607 new_item->prev = child;
608 child = new_item;
609 value = skip(parse_string(child, skip(value + 1)));
610 if(!value)
611 return 0;
612 child->string = child->valuestring;
613 child->valuestring = 0;
614 if(*value != ':') {
615 ep = value;
616 return 0;
617 } /* fail! */
618 value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
619 if(!value)
620 return 0;
621 }
622
623 if(*value == '}')
624 return value + 1; /* end of array */
625 ep = value;
626 return 0; /* malformed. */
627 }
628
629 /* Render an object to text. */
print_object(cJSON * item,int depth,int fmt)630 static char* print_object(cJSON* item, int depth, int fmt)
631 {
632 char** entries = 0, **names = 0;
633 char* out = 0, *ptr, *ret, *str;
634 int len = 7, i = 0, j;
635 cJSON* child = item->child;
636 int numentries = 0, fail = 0;
637 /* Count the number of entries. */
638 while(child)
639 numentries++, child = child->next;
640 /* Allocate space for the names and the objects */
641 entries = (char**)cJSON_malloc(numentries * sizeof(char*));
642 if(!entries)
643 return 0;
644 names = (char**)cJSON_malloc(numentries * sizeof(char*));
645 if(!names) {
646 cJSON_free(entries);
647 return 0;
648 }
649 memset(entries, 0, sizeof(char*) * numentries);
650 memset(names, 0, sizeof(char*) * numentries);
651
652 /* Collect all the results into our arrays: */
653 child = item->child;
654 depth++;
655 if(fmt)
656 len += depth;
657 while(child) {
658 names[i] = str = print_string_ptr(child->string);
659 entries[i++] = ret = print_value(child, depth, fmt);
660 if(str && ret)
661 len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
662 else
663 fail = 1;
664 child = child->next;
665 }
666
667 /* Try to allocate the output string */
668 if(!fail)
669 out = (char*)cJSON_malloc(len);
670 if(!out)
671 fail = 1;
672
673 /* Handle failure */
674 if(fail) {
675 for(i = 0; i < numentries; i++) {
676 if(names[i])
677 cJSON_free(names[i]);
678 if(entries[i])
679 cJSON_free(entries[i]);
680 }
681 cJSON_free(names);
682 cJSON_free(entries);
683 return 0;
684 }
685
686 /* Compose the output: */
687 *out = '{';
688 ptr = out + 1;
689 if(fmt)
690 *ptr++ = '\n';
691 *ptr = 0;
692 for(i = 0; i < numentries; i++) {
693 if(fmt)
694 for(j = 0; j < depth; j++)
695 *ptr++ = FMT_WHITESPACE_CHAR;
696 strcpy(ptr, names[i]);
697 ptr += strlen(names[i]);
698 *ptr++ = ':';
699 if(fmt)
700 *ptr++ = FMT_WHITESPACE_CHAR;
701 strcpy(ptr, entries[i]);
702 ptr += strlen(entries[i]);
703 if(i != numentries - 1)
704 *ptr++ = ',';
705 if(fmt)
706 *ptr++ = '\n';
707 *ptr = 0;
708 cJSON_free(names[i]);
709 cJSON_free(entries[i]);
710 }
711
712 cJSON_free(names);
713 cJSON_free(entries);
714 if(fmt)
715 for(i = 0; i < depth - 1; i++)
716 *ptr++ = FMT_WHITESPACE_CHAR;
717 *ptr++ = '}';
718 *ptr++ = 0;
719 return out;
720 }
721
722 /* Get Array size/item / object item. */
cJSON_GetArraySize(cJSON * array)723 int cJSON_GetArraySize(cJSON* array)
724 {
725 cJSON* c = array->child;
726 int i = 0;
727 while(c)
728 i++, c = c->next;
729 return i;
730 }
cJSON_GetArrayItem(cJSON * array,int item)731 cJSON* cJSON_GetArrayItem(cJSON* array, int item)
732 {
733 cJSON* c = array->child;
734 while(c && item > 0)
735 item--, c = c->next;
736 return c;
737 }
cJSON_GetObjectItem(cJSON * object,const char * string)738 cJSON* cJSON_GetObjectItem(cJSON* object, const char* string)
739 {
740 cJSON* c = object->child;
741 while(c && cJSON_strcasecmp(c->string, string))
742 c = c->next;
743 return c;
744 }
745
746 /* Utility for array list handling. */
suffix_object(cJSON * prev,cJSON * item)747 static void suffix_object(cJSON* prev, cJSON* item)
748 {
749 prev->next = item;
750 item->prev = prev;
751 }
752 /* Utility for handling references. */
create_reference(cJSON * item)753 static cJSON* create_reference(cJSON* item)
754 {
755 cJSON* ref = cJSON_New_Item();
756 if(!ref)
757 return 0;
758 memcpy(ref, item, sizeof(cJSON));
759 ref->string = 0;
760 ref->type |= cJSON_IsReference;
761 ref->next = ref->prev = 0;
762 return ref;
763 }
764
765 /* Add item to array/object. */
cJSON_AddItemToArray(cJSON * array,cJSON * item)766 void cJSON_AddItemToArray(cJSON* array, cJSON* item)
767 {
768 cJSON* c = array->child;
769 if(!item)
770 return;
771 if(!c) {
772 array->child = item;
773 } else {
774 while(c && c->next)
775 c = c->next;
776 suffix_object(c, item);
777 }
778 }
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)779 void cJSON_AddItemToObject(cJSON* object, const char* string, cJSON* item)
780 {
781 if(!item)
782 return;
783 if(item->string)
784 cJSON_free(item->string);
785 item->string = cJSON_strdup(string);
786 cJSON_AddItemToArray(object, item);
787 }
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)788 void cJSON_AddItemReferenceToArray(cJSON* array, cJSON* item)
789 {
790 cJSON_AddItemToArray(array, create_reference(item));
791 }
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)792 void cJSON_AddItemReferenceToObject(cJSON* object, const char* string, cJSON* item)
793 {
794 cJSON_AddItemToObject(object, string, create_reference(item));
795 }
796
cJSON_DetachItemFromArray(cJSON * array,int which)797 cJSON* cJSON_DetachItemFromArray(cJSON* array, int which)
798 {
799 cJSON* c = array->child;
800 while(c && which > 0)
801 c = c->next, which--;
802 if(!c)
803 return 0;
804 if(c->prev)
805 c->prev->next = c->next;
806 if(c->next)
807 c->next->prev = c->prev;
808 if(c == array->child)
809 array->child = c->next;
810 c->prev = c->next = 0;
811 return c;
812 }
cJSON_DeleteItemFromArray(cJSON * array,int which)813 void cJSON_DeleteItemFromArray(cJSON* array, int which)
814 {
815 cJSON_Delete(cJSON_DetachItemFromArray(array, which));
816 }
cJSON_DetachItemFromObject(cJSON * object,const char * string)817 cJSON* cJSON_DetachItemFromObject(cJSON* object, const char* string)
818 {
819 int i = 0;
820 cJSON* c = object->child;
821 while(c && cJSON_strcasecmp(c->string, string))
822 i++, c = c->next;
823 if(c)
824 return cJSON_DetachItemFromArray(object, i);
825 return 0;
826 }
cJSON_DeleteItemFromObject(cJSON * object,const char * string)827 void cJSON_DeleteItemFromObject(cJSON* object, const char* string)
828 {
829 cJSON_Delete(cJSON_DetachItemFromObject(object, string));
830 }
831
832 /* Replace array/object items with new ones. */
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)833 void cJSON_ReplaceItemInArray(cJSON* array, int which, cJSON* newitem)
834 {
835 cJSON* c = array->child;
836 while(c && which > 0)
837 c = c->next, which--;
838 if(!c)
839 return;
840 newitem->next = c->next;
841 newitem->prev = c->prev;
842 if(newitem->next)
843 newitem->next->prev = newitem;
844 if(c == array->child)
845 array->child = newitem;
846 else
847 newitem->prev->next = newitem;
848 c->next = c->prev = 0;
849 cJSON_Delete(c);
850 }
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)851 void cJSON_ReplaceItemInObject(cJSON* object, const char* string, cJSON* newitem)
852 {
853 int i = 0;
854 cJSON* c = object->child;
855 while(c && cJSON_strcasecmp(c->string, string))
856 i++, c = c->next;
857 if(c) {
858 newitem->string = cJSON_strdup(string);
859 cJSON_ReplaceItemInArray(object, i, newitem);
860 }
861 }
862
863 /* Create basic types: */
cJSON_CreateNull()864 cJSON* cJSON_CreateNull()
865 {
866 cJSON* item = cJSON_New_Item();
867 if(item)
868 item->type = cJSON_NULL;
869 return item;
870 }
cJSON_CreateTrue()871 cJSON* cJSON_CreateTrue()
872 {
873 cJSON* item = cJSON_New_Item();
874 if(item)
875 item->type = cJSON_True;
876 return item;
877 }
cJSON_CreateFalse()878 cJSON* cJSON_CreateFalse()
879 {
880 cJSON* item = cJSON_New_Item();
881 if(item)
882 item->type = cJSON_False;
883 return item;
884 }
cJSON_CreateBool(int b)885 cJSON* cJSON_CreateBool(int b)
886 {
887 cJSON* item = cJSON_New_Item();
888 if(item)
889 item->type = b ? cJSON_True : cJSON_False;
890 return item;
891 }
cJSON_CreateNumber(double num)892 cJSON* cJSON_CreateNumber(double num)
893 {
894 cJSON* item = cJSON_New_Item();
895 if(item) {
896 item->type = cJSON_Number;
897 item->valuedouble = num;
898 item->valueint = (int)num;
899 }
900 return item;
901 }
cJSON_CreateString(const char * string)902 cJSON* cJSON_CreateString(const char* string)
903 {
904 cJSON* item = cJSON_New_Item();
905 if(item) {
906 item->type = cJSON_String;
907 item->valuestring = cJSON_strdup(string);
908 }
909 return item;
910 }
cJSON_CreateArray()911 cJSON* cJSON_CreateArray()
912 {
913 cJSON* item = cJSON_New_Item();
914 if(item)
915 item->type = cJSON_Array;
916 return item;
917 }
cJSON_CreateObject()918 cJSON* cJSON_CreateObject()
919 {
920 cJSON* item = cJSON_New_Item();
921 if(item)
922 item->type = cJSON_Object;
923 return item;
924 }
925
926 /* Create Arrays: */
cJSON_CreateIntArray(int * numbers,int count)927 cJSON* cJSON_CreateIntArray(int* numbers, int count)
928 {
929 int i;
930 cJSON* n = 0, *p = 0, *a = cJSON_CreateArray();
931 for(i = 0; a && i < count; i++) {
932 n = cJSON_CreateNumber(numbers[i]);
933 if(!i)
934 a->child = n;
935 else
936 suffix_object(p, n);
937 p = n;
938 }
939 return a;
940 }
cJSON_CreateFloatArray(float * numbers,int count)941 cJSON* cJSON_CreateFloatArray(float* numbers, int count)
942 {
943 int i;
944 cJSON* n = 0, *p = 0, *a = cJSON_CreateArray();
945 for(i = 0; a && i < count; i++) {
946 n = cJSON_CreateNumber(numbers[i]);
947 if(!i)
948 a->child = n;
949 else
950 suffix_object(p, n);
951 p = n;
952 }
953 return a;
954 }
cJSON_CreateDoubleArray(double * numbers,int count)955 cJSON* cJSON_CreateDoubleArray(double* numbers, int count)
956 {
957 int i;
958 cJSON* n = 0, *p = 0, *a = cJSON_CreateArray();
959 for(i = 0; a && i < count; i++) {
960 n = cJSON_CreateNumber(numbers[i]);
961 if(!i)
962 a->child = n;
963 else
964 suffix_object(p, n);
965 p = n;
966 }
967 return a;
968 }
cJSON_CreateStringArray(const char ** strings,int count)969 cJSON* cJSON_CreateStringArray(const char** strings, int count)
970 {
971 int i;
972 cJSON* n = 0, *p = 0, *a = cJSON_CreateArray();
973 for(i = 0; a && i < count; i++) {
974 n = cJSON_CreateString(strings[i]);
975 if(!i)
976 a->child = n;
977 else
978 suffix_object(p, n);
979 p = n;
980 }
981 return a;
982 }
983