webxos commited on
Commit
fc54d85
·
verified ·
1 Parent(s): b0e7917

Delete cJSON.c

Browse files
Files changed (1) hide show
  1. cJSON.c +0 -3174
cJSON.c DELETED
@@ -1,3174 +0,0 @@
1
- /*
2
- Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
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
- /* disable warnings about old C89 functions in MSVC */
27
- #if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
28
- #define _CRT_SECURE_NO_DEPRECATE
29
- #endif
30
-
31
- #ifdef __GNUC__
32
- #pragma GCC visibility push(default)
33
- #endif
34
- #if defined(_MSC_VER)
35
- #pragma warning (push)
36
- /* disable warning about single line comments in system headers */
37
- #pragma warning (disable : 4001)
38
- #endif
39
-
40
- #include <string.h>
41
- #include <stdio.h>
42
- #include <math.h>
43
- #include <stdlib.h>
44
- #include <limits.h>
45
- #include <ctype.h>
46
- #include <float.h>
47
-
48
- #ifdef ENABLE_LOCALES
49
- #include <locale.h>
50
- #endif
51
-
52
- #if defined(_MSC_VER)
53
- #pragma warning (pop)
54
- #endif
55
- #ifdef __GNUC__
56
- #pragma GCC visibility pop
57
- #endif
58
-
59
- #include "cJSON.h"
60
-
61
- /* define our own boolean type */
62
- #ifdef true
63
- #undef true
64
- #endif
65
- #define true ((cJSON_bool)1)
66
-
67
- #ifdef false
68
- #undef false
69
- #endif
70
- #define false ((cJSON_bool)0)
71
-
72
- /* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
73
- #ifndef isinf
74
- #define isinf(d) (isnan((d - d)) && !isnan(d))
75
- #endif
76
- #ifndef isnan
77
- #define isnan(d) (d != d)
78
- #endif
79
-
80
- #ifndef NAN
81
- #ifdef _WIN32
82
- #define NAN sqrt(-1.0)
83
- #else
84
- #define NAN 0.0/0.0
85
- #endif
86
- #endif
87
-
88
- typedef struct {
89
- const unsigned char *json;
90
- size_t position;
91
- } error;
92
- static error global_error = { NULL, 0 };
93
-
94
- CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
95
- {
96
- return (const char*) (global_error.json + global_error.position);
97
- }
98
-
99
- CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
100
- {
101
- if (!cJSON_IsString(item))
102
- {
103
- return NULL;
104
- }
105
-
106
- return item->valuestring;
107
- }
108
-
109
- CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
110
- {
111
- if (!cJSON_IsNumber(item))
112
- {
113
- return (double) NAN;
114
- }
115
-
116
- return item->valuedouble;
117
- }
118
-
119
- /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
120
- #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18)
121
- #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
122
- #endif
123
-
124
- CJSON_PUBLIC(const char*) cJSON_Version(void)
125
- {
126
- static char version[15];
127
- sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
128
-
129
- return version;
130
- }
131
-
132
- /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
133
- static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
134
- {
135
- if ((string1 == NULL) || (string2 == NULL))
136
- {
137
- return 1;
138
- }
139
-
140
- if (string1 == string2)
141
- {
142
- return 0;
143
- }
144
-
145
- for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
146
- {
147
- if (*string1 == '\0')
148
- {
149
- return 0;
150
- }
151
- }
152
-
153
- return tolower(*string1) - tolower(*string2);
154
- }
155
-
156
- typedef struct internal_hooks
157
- {
158
- void *(CJSON_CDECL *allocate)(size_t size);
159
- void (CJSON_CDECL *deallocate)(void *pointer);
160
- void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
161
- } internal_hooks;
162
-
163
- #if defined(_MSC_VER)
164
- /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
165
- static void * CJSON_CDECL internal_malloc(size_t size)
166
- {
167
- return malloc(size);
168
- }
169
- static void CJSON_CDECL internal_free(void *pointer)
170
- {
171
- free(pointer);
172
- }
173
- static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
174
- {
175
- return realloc(pointer, size);
176
- }
177
- #else
178
- #define internal_malloc malloc
179
- #define internal_free free
180
- #define internal_realloc realloc
181
- #endif
182
-
183
- /* strlen of character literals resolved at compile time */
184
- #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
185
-
186
- static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
187
-
188
- static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
189
- {
190
- size_t length = 0;
191
- unsigned char *copy = NULL;
192
-
193
- if (string == NULL)
194
- {
195
- return NULL;
196
- }
197
-
198
- length = strlen((const char*)string) + sizeof("");
199
- copy = (unsigned char*)hooks->allocate(length);
200
- if (copy == NULL)
201
- {
202
- return NULL;
203
- }
204
- memcpy(copy, string, length);
205
-
206
- return copy;
207
- }
208
-
209
- CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
210
- {
211
- if (hooks == NULL)
212
- {
213
- /* Reset hooks */
214
- global_hooks.allocate = malloc;
215
- global_hooks.deallocate = free;
216
- global_hooks.reallocate = realloc;
217
- return;
218
- }
219
-
220
- global_hooks.allocate = malloc;
221
- if (hooks->malloc_fn != NULL)
222
- {
223
- global_hooks.allocate = hooks->malloc_fn;
224
- }
225
-
226
- global_hooks.deallocate = free;
227
- if (hooks->free_fn != NULL)
228
- {
229
- global_hooks.deallocate = hooks->free_fn;
230
- }
231
-
232
- /* use realloc only if both free and malloc are used */
233
- global_hooks.reallocate = NULL;
234
- if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
235
- {
236
- global_hooks.reallocate = realloc;
237
- }
238
- }
239
-
240
- /* Internal constructor. */
241
- static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
242
- {
243
- cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
244
- if (node)
245
- {
246
- memset(node, '\0', sizeof(cJSON));
247
- }
248
-
249
- return node;
250
- }
251
-
252
- /* Delete a cJSON structure. */
253
- CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
254
- {
255
- cJSON *next = NULL;
256
- while (item != NULL)
257
- {
258
- next = item->next;
259
- if (!(item->type & cJSON_IsReference) && (item->child != NULL))
260
- {
261
- cJSON_Delete(item->child);
262
- }
263
- if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
264
- {
265
- global_hooks.deallocate(item->valuestring);
266
- item->valuestring = NULL;
267
- }
268
- if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
269
- {
270
- global_hooks.deallocate(item->string);
271
- item->string = NULL;
272
- }
273
- global_hooks.deallocate(item);
274
- item = next;
275
- }
276
- }
277
-
278
- /* get the decimal point character of the current locale */
279
- static unsigned char get_decimal_point(void)
280
- {
281
- #ifdef ENABLE_LOCALES
282
- struct lconv *lconv = localeconv();
283
- return (unsigned char) lconv->decimal_point[0];
284
- #else
285
- return '.';
286
- #endif
287
- }
288
-
289
- typedef struct
290
- {
291
- const unsigned char *content;
292
- size_t length;
293
- size_t offset;
294
- size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
295
- internal_hooks hooks;
296
- } parse_buffer;
297
-
298
- /* check if the given size is left to read in a given parse buffer (starting with 1) */
299
- #define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
300
- /* check if the buffer can be accessed at the given index (starting with 0) */
301
- #define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
302
- #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
303
- /* get a pointer to the buffer at the position */
304
- #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
305
-
306
- /* Parse the input text to generate a number, and populate the result into item. */
307
- static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
308
- {
309
- double number = 0;
310
- unsigned char *after_end = NULL;
311
- unsigned char number_c_string[64];
312
- unsigned char decimal_point = get_decimal_point();
313
- size_t i = 0;
314
-
315
- if ((input_buffer == NULL) || (input_buffer->content == NULL))
316
- {
317
- return false;
318
- }
319
-
320
- /* copy the number into a temporary buffer and replace '.' with the decimal point
321
- * of the current locale (for strtod)
322
- * This also takes care of '\0' not necessarily being available for marking the end of the input */
323
- for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
324
- {
325
- switch (buffer_at_offset(input_buffer)[i])
326
- {
327
- case '0':
328
- case '1':
329
- case '2':
330
- case '3':
331
- case '4':
332
- case '5':
333
- case '6':
334
- case '7':
335
- case '8':
336
- case '9':
337
- case '+':
338
- case '-':
339
- case 'e':
340
- case 'E':
341
- number_c_string[i] = buffer_at_offset(input_buffer)[i];
342
- break;
343
-
344
- case '.':
345
- number_c_string[i] = decimal_point;
346
- break;
347
-
348
- default:
349
- goto loop_end;
350
- }
351
- }
352
- loop_end:
353
- number_c_string[i] = '\0';
354
-
355
- number = strtod((const char*)number_c_string, (char**)&after_end);
356
- if (number_c_string == after_end)
357
- {
358
- return false; /* parse_error */
359
- }
360
-
361
- item->valuedouble = number;
362
-
363
- /* use saturation in case of overflow */
364
- if (number >= INT_MAX)
365
- {
366
- item->valueint = INT_MAX;
367
- }
368
- else if (number <= (double)INT_MIN)
369
- {
370
- item->valueint = INT_MIN;
371
- }
372
- else
373
- {
374
- item->valueint = (int)number;
375
- }
376
-
377
- item->type = cJSON_Number;
378
-
379
- input_buffer->offset += (size_t)(after_end - number_c_string);
380
- return true;
381
- }
382
-
383
- /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
384
- CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
385
- {
386
- if (number >= INT_MAX)
387
- {
388
- object->valueint = INT_MAX;
389
- }
390
- else if (number <= (double)INT_MIN)
391
- {
392
- object->valueint = INT_MIN;
393
- }
394
- else
395
- {
396
- object->valueint = (int)number;
397
- }
398
-
399
- return object->valuedouble = number;
400
- }
401
-
402
- CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
403
- {
404
- char *copy = NULL;
405
- /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
406
- if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
407
- {
408
- return NULL;
409
- }
410
- /* return NULL if the object is corrupted */
411
- if (object->valuestring == NULL)
412
- {
413
- return NULL;
414
- }
415
- if (strlen(valuestring) <= strlen(object->valuestring))
416
- {
417
- strcpy(object->valuestring, valuestring);
418
- return object->valuestring;
419
- }
420
- copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
421
- if (copy == NULL)
422
- {
423
- return NULL;
424
- }
425
- if (object->valuestring != NULL)
426
- {
427
- cJSON_free(object->valuestring);
428
- }
429
- object->valuestring = copy;
430
-
431
- return copy;
432
- }
433
-
434
- typedef struct
435
- {
436
- unsigned char *buffer;
437
- size_t length;
438
- size_t offset;
439
- size_t depth; /* current nesting depth (for formatted printing) */
440
- cJSON_bool noalloc;
441
- cJSON_bool format; /* is this print a formatted print */
442
- internal_hooks hooks;
443
- } printbuffer;
444
-
445
- /* realloc printbuffer if necessary to have at least "needed" bytes more */
446
- static unsigned char* ensure(printbuffer * const p, size_t needed)
447
- {
448
- unsigned char *newbuffer = NULL;
449
- size_t newsize = 0;
450
-
451
- if ((p == NULL) || (p->buffer == NULL))
452
- {
453
- return NULL;
454
- }
455
-
456
- if ((p->length > 0) && (p->offset >= p->length))
457
- {
458
- /* make sure that offset is valid */
459
- return NULL;
460
- }
461
-
462
- if (needed > INT_MAX)
463
- {
464
- /* sizes bigger than INT_MAX are currently not supported */
465
- return NULL;
466
- }
467
-
468
- needed += p->offset + 1;
469
- if (needed <= p->length)
470
- {
471
- return p->buffer + p->offset;
472
- }
473
-
474
- if (p->noalloc) {
475
- return NULL;
476
- }
477
-
478
- /* calculate new buffer size */
479
- if (needed > (INT_MAX / 2))
480
- {
481
- /* overflow of int, use INT_MAX if possible */
482
- if (needed <= INT_MAX)
483
- {
484
- newsize = INT_MAX;
485
- }
486
- else
487
- {
488
- return NULL;
489
- }
490
- }
491
- else
492
- {
493
- newsize = needed * 2;
494
- }
495
-
496
- if (p->hooks.reallocate != NULL)
497
- {
498
- /* reallocate with realloc if available */
499
- newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
500
- if (newbuffer == NULL)
501
- {
502
- p->hooks.deallocate(p->buffer);
503
- p->length = 0;
504
- p->buffer = NULL;
505
-
506
- return NULL;
507
- }
508
- }
509
- else
510
- {
511
- /* otherwise reallocate manually */
512
- newbuffer = (unsigned char*)p->hooks.allocate(newsize);
513
- if (!newbuffer)
514
- {
515
- p->hooks.deallocate(p->buffer);
516
- p->length = 0;
517
- p->buffer = NULL;
518
-
519
- return NULL;
520
- }
521
-
522
- memcpy(newbuffer, p->buffer, p->offset + 1);
523
- p->hooks.deallocate(p->buffer);
524
- }
525
- p->length = newsize;
526
- p->buffer = newbuffer;
527
-
528
- return newbuffer + p->offset;
529
- }
530
-
531
- /* calculate the new length of the string in a printbuffer and update the offset */
532
- static void update_offset(printbuffer * const p)
533
- {
534
- const unsigned char *buffer = NULL;
535
- if ((p == NULL) || (p->buffer == NULL))
536
- {
537
- return;
538
- }
539
- buffer = p->buffer + p->offset;
540
-
541
- p->offset += strlen((const char*)buffer);
542
- }
543
-
544
- /* securely comparison of floating-point variables */
545
- static cJSON_bool compare_double(double a, double b)
546
- {
547
- double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
548
- return (fabs(a - b) <= maxVal * DBL_EPSILON);
549
- }
550
-
551
- /* Render the number nicely from the given item into a string. */
552
- static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
553
- {
554
- unsigned char *output_pointer = NULL;
555
- double d = item->valuedouble;
556
- int length = 0;
557
- size_t i = 0;
558
- unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
559
- unsigned char decimal_point = get_decimal_point();
560
- double test = 0.0;
561
-
562
- if (output_buffer == NULL)
563
- {
564
- return false;
565
- }
566
-
567
- /* This checks for NaN and Infinity */
568
- if (isnan(d) || isinf(d))
569
- {
570
- length = sprintf((char*)number_buffer, "null");
571
- }
572
- else if (d == (double)item->valueint)
573
- {
574
- length = sprintf((char*)number_buffer, "%d", item->valueint);
575
- }
576
- else
577
- {
578
- /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
579
- length = sprintf((char*)number_buffer, "%1.15g", d);
580
-
581
- /* Check whether the original double can be recovered */
582
- if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
583
- {
584
- /* If not, print with 17 decimal places of precision */
585
- length = sprintf((char*)number_buffer, "%1.17g", d);
586
- }
587
- }
588
-
589
- /* sprintf failed or buffer overrun occurred */
590
- if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
591
- {
592
- return false;
593
- }
594
-
595
- /* reserve appropriate space in the output */
596
- output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
597
- if (output_pointer == NULL)
598
- {
599
- return false;
600
- }
601
-
602
- /* copy the printed number to the output and replace locale
603
- * dependent decimal point with '.' */
604
- for (i = 0; i < ((size_t)length); i++)
605
- {
606
- if (number_buffer[i] == decimal_point)
607
- {
608
- output_pointer[i] = '.';
609
- continue;
610
- }
611
-
612
- output_pointer[i] = number_buffer[i];
613
- }
614
- output_pointer[i] = '\0';
615
-
616
- output_buffer->offset += (size_t)length;
617
-
618
- return true;
619
- }
620
-
621
- /* parse 4 digit hexadecimal number */
622
- static unsigned parse_hex4(const unsigned char * const input)
623
- {
624
- unsigned int h = 0;
625
- size_t i = 0;
626
-
627
- for (i = 0; i < 4; i++)
628
- {
629
- /* parse digit */
630
- if ((input[i] >= '0') && (input[i] <= '9'))
631
- {
632
- h += (unsigned int) input[i] - '0';
633
- }
634
- else if ((input[i] >= 'A') && (input[i] <= 'F'))
635
- {
636
- h += (unsigned int) 10 + input[i] - 'A';
637
- }
638
- else if ((input[i] >= 'a') && (input[i] <= 'f'))
639
- {
640
- h += (unsigned int) 10 + input[i] - 'a';
641
- }
642
- else /* invalid */
643
- {
644
- return 0;
645
- }
646
-
647
- if (i < 3)
648
- {
649
- /* shift left to make place for the next nibble */
650
- h = h << 4;
651
- }
652
- }
653
-
654
- return h;
655
- }
656
-
657
- /* converts a UTF-16 literal to UTF-8
658
- * A literal can be one or two sequences of the form \uXXXX */
659
- static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
660
- {
661
- long unsigned int codepoint = 0;
662
- unsigned int first_code = 0;
663
- const unsigned char *first_sequence = input_pointer;
664
- unsigned char utf8_length = 0;
665
- unsigned char utf8_position = 0;
666
- unsigned char sequence_length = 0;
667
- unsigned char first_byte_mark = 0;
668
-
669
- if ((input_end - first_sequence) < 6)
670
- {
671
- /* input ends unexpectedly */
672
- goto fail;
673
- }
674
-
675
- /* get the first utf16 sequence */
676
- first_code = parse_hex4(first_sequence + 2);
677
-
678
- /* check that the code is valid */
679
- if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
680
- {
681
- goto fail;
682
- }
683
-
684
- /* UTF16 surrogate pair */
685
- if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
686
- {
687
- const unsigned char *second_sequence = first_sequence + 6;
688
- unsigned int second_code = 0;
689
- sequence_length = 12; /* \uXXXX\uXXXX */
690
-
691
- if ((input_end - second_sequence) < 6)
692
- {
693
- /* input ends unexpectedly */
694
- goto fail;
695
- }
696
-
697
- if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
698
- {
699
- /* missing second half of the surrogate pair */
700
- goto fail;
701
- }
702
-
703
- /* get the second utf16 sequence */
704
- second_code = parse_hex4(second_sequence + 2);
705
- /* check that the code is valid */
706
- if ((second_code < 0xDC00) || (second_code > 0xDFFF))
707
- {
708
- /* invalid second half of the surrogate pair */
709
- goto fail;
710
- }
711
-
712
-
713
- /* calculate the unicode codepoint from the surrogate pair */
714
- codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
715
- }
716
- else
717
- {
718
- sequence_length = 6; /* \uXXXX */
719
- codepoint = first_code;
720
- }
721
-
722
- /* encode as UTF-8
723
- * takes at maximum 4 bytes to encode:
724
- * 0 - 0x7F: 0xxxxxxx
725
- * 0x80 - 0x7FF: 110xxxxx 10xxxxxx
726
- * 0x800 - 0xFFFF: 1110xxxx 10xxxxxx 10xxxxxx
727
- * 0x10000 - 0x10FFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
728
-
729
- if (codepoint < 0x80)
730
- {
731
- /* one byte symbol */
732
- utf8_length = 1;
733
- }
734
- else if (codepoint < 0x800)
735
- {
736
- /* two byte symbol */
737
- utf8_length = 2;
738
- }
739
- else if (codepoint < 0x10000)
740
- {
741
- /* three byte symbol */
742
- utf8_length = 3;
743
- }
744
- else if (codepoint <= 0x10FFFF)
745
- {
746
- /* four byte symbol */
747
- utf8_length = 4;
748
- }
749
- else
750
- {
751
- /* invalid unicode codepoint */
752
- goto fail;
753
- }
754
-
755
- /* encode as utf8 */
756
- switch (utf8_length)
757
- {
758
- case 1:
759
- /* first byte */
760
- (*output_pointer)[0] = (unsigned char)(codepoint);
761
- break;
762
- case 2:
763
- first_byte_mark = 0xC0; /* 11000000 */
764
- (*output_pointer)[0] = (unsigned char)(codepoint >> 6) | first_byte_mark;
765
- (*output_pointer)[1] = (unsigned char)(codepoint & 0x3F) | 0x80;
766
- break;
767
- case 3:
768
- first_byte_mark = 0xE0; /* 11100000 */
769
- (*output_pointer)[0] = (unsigned char)(codepoint >> 12) | first_byte_mark;
770
- (*output_pointer)[1] = (unsigned char)((codepoint >> 6) & 0x3F) | 0x80;
771
- (*output_pointer)[2] = (unsigned char)(codepoint & 0x3F) | 0x80;
772
- break;
773
- case 4:
774
- first_byte_mark = 0xF0; /* 11110000 */
775
- (*output_pointer)[0] = (unsigned char)(codepoint >> 18) | first_byte_mark;
776
- (*output_pointer)[1] = (unsigned char)((codepoint >> 12) & 0x3F) | 0x80;
777
- (*output_pointer)[2] = (unsigned char)((codepoint >> 6) & 0x3F) | 0x80;
778
- (*output_pointer)[3] = (unsigned char)(codepoint & 0x3F) | 0x80;
779
- break;
780
- default:
781
- /* Should not execute */
782
- goto fail;
783
- }
784
-
785
- utf8_position = utf8_length;
786
- /* skip the \u characters */
787
- sequence_length = (sequence_length > 0) ? sequence_length : 0;
788
-
789
- *output_pointer += utf8_position;
790
- return sequence_length;
791
-
792
- fail:
793
- return 0;
794
- }
795
-
796
- /* Parse the input text into an unescaped cinput, and populate item. */
797
- static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
798
- {
799
- const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
800
- const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
801
- unsigned char *output_pointer = NULL;
802
- unsigned char *output = NULL;
803
-
804
- /* not a string */
805
- if (buffer_at_offset(input_buffer)[0] != '\"')
806
- {
807
- goto fail;
808
- }
809
-
810
- {
811
- /* calculate approximate size of the output (overestimate) */
812
- size_t allocation_length = 0;
813
- size_t skipped_bytes = 0;
814
- while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
815
- {
816
- /* Is escape sequence */
817
- if (input_end[0] == '\\')
818
- {
819
- if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
820
- {
821
- /* prevent buffer overflow when last input character is a backslash */
822
- goto fail;
823
- }
824
- skipped_bytes++;
825
- input_end++;
826
- }
827
- input_end++;
828
- }
829
- if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
830
- {
831
- goto fail; /* string ended unexpectedly */
832
- }
833
-
834
- /* This is at most how much we need for the output */
835
- allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
836
- output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
837
- if (output == NULL)
838
- {
839
- goto fail; /* allocation failure */
840
- }
841
- }
842
-
843
- output_pointer = output;
844
- /* loop through the string literal */
845
- while (input_pointer < input_end)
846
- {
847
- if (*input_pointer != '\\')
848
- {
849
- *output_pointer++ = *input_pointer++;
850
- }
851
- /* escape sequence */
852
- else
853
- {
854
- unsigned char sequence_length = 2;
855
- if ((input_end - input_pointer) < 1)
856
- {
857
- goto fail;
858
- }
859
-
860
- switch (input_pointer[1])
861
- {
862
- case 'b':
863
- *output_pointer++ = '\b';
864
- break;
865
- case 'f':
866
- *output_pointer++ = '\f';
867
- break;
868
- case 'n':
869
- *output_pointer++ = '\n';
870
- break;
871
- case 'r':
872
- *output_pointer++ = '\r';
873
- break;
874
- case 't':
875
- *output_pointer++ = '\t';
876
- break;
877
- case '\"':
878
- case '\\':
879
- case '/':
880
- *output_pointer++ = input_pointer[1];
881
- break;
882
-
883
- /* UTF-16 literal */
884
- case 'u':
885
- sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
886
- if (sequence_length == 0)
887
- {
888
- /* failed to convert UTF-16-literal to UTF-8 */
889
- goto fail;
890
- }
891
- break;
892
-
893
- default:
894
- goto fail;
895
- }
896
- input_pointer += sequence_length;
897
- }
898
- }
899
-
900
- /* zero terminate the output */
901
- *output_pointer = '\0';
902
-
903
- item->type = cJSON_String;
904
- item->valuestring = (char*)output;
905
-
906
- input_buffer->offset = (size_t) (input_end - input_buffer->content);
907
- input_buffer->offset++;
908
-
909
- return true;
910
-
911
- fail:
912
- if (output != NULL)
913
- {
914
- input_buffer->hooks.deallocate(output);
915
- output = NULL;
916
- }
917
-
918
- if (input_pointer != NULL)
919
- {
920
- input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
921
- }
922
-
923
- return false;
924
- }
925
-
926
- /* Render the cstring provided to an escaped version that can be printed. */
927
- static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
928
- {
929
- const unsigned char *input_pointer = NULL;
930
- unsigned char *output = NULL;
931
- unsigned char *output_pointer = NULL;
932
- size_t output_length = 0;
933
- /* numbers of additional characters needed for escaping */
934
- size_t escape_characters = 0;
935
-
936
- if (output_buffer == NULL)
937
- {
938
- return false;
939
- }
940
-
941
- /* empty string */
942
- if (input == NULL)
943
- {
944
- output = ensure(output_buffer, sizeof("\"\""));
945
- if (output == NULL)
946
- {
947
- return false;
948
- }
949
- strcpy((char*)output, "\"\"");
950
-
951
- output_buffer->offset += 2;
952
-
953
- return true;
954
- }
955
-
956
- /* calculate "escape" characters and final string length */
957
- for (input_pointer = input; *input_pointer; input_pointer++)
958
- {
959
- switch (*input_pointer)
960
- {
961
- case '\"':
962
- case '\\':
963
- case '\b':
964
- case '\f':
965
- case '\n':
966
- case '\r':
967
- case '\t':
968
- /* one character escape needed */
969
- escape_characters++;
970
- break;
971
- default:
972
- if (*input_pointer < 32)
973
- {
974
- /* UTF-16 escape sequence \uXXXX should be printed */
975
- escape_characters += 5;
976
- }
977
- break;
978
- }
979
- }
980
- output_length = (size_t)(input_pointer - input) + escape_characters;
981
-
982
- output = ensure(output_buffer, output_length + sizeof("\"\""));
983
- if (output == NULL)
984
- {
985
- return false;
986
- }
987
-
988
- /* no characters have to be escaped */
989
- if (escape_characters == 0)
990
- {
991
- output[0] = '\"';
992
- memcpy(output + 1, input, output_length);
993
- output[output_length + 1] = '\"';
994
- output[output_length + 2] = '\0';
995
-
996
- output_buffer->offset += output_length + 2;
997
-
998
- return true;
999
- }
1000
-
1001
- output[0] = '\"';
1002
- output_pointer = output + 1;
1003
- /* copy the string */
1004
- for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
1005
- {
1006
- if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1007
- {
1008
- /* normal character, copy */
1009
- *output_pointer = *input_pointer;
1010
- }
1011
- else
1012
- {
1013
- /* character needs to be escaped */
1014
- *output_pointer++ = '\\';
1015
- switch (*input_pointer)
1016
- {
1017
- case '\\':
1018
- *output_pointer = '\\';
1019
- break;
1020
- case '\"':
1021
- *output_pointer = '\"';
1022
- break;
1023
- case '\b':
1024
- *output_pointer = 'b';
1025
- break;
1026
- case '\f':
1027
- *output_pointer = 'f';
1028
- break;
1029
- case '\n':
1030
- *output_pointer = 'n';
1031
- break;
1032
- case '\r':
1033
- *output_pointer = 'r';
1034
- break;
1035
- case '\t':
1036
- *output_pointer = 't';
1037
- break;
1038
- default:
1039
- /* escape and print as unicode codepoint */
1040
- sprintf((char*)output_pointer, "u%04x", *input_pointer);
1041
- output_pointer += 4;
1042
- break;
1043
- }
1044
- }
1045
- }
1046
- output[output_length + 1] = '\"';
1047
- output[output_length + 2] = '\0';
1048
-
1049
- output_buffer->offset += output_length + 2;
1050
-
1051
- return true;
1052
- }
1053
-
1054
- /* Invoke print_string_ptr (which is useful) on an item. */
1055
- static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1056
- {
1057
- return print_string_ptr((unsigned char*)item->valuestring, p);
1058
- }
1059
-
1060
- /* Predeclare these prototypes. */
1061
- static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1062
- static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1063
- static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1064
- static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1065
- static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1066
- static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1067
-
1068
- /* Utility to jump whitespace and cr/lf */
1069
- static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1070
- {
1071
- if ((buffer == NULL) || (buffer->content == NULL))
1072
- {
1073
- return NULL;
1074
- }
1075
-
1076
- if (cannot_access_at_index(buffer, 0))
1077
- {
1078
- return buffer;
1079
- }
1080
-
1081
- while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1082
- {
1083
- buffer->offset++;
1084
- }
1085
-
1086
- if (buffer->offset == buffer->length)
1087
- {
1088
- buffer->offset--;
1089
- }
1090
-
1091
- return buffer;
1092
- }
1093
-
1094
- /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1095
- static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1096
- {
1097
- if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1098
- {
1099
- return NULL;
1100
- }
1101
-
1102
- if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1103
- {
1104
- buffer->offset += 3;
1105
- }
1106
-
1107
- return buffer;
1108
- }
1109
-
1110
- CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1111
- {
1112
- size_t buffer_length;
1113
-
1114
- if (NULL == value)
1115
- {
1116
- return NULL;
1117
- }
1118
-
1119
- /* Adding null character detection due to parse_parse_string and the way cJSON works */
1120
- buffer_length = strlen(value) + sizeof("");
1121
- return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1122
- }
1123
-
1124
- /* Parse an object - create a new root, and populate. */
1125
- CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1126
- {
1127
- parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1128
- cJSON *item = NULL;
1129
-
1130
- /* reset error position */
1131
- global_error.json = NULL;
1132
- global_error.position = 0;
1133
-
1134
- if (value == NULL || 0 == buffer_length)
1135
- {
1136
- goto fail;
1137
- }
1138
-
1139
- buffer.content = (const unsigned char*)value;
1140
- buffer.length = buffer_length;
1141
- buffer.offset = 0;
1142
- buffer.hooks = global_hooks;
1143
-
1144
- item = cJSON_New_Item(&global_hooks);
1145
- if (item == NULL) /* memory fail */
1146
- {
1147
- goto fail;
1148
- }
1149
-
1150
- if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1151
- {
1152
- /* parse failure. ep is set. */
1153
- goto fail;
1154
- }
1155
-
1156
- /* if we require null-terminated JSON without appended garbage, skip then and check for a null terminator */
1157
- if (require_null_terminated)
1158
- {
1159
- buffer_skip_whitespace(&buffer);
1160
- if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1161
- {
1162
- goto fail;
1163
- }
1164
- }
1165
- if (return_parse_end)
1166
- {
1167
- *return_parse_end = (const char*)buffer_at_offset(&buffer);
1168
- }
1169
-
1170
- return item;
1171
-
1172
- fail:
1173
- if (item != NULL)
1174
- {
1175
- cJSON_Delete(item);
1176
- }
1177
-
1178
- if (value != NULL)
1179
- {
1180
- error local_error;
1181
- local_error.json = (const unsigned char*)value;
1182
- local_error.position = 0;
1183
-
1184
- if (buffer.offset < buffer.length)
1185
- {
1186
- local_error.position = buffer.offset;
1187
- }
1188
- else if (buffer.length > 0)
1189
- {
1190
- local_error.position = buffer.length - 1;
1191
- }
1192
-
1193
- if (return_parse_end != NULL)
1194
- {
1195
- *return_parse_end = (const char*)local_error.json + local_error.position;
1196
- }
1197
-
1198
- global_error = local_error;
1199
- }
1200
-
1201
- return NULL;
1202
- }
1203
-
1204
- /* Default options for cJSON_Parse */
1205
- CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1206
- {
1207
- return cJSON_ParseWithOpts(value, 0, 0);
1208
- }
1209
-
1210
- CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1211
- {
1212
- return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1213
- }
1214
-
1215
- #define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1216
-
1217
- static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1218
- {
1219
- static const size_t default_buffer_size = 256;
1220
- printbuffer buffer[1];
1221
- unsigned char *printed = NULL;
1222
-
1223
- memset(buffer, 0, sizeof(buffer));
1224
-
1225
- /* create buffer */
1226
- buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1227
- buffer->length = default_buffer_size;
1228
- buffer->format = format;
1229
- buffer->hooks = *hooks;
1230
- if (buffer->buffer == NULL)
1231
- {
1232
- goto fail;
1233
- }
1234
-
1235
- /* print the value */
1236
- if (!print_value(item, buffer))
1237
- {
1238
- goto fail;
1239
- }
1240
- update_offset(buffer);
1241
-
1242
- /* check if reallocate is available */
1243
- if (hooks->reallocate != NULL)
1244
- {
1245
- printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1246
- if (printed == NULL) {
1247
- goto fail;
1248
- }
1249
- buffer->buffer = NULL;
1250
- }
1251
- else /* otherwise copy the JSON over to a new buffer */
1252
- {
1253
- printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1254
- if (printed == NULL)
1255
- {
1256
- goto fail;
1257
- }
1258
- memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1259
- printed[buffer->offset] = '\0'; /* just to be sure */
1260
-
1261
- /* free the buffer */
1262
- hooks->deallocate(buffer->buffer);
1263
- buffer->buffer = NULL;
1264
- }
1265
-
1266
- return printed;
1267
-
1268
- fail:
1269
- if (buffer->buffer != NULL)
1270
- {
1271
- hooks->deallocate(buffer->buffer);
1272
- buffer->buffer = NULL;
1273
- }
1274
-
1275
- if (printed != NULL)
1276
- {
1277
- hooks->deallocate(printed);
1278
- printed = NULL;
1279
- }
1280
-
1281
- return NULL;
1282
- }
1283
-
1284
- /* Render a cJSON item/entity/structure to text. */
1285
- CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1286
- {
1287
- return (char*)print(item, true, &global_hooks);
1288
- }
1289
-
1290
- CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1291
- {
1292
- return (char*)print(item, false, &global_hooks);
1293
- }
1294
-
1295
- CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1296
- {
1297
- printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1298
-
1299
- if (prebuffer < 0)
1300
- {
1301
- return NULL;
1302
- }
1303
-
1304
- p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1305
- if (!p.buffer)
1306
- {
1307
- return NULL;
1308
- }
1309
-
1310
- p.length = (size_t)prebuffer;
1311
- p.offset = 0;
1312
- p.noalloc = false;
1313
- p.format = fmt;
1314
- p.hooks = global_hooks;
1315
-
1316
- if (!print_value(item, &p))
1317
- {
1318
- global_hooks.deallocate(p.buffer);
1319
- p.buffer = NULL;
1320
- return NULL;
1321
- }
1322
-
1323
- update_offset(&p);
1324
-
1325
- return (char*)p.buffer;
1326
- }
1327
-
1328
- CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1329
- {
1330
- printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1331
-
1332
- if ((length < 0) || (buffer == NULL))
1333
- {
1334
- return false;
1335
- }
1336
-
1337
- p.buffer = (unsigned char*)buffer;
1338
- p.length = (size_t)length;
1339
- p.offset = 0;
1340
- p.noalloc = true;
1341
- p.format = format;
1342
- p.hooks = global_hooks;
1343
-
1344
- return print_value(item, &p);
1345
- }
1346
-
1347
- /* Parser core - when encountering text, process appropriately. */
1348
- static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1349
- {
1350
- if ((input_buffer == NULL) || (input_buffer->content == NULL))
1351
- {
1352
- return false; /* no input */
1353
- }
1354
-
1355
- /* parse the different types of values */
1356
- /* null */
1357
- if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1358
- {
1359
- item->type = cJSON_NULL;
1360
- input_buffer->offset += 4;
1361
- return true;
1362
- }
1363
- /* false */
1364
- if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1365
- {
1366
- item->type = cJSON_False;
1367
- input_buffer->offset += 5;
1368
- return true;
1369
- }
1370
- /* true */
1371
- if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1372
- {
1373
- item->type = cJSON_True;
1374
- item->valueint = 1;
1375
- input_buffer->offset += 4;
1376
- return true;
1377
- }
1378
- /* string */
1379
- if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1380
- {
1381
- return parse_string(item, input_buffer);
1382
- }
1383
- /* number */
1384
- if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
1385
- {
1386
- return parse_number(item, input_buffer);
1387
- }
1388
- /* array */
1389
- if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1390
- {
1391
- return parse_array(item, input_buffer);
1392
- }
1393
- /* object */
1394
- if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1395
- {
1396
- return parse_object(item, input_buffer);
1397
- }
1398
-
1399
- return false;
1400
- }
1401
-
1402
- /* Render a value to text. */
1403
- static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1404
- {
1405
- unsigned char *output = NULL;
1406
-
1407
- if ((item == NULL) || (output_buffer == NULL))
1408
- {
1409
- return false;
1410
- }
1411
-
1412
- switch ((item->type) & 0xFF)
1413
- {
1414
- case cJSON_NULL:
1415
- output = ensure(output_buffer, 5);
1416
- if (output == NULL)
1417
- {
1418
- return false;
1419
- }
1420
- strcpy((char*)output, "null");
1421
- output_buffer->offset += 4;
1422
- return true;
1423
-
1424
- case cJSON_False:
1425
- output = ensure(output_buffer, 6);
1426
- if (output == NULL)
1427
- {
1428
- return false;
1429
- }
1430
- strcpy((char*)output, "false");
1431
- output_buffer->offset += 5;
1432
- return true;
1433
-
1434
- case cJSON_True:
1435
- output = ensure(output_buffer, 5);
1436
- if (output == NULL)
1437
- {
1438
- return false;
1439
- }
1440
- strcpy((char*)output, "true");
1441
- output_buffer->offset += 4;
1442
- return true;
1443
-
1444
- case cJSON_Number:
1445
- return print_number(item, output_buffer);
1446
-
1447
- case cJSON_Raw:
1448
- {
1449
- size_t raw_length = 0;
1450
- if (item->valuestring == NULL)
1451
- {
1452
- return false;
1453
- }
1454
-
1455
- raw_length = strlen(item->valuestring) + sizeof("");
1456
- output = ensure(output_buffer, raw_length);
1457
- if (output == NULL)
1458
- {
1459
- return false;
1460
- }
1461
- memcpy(output, item->valuestring, raw_length);
1462
- output_buffer->offset += raw_length - 1;
1463
- return true;
1464
- }
1465
-
1466
- case cJSON_String:
1467
- return print_string(item, output_buffer);
1468
-
1469
- case cJSON_Array:
1470
- return print_array(item, output_buffer);
1471
-
1472
- case cJSON_Object:
1473
- return print_object(item, output_buffer);
1474
-
1475
- default:
1476
- return false;
1477
- }
1478
- }
1479
-
1480
- /* Build an array from input text. */
1481
- static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1482
- {
1483
- cJSON *head = NULL; /* head of the linked list */
1484
- cJSON *current_item = NULL;
1485
-
1486
- if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1487
- {
1488
- return false; /* to deeply nested */
1489
- }
1490
- input_buffer->depth++;
1491
-
1492
- if (buffer_at_offset(input_buffer)[0] != '[')
1493
- {
1494
- /* not an array */
1495
- goto fail;
1496
- }
1497
-
1498
- input_buffer->offset++;
1499
- buffer_skip_whitespace(input_buffer);
1500
- if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1501
- {
1502
- /* empty array */
1503
- goto success;
1504
- }
1505
-
1506
- /* check if we skipped to the end of the buffer */
1507
- if (cannot_access_at_index(input_buffer, 0))
1508
- {
1509
- input_buffer->offset--;
1510
- goto fail;
1511
- }
1512
-
1513
- /* step back to character in front of the first element */
1514
- input_buffer->offset--;
1515
- /* loop through the comma separated array elements */
1516
- do
1517
- {
1518
- /* allocate next item */
1519
- cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1520
- if (new_item == NULL)
1521
- {
1522
- goto fail; /* allocation failure */
1523
- }
1524
-
1525
- /* attach next item to list */
1526
- if (head == NULL)
1527
- {
1528
- /* start the linked list */
1529
- current_item = head = new_item;
1530
- }
1531
- else
1532
- {
1533
- /* add to the end and advance */
1534
- current_item->next = new_item;
1535
- new_item->prev = current_item;
1536
- current_item = new_item;
1537
- }
1538
-
1539
- /* parse next value */
1540
- input_buffer->offset++;
1541
- buffer_skip_whitespace(input_buffer);
1542
- if (!parse_value(current_item, input_buffer))
1543
- {
1544
- goto fail; /* failed to parse value */
1545
- }
1546
- buffer_skip_whitespace(input_buffer);
1547
- }
1548
- while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1549
-
1550
- if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1551
- {
1552
- goto fail; /* expected end of array */
1553
- }
1554
-
1555
- success:
1556
- input_buffer->depth--;
1557
-
1558
- if (head != NULL) {
1559
- head->prev = current_item;
1560
- }
1561
-
1562
- item->type = cJSON_Array;
1563
- item->child = head;
1564
-
1565
- input_buffer->offset++;
1566
-
1567
- return true;
1568
-
1569
- fail:
1570
- if (head != NULL)
1571
- {
1572
- cJSON_Delete(head);
1573
- }
1574
-
1575
- return false;
1576
- }
1577
-
1578
- /* Render an array to text */
1579
- static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1580
- {
1581
- unsigned char *output_pointer = NULL;
1582
- size_t length = 0;
1583
- cJSON *current_element = item->child;
1584
-
1585
- if (output_buffer == NULL)
1586
- {
1587
- return false;
1588
- }
1589
-
1590
- /* Compose the output array. */
1591
- /* opening square bracket */
1592
- output_pointer = ensure(output_buffer, 1);
1593
- if (output_pointer == NULL)
1594
- {
1595
- return false;
1596
- }
1597
-
1598
- *output_pointer = '[';
1599
- output_buffer->offset++;
1600
- output_buffer->depth++;
1601
-
1602
- while (current_element != NULL)
1603
- {
1604
- if (!print_value(current_element, output_buffer))
1605
- {
1606
- return false;
1607
- }
1608
- update_offset(output_buffer);
1609
- if (current_element->next)
1610
- {
1611
- length = (size_t) (output_buffer->format ? 2 : 1);
1612
- output_pointer = ensure(output_buffer, length + 1);
1613
- if (output_pointer == NULL)
1614
- {
1615
- return false;
1616
- }
1617
- *output_pointer++ = ',';
1618
- if(output_buffer->format)
1619
- {
1620
- *output_pointer++ = ' ';
1621
- }
1622
- *output_pointer = '\0';
1623
- output_buffer->offset += length;
1624
- }
1625
- current_element = current_element->next;
1626
- }
1627
-
1628
- output_pointer = ensure(output_buffer, 2);
1629
- if (output_pointer == NULL)
1630
- {
1631
- return false;
1632
- }
1633
- *output_pointer++ = ']';
1634
- *output_pointer = '\0';
1635
- output_buffer->depth--;
1636
-
1637
- return true;
1638
- }
1639
-
1640
- /* Build an object from the text. */
1641
- static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1642
- {
1643
- cJSON *head = NULL; /* linked list head */
1644
- cJSON *current_item = NULL;
1645
-
1646
- if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1647
- {
1648
- return false; /* to deeply nested */
1649
- }
1650
- input_buffer->depth++;
1651
-
1652
- if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1653
- {
1654
- goto fail; /* not an object */
1655
- }
1656
-
1657
- input_buffer->offset++;
1658
- buffer_skip_whitespace(input_buffer);
1659
- if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1660
- {
1661
- goto success; /* empty object */
1662
- }
1663
-
1664
- /* check if we skipped to the end of the buffer */
1665
- if (cannot_access_at_index(input_buffer, 0))
1666
- {
1667
- input_buffer->offset--;
1668
- goto fail;
1669
- }
1670
-
1671
- /* step back to character in front of the first element */
1672
- input_buffer->offset--;
1673
- /* loop through the comma separated array elements */
1674
- do
1675
- {
1676
- /* allocate next item */
1677
- cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1678
- if (new_item == NULL)
1679
- {
1680
- goto fail; /* allocation failure */
1681
- }
1682
-
1683
- /* attach next item to list */
1684
- if (head == NULL)
1685
- {
1686
- /* start the linked list */
1687
- current_item = head = new_item;
1688
- }
1689
- else
1690
- {
1691
- /* add to the end and advance */
1692
- current_item->next = new_item;
1693
- new_item->prev = current_item;
1694
- current_item = new_item;
1695
- }
1696
-
1697
- if (cannot_access_at_index(input_buffer, 1))
1698
- {
1699
- goto fail; /* nothing comes after the comma */
1700
- }
1701
-
1702
- /* parse the name of the child */
1703
- input_buffer->offset++;
1704
- buffer_skip_whitespace(input_buffer);
1705
- if (!parse_string(current_item, input_buffer))
1706
- {
1707
- goto fail; /* failed to parse name */
1708
- }
1709
- buffer_skip_whitespace(input_buffer);
1710
-
1711
- /* swap valuestring and string, because we parsed the name */
1712
- current_item->string = current_item->valuestring;
1713
- current_item->valuestring = NULL;
1714
-
1715
- if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1716
- {
1717
- goto fail; /* invalid object */
1718
- }
1719
-
1720
- /* parse the value */
1721
- input_buffer->offset++;
1722
- buffer_skip_whitespace(input_buffer);
1723
- if (!parse_value(current_item, input_buffer))
1724
- {
1725
- goto fail; /* failed to parse value */
1726
- }
1727
- buffer_skip_whitespace(input_buffer);
1728
- }
1729
- while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1730
-
1731
- if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1732
- {
1733
- goto fail; /* expected end of object */
1734
- }
1735
-
1736
- success:
1737
- input_buffer->depth--;
1738
-
1739
- if (head != NULL) {
1740
- head->prev = current_item;
1741
- }
1742
-
1743
- item->type = cJSON_Object;
1744
- item->child = head;
1745
-
1746
- input_buffer->offset++;
1747
-
1748
- return true;
1749
-
1750
- fail:
1751
- if (head != NULL)
1752
- {
1753
- cJSON_Delete(head);
1754
- }
1755
-
1756
- return false;
1757
- }
1758
-
1759
- /* Render an object to text. */
1760
- static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1761
- {
1762
- unsigned char *output_pointer = NULL;
1763
- size_t length = 0;
1764
- cJSON *current_item = item->child;
1765
-
1766
- if (output_buffer == NULL)
1767
- {
1768
- return false;
1769
- }
1770
-
1771
- /* Compose the output: */
1772
- length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1773
- output_pointer = ensure(output_buffer, length + 1);
1774
- if (output_pointer == NULL)
1775
- {
1776
- return false;
1777
- }
1778
-
1779
- *output_pointer++ = '{';
1780
- output_buffer->depth++;
1781
- if (output_buffer->format)
1782
- {
1783
- *output_pointer++ = '\n';
1784
- }
1785
- output_buffer->offset += length;
1786
-
1787
- while (current_item)
1788
- {
1789
- if (output_buffer->format)
1790
- {
1791
- size_t i;
1792
- output_pointer = ensure(output_buffer, output_buffer->depth);
1793
- if (output_pointer == NULL)
1794
- {
1795
- return false;
1796
- }
1797
- for (i = 0; i < output_buffer->depth; i++)
1798
- {
1799
- *output_pointer++ = '\t';
1800
- }
1801
- output_buffer->offset += output_buffer->depth;
1802
- }
1803
-
1804
- /* print key */
1805
- if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1806
- {
1807
- return false;
1808
- }
1809
- update_offset(output_buffer);
1810
-
1811
- length = (size_t) (output_buffer->format ? 2 : 1);
1812
- output_pointer = ensure(output_buffer, length);
1813
- if (output_pointer == NULL)
1814
- {
1815
- return false;
1816
- }
1817
- *output_pointer++ = ':';
1818
- if (output_buffer->format)
1819
- {
1820
- *output_pointer++ = '\t';
1821
- }
1822
- output_buffer->offset += length;
1823
-
1824
- /* print value */
1825
- if (!print_value(current_item, output_buffer))
1826
- {
1827
- return false;
1828
- }
1829
- update_offset(output_buffer);
1830
-
1831
- /* print comma if not last */
1832
- length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1833
- output_pointer = ensure(output_buffer, length + 1);
1834
- if (output_pointer == NULL)
1835
- {
1836
- return false;
1837
- }
1838
- if (current_item->next)
1839
- {
1840
- *output_pointer++ = ',';
1841
- }
1842
-
1843
- if (output_buffer->format)
1844
- {
1845
- *output_pointer++ = '\n';
1846
- }
1847
- *output_pointer = '\0';
1848
- output_buffer->offset += length;
1849
-
1850
- current_item = current_item->next;
1851
- }
1852
-
1853
- output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1854
- if (output_pointer == NULL)
1855
- {
1856
- return false;
1857
- }
1858
- if (output_buffer->format)
1859
- {
1860
- size_t i;
1861
- for (i = 0; i < (output_buffer->depth - 1); i++)
1862
- {
1863
- *output_pointer++ = '\t';
1864
- }
1865
- }
1866
- *output_pointer++ = '}';
1867
- *output_pointer = '\0';
1868
- output_buffer->depth--;
1869
-
1870
- return true;
1871
- }
1872
-
1873
- /* Get Array size/item / object item. */
1874
- CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1875
- {
1876
- cJSON *child = NULL;
1877
- size_t size = 0;
1878
-
1879
- if (array == NULL)
1880
- {
1881
- return 0;
1882
- }
1883
-
1884
- child = array->child;
1885
-
1886
- while(child != NULL)
1887
- {
1888
- size++;
1889
- child = child->next;
1890
- }
1891
-
1892
- /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1893
-
1894
- return (int)size;
1895
- }
1896
-
1897
- static cJSON* get_array_item(const cJSON *array, size_t index)
1898
- {
1899
- cJSON *current_child = NULL;
1900
-
1901
- if (array == NULL)
1902
- {
1903
- return NULL;
1904
- }
1905
-
1906
- current_child = array->child;
1907
- while ((current_child != NULL) && (index > 0))
1908
- {
1909
- index--;
1910
- current_child = current_child->next;
1911
- }
1912
-
1913
- return current_child;
1914
- }
1915
-
1916
- CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1917
- {
1918
- if (index < 0)
1919
- {
1920
- return NULL;
1921
- }
1922
-
1923
- return get_array_item(array, (size_t)index);
1924
- }
1925
-
1926
- static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1927
- {
1928
- cJSON *current_element = NULL;
1929
-
1930
- if ((object == NULL) || (name == NULL))
1931
- {
1932
- return NULL;
1933
- }
1934
-
1935
- current_element = object->child;
1936
- if (case_sensitive)
1937
- {
1938
- while (current_element != NULL)
1939
- {
1940
- if (current_element->string && (strcmp(name, current_element->string) == 0))
1941
- {
1942
- return current_element;
1943
- }
1944
- current_element = current_element->next;
1945
- }
1946
- }
1947
- else
1948
- {
1949
- while (current_element != NULL)
1950
- {
1951
- if (current_element->string && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) == 0))
1952
- {
1953
- return current_element;
1954
- }
1955
- current_element = current_element->next;
1956
- }
1957
- }
1958
-
1959
- return NULL;
1960
- }
1961
-
1962
- CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1963
- {
1964
- return get_object_item(object, string, false);
1965
- }
1966
-
1967
- CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1968
- {
1969
- return get_object_item(object, string, true);
1970
- }
1971
-
1972
- CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1973
- {
1974
- return cJSON_GetObjectItem(object, string) ? 1 : 0;
1975
- }
1976
-
1977
- /* Utility for array list handling. */
1978
- static void suffix_object(cJSON *prev, cJSON *item)
1979
- {
1980
- prev->next = item;
1981
- item->prev = prev;
1982
- }
1983
-
1984
- /* Utility for handling references. */
1985
- static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1986
- {
1987
- cJSON *reference = NULL;
1988
- if (item == NULL)
1989
- {
1990
- return NULL;
1991
- }
1992
-
1993
- reference = cJSON_New_Item(hooks);
1994
- if (reference == NULL)
1995
- {
1996
- return NULL;
1997
- }
1998
-
1999
- memcpy(reference, item, sizeof(cJSON));
2000
- reference->string = NULL;
2001
- reference->type |= cJSON_IsReference;
2002
- reference->next = reference->prev = NULL;
2003
- return reference;
2004
- }
2005
-
2006
- static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
2007
- {
2008
- cJSON *child = NULL;
2009
-
2010
- if ((item == NULL) || (array == NULL) || (array == item))
2011
- {
2012
- return false;
2013
- }
2014
-
2015
- child = array->child;
2016
- /*
2017
- * To find the last item in array quickly, we use prev in array
2018
- */
2019
- if (child == NULL)
2020
- {
2021
- /* list is empty, start new one */
2022
- array->child = item;
2023
- item->prev = item;
2024
- item->next = NULL;
2025
- }
2026
- else
2027
- {
2028
- /* append to the end */
2029
- if (child->prev)
2030
- {
2031
- suffix_object(child->prev, item);
2032
- array->child->prev = item;
2033
- }
2034
- }
2035
-
2036
- return true;
2037
- }
2038
-
2039
- /* Add item to array/object. */
2040
- CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
2041
- {
2042
- return add_item_to_array(array, item);
2043
- }
2044
-
2045
- #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2046
- #pragma GCC diagnostic push
2047
- #endif
2048
- #ifdef __GNUC__
2049
- #pragma GCC diagnostic ignored "-Wcast-qual"
2050
- #endif
2051
- /* helper function to cast away const */
2052
- static void* cast_away_const(const void* string)
2053
- {
2054
- return (void*)string;
2055
- }
2056
- #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2057
- #pragma GCC diagnostic pop
2058
- #endif
2059
-
2060
-
2061
- static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
2062
- {
2063
- char *new_key = NULL;
2064
- int new_type = cJSON_Invalid;
2065
-
2066
- if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2067
- {
2068
- return false;
2069
- }
2070
-
2071
- if (constant_key)
2072
- {
2073
- new_key = (char*)cast_away_const(string);
2074
- new_type = item->type | cJSON_StringIsConst;
2075
- }
2076
- else
2077
- {
2078
- new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2079
- if (new_key == NULL)
2080
- {
2081
- return false;
2082
- }
2083
-
2084
- new_type = item->type & ~cJSON_StringIsConst;
2085
- }
2086
-
2087
- if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2088
- {
2089
- hooks->deallocate(item->string);
2090
- }
2091
-
2092
- item->string = new_key;
2093
- item->type = new_type;
2094
-
2095
- return add_item_to_array(object, item);
2096
- }
2097
-
2098
- CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2099
- {
2100
- return add_item_to_object(object, string, item, &global_hooks, false);
2101
- }
2102
-
2103
- /* Add an item to an object with constant string as key */
2104
- CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2105
- {
2106
- return add_item_to_object(object, string, item, &global_hooks, true);
2107
- }
2108
-
2109
- CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2110
- {
2111
- if (array == NULL)
2112
- {
2113
- return false;
2114
- }
2115
-
2116
- return add_item_to_array(array, create_reference(item, &global_hooks));
2117
- }
2118
-
2119
- CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2120
- {
2121
- if ((object == NULL) || (string == NULL))
2122
- {
2123
- return false;
2124
- }
2125
-
2126
- return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2127
- }
2128
-
2129
- CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2130
- {
2131
- cJSON *null = cJSON_CreateNull();
2132
- if (add_item_to_object(object, name, null, &global_hooks, false))
2133
- {
2134
- return null;
2135
- }
2136
-
2137
- cJSON_Delete(null);
2138
- return NULL;
2139
- }
2140
-
2141
- CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2142
- {
2143
- cJSON *true_item = cJSON_CreateTrue();
2144
- if (add_item_to_object(object, name, true_item, &global_hooks, false))
2145
- {
2146
- return true_item;
2147
- }
2148
-
2149
- cJSON_Delete(true_item);
2150
- return NULL;
2151
- }
2152
-
2153
- CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2154
- {
2155
- cJSON *false_item = cJSON_CreateFalse();
2156
- if (add_item_to_object(object, name, false_item, &global_hooks, false))
2157
- {
2158
- return false_item;
2159
- }
2160
-
2161
- cJSON_Delete(false_item);
2162
- return NULL;
2163
- }
2164
-
2165
- CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2166
- {
2167
- cJSON *bool_item = cJSON_CreateBool(boolean);
2168
- if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2169
- {
2170
- return bool_item;
2171
- }
2172
-
2173
- cJSON_Delete(bool_item);
2174
- return NULL;
2175
- }
2176
-
2177
- CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2178
- {
2179
- cJSON *number_item = cJSON_CreateNumber(number);
2180
- if (add_item_to_object(object, name, number_item, &global_hooks, false))
2181
- {
2182
- return number_item;
2183
- }
2184
-
2185
- cJSON_Delete(number_item);
2186
- return NULL;
2187
- }
2188
-
2189
- CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2190
- {
2191
- cJSON *string_item = cJSON_CreateString(string);
2192
- if (add_item_to_object(object, name, string_item, &global_hooks, false))
2193
- {
2194
- return string_item;
2195
- }
2196
-
2197
- cJSON_Delete(string_item);
2198
- return NULL;
2199
- }
2200
-
2201
- CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2202
- {
2203
- cJSON *raw_item = cJSON_CreateRaw(raw);
2204
- if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2205
- {
2206
- return raw_item;
2207
- }
2208
-
2209
- cJSON_Delete(raw_item);
2210
- return NULL;
2211
- }
2212
-
2213
- CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2214
- {
2215
- cJSON *object_item = cJSON_CreateObject();
2216
- if (add_item_to_object(object, name, object_item, &global_hooks, false))
2217
- {
2218
- return object_item;
2219
- }
2220
-
2221
- cJSON_Delete(object_item);
2222
- return NULL;
2223
- }
2224
-
2225
- CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2226
- {
2227
- cJSON *array = cJSON_CreateArray();
2228
- if (add_item_to_object(object, name, array, &global_hooks, false))
2229
- {
2230
- return array;
2231
- }
2232
-
2233
- cJSON_Delete(array);
2234
- return NULL;
2235
- }
2236
-
2237
- CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2238
- {
2239
- if ((parent == NULL) || (item == NULL))
2240
- {
2241
- return NULL;
2242
- }
2243
-
2244
- if (item != parent->child)
2245
- {
2246
- /* not the first element */
2247
- item->prev->next = item->next;
2248
- }
2249
- if (item->next != NULL)
2250
- {
2251
- /* not the last element */
2252
- item->next->prev = item->prev;
2253
- }
2254
-
2255
- if (item == parent->child)
2256
- {
2257
- /* first element */
2258
- parent->child = item->next;
2259
- }
2260
- else if (item->next == NULL)
2261
- {
2262
- /* last element */
2263
- parent->child->prev = item->prev;
2264
- }
2265
-
2266
- /* make sure the detached item doesn't point anywhere anymore */
2267
- item->prev = NULL;
2268
- item->next = NULL;
2269
-
2270
- return item;
2271
- }
2272
-
2273
- CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2274
- {
2275
- if (which < 0)
2276
- {
2277
- return NULL;
2278
- }
2279
-
2280
- return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2281
- }
2282
-
2283
- CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2284
- {
2285
- cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2286
- }
2287
-
2288
- CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2289
- {
2290
- cJSON *to_detach = cJSON_GetObjectItem(object, string);
2291
-
2292
- return cJSON_DetachItemViaPointer(object, to_detach);
2293
- }
2294
-
2295
- CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2296
- {
2297
- cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2298
-
2299
- return cJSON_DetachItemViaPointer(object, to_detach);
2300
- }
2301
-
2302
- CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2303
- {
2304
- cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2305
- }
2306
-
2307
- CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2308
- {
2309
- cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2310
- }
2311
-
2312
- /* Replace array/object items with new ones. */
2313
- CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2314
- {
2315
- cJSON *after_inserted = NULL;
2316
-
2317
- if (which < 0 || newitem == NULL)
2318
- {
2319
- return false;
2320
- }
2321
-
2322
- after_inserted = get_array_item(array, (size_t)which);
2323
- if (after_inserted == NULL)
2324
- {
2325
- return add_item_to_array(array, newitem);
2326
- }
2327
-
2328
- if (after_inserted != array->child && after_inserted->prev == NULL) {
2329
- /* return false if after_inserted is a corrupted array item */
2330
- return false;
2331
- }
2332
-
2333
- newitem->next = after_inserted;
2334
- newitem->prev = after_inserted->prev;
2335
- after_inserted->prev = newitem;
2336
- if (after_inserted == array->child)
2337
- {
2338
- array->child = newitem;
2339
- }
2340
- else
2341
- {
2342
- newitem->prev->next = newitem;
2343
- }
2344
- return true;
2345
- }
2346
-
2347
- CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2348
- {
2349
- if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
2350
- {
2351
- return false;
2352
- }
2353
-
2354
- if (replacement == item)
2355
- {
2356
- return true;
2357
- }
2358
-
2359
- replacement->next = item->next;
2360
- replacement->prev = item->prev;
2361
-
2362
- if (replacement->next != NULL)
2363
- {
2364
- replacement->next->prev = replacement;
2365
- }
2366
- if (parent->child == item)
2367
- {
2368
- if (parent->child->prev == parent->child)
2369
- {
2370
- replacement->prev = replacement;
2371
- }
2372
- parent->child = replacement;
2373
- }
2374
- else
2375
- { /*
2376
- * To find the last item in array quickly, we use prev in array.
2377
- * We can't modify the last item's prev pointer from pointer to pointer conversion.
2378
- */
2379
- if (replacement->prev != NULL)
2380
- {
2381
- replacement->prev->next = replacement;
2382
- }
2383
- if (replacement->next == NULL)
2384
- {
2385
- parent->child->prev = replacement;
2386
- }
2387
- }
2388
-
2389
- item->next = NULL;
2390
- item->prev = NULL;
2391
- cJSON_Delete(item);
2392
-
2393
- return true;
2394
- }
2395
-
2396
- CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2397
- {
2398
- if (which < 0)
2399
- {
2400
- return false;
2401
- }
2402
-
2403
- return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2404
- }
2405
-
2406
- static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2407
- {
2408
- if ((replacement == NULL) || (string == NULL))
2409
- {
2410
- return false;
2411
- }
2412
-
2413
- /* replace the name in the replacement */
2414
- if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2415
- {
2416
- cJSON_free(replacement->string);
2417
- }
2418
- replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2419
- if (replacement->string == NULL)
2420
- {
2421
- return false;
2422
- }
2423
-
2424
- replacement->type &= ~cJSON_StringIsConst;
2425
-
2426
- return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2427
- }
2428
-
2429
- CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2430
- {
2431
- return replace_item_in_object(object, string, newitem, false);
2432
- }
2433
-
2434
- CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2435
- {
2436
- return replace_item_in_object(object, string, newitem, true);
2437
- }
2438
-
2439
- /* Create basic types: */
2440
- CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2441
- {
2442
- cJSON *item = cJSON_New_Item(&global_hooks);
2443
- if(item)
2444
- {
2445
- item->type = cJSON_NULL;
2446
- }
2447
-
2448
- return item;
2449
- }
2450
-
2451
- CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2452
- {
2453
- cJSON *item = cJSON_New_Item(&global_hooks);
2454
- if(item)
2455
- {
2456
- item->type = cJSON_True;
2457
- }
2458
-
2459
- return item;
2460
- }
2461
-
2462
- CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2463
- {
2464
- cJSON *item = cJSON_New_Item(&global_hooks);
2465
- if(item)
2466
- {
2467
- item->type = cJSON_False;
2468
- }
2469
-
2470
- return item;
2471
- }
2472
-
2473
- CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2474
- {
2475
- cJSON *item = cJSON_New_Item(&global_hooks);
2476
- if(item)
2477
- {
2478
- item->type = boolean ? cJSON_True : cJSON_False;
2479
- }
2480
-
2481
- return item;
2482
- }
2483
-
2484
- CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2485
- {
2486
- cJSON *item = cJSON_New_Item(&global_hooks);
2487
- if(item)
2488
- {
2489
- item->type = cJSON_Number;
2490
- item->valuedouble = num;
2491
-
2492
- /* use saturation in case of overflow */
2493
- if (num >= INT_MAX)
2494
- {
2495
- item->valueint = INT_MAX;
2496
- }
2497
- else if (num <= (double)INT_MIN)
2498
- {
2499
- item->valueint = INT_MIN;
2500
- }
2501
- else
2502
- {
2503
- item->valueint = (int)num;
2504
- }
2505
- }
2506
-
2507
- return item;
2508
- }
2509
-
2510
- CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2511
- {
2512
- cJSON *item = cJSON_New_Item(&global_hooks);
2513
- if(item)
2514
- {
2515
- item->type = cJSON_String;
2516
- item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2517
- if(!item->valuestring)
2518
- {
2519
- cJSON_Delete(item);
2520
- return NULL;
2521
- }
2522
- }
2523
-
2524
- return item;
2525
- }
2526
-
2527
- CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2528
- {
2529
- cJSON *item = cJSON_New_Item(&global_hooks);
2530
- if (item != NULL)
2531
- {
2532
- item->type = cJSON_String | cJSON_IsReference;
2533
- item->valuestring = (char*)cast_away_const(string);
2534
- }
2535
-
2536
- return item;
2537
- }
2538
-
2539
- CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2540
- {
2541
- cJSON *item = cJSON_New_Item(&global_hooks);
2542
- if (item != NULL) {
2543
- item->type = cJSON_Object | cJSON_IsReference;
2544
- item->child = (cJSON*)cast_away_const(child);
2545
- }
2546
-
2547
- return item;
2548
- }
2549
-
2550
- CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2551
- cJSON *item = cJSON_New_Item(&global_hooks);
2552
- if (item != NULL) {
2553
- item->type = cJSON_Array | cJSON_IsReference;
2554
- item->child = (cJSON*)cast_away_const(child);
2555
- }
2556
-
2557
- return item;
2558
- }
2559
-
2560
- CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2561
- {
2562
- cJSON *item = cJSON_New_Item(&global_hooks);
2563
- if(item)
2564
- {
2565
- item->type = cJSON_Raw;
2566
- item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2567
- if(!item->valuestring)
2568
- {
2569
- cJSON_Delete(item);
2570
- return NULL;
2571
- }
2572
- }
2573
-
2574
- return item;
2575
- }
2576
-
2577
- CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2578
- {
2579
- cJSON *item = cJSON_New_Item(&global_hooks);
2580
- if(item)
2581
- {
2582
- item->type=cJSON_Array;
2583
- }
2584
-
2585
- return item;
2586
- }
2587
-
2588
- CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2589
- {
2590
- cJSON *item = cJSON_New_Item(&global_hooks);
2591
- if(item)
2592
- {
2593
- item->type = cJSON_Object;
2594
- }
2595
-
2596
- return item;
2597
- }
2598
-
2599
- /* Create Arrays: */
2600
- CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2601
- {
2602
- size_t i = 0;
2603
- cJSON *n = NULL;
2604
- cJSON *p = NULL;
2605
- cJSON *a = NULL;
2606
-
2607
- if ((count < 0) || (numbers == NULL))
2608
- {
2609
- return NULL;
2610
- }
2611
-
2612
- a = cJSON_CreateArray();
2613
-
2614
- for(i = 0; a && (i < (size_t)count); i++)
2615
- {
2616
- n = cJSON_CreateNumber((double)numbers[i]);
2617
- if (!n)
2618
- {
2619
- cJSON_Delete(a);
2620
- return NULL;
2621
- }
2622
- if(!i)
2623
- {
2624
- a->child = n;
2625
- }
2626
- else
2627
- {
2628
- suffix_object(p, n);
2629
- }
2630
- p = n;
2631
- }
2632
-
2633
- if (a && a->child) {
2634
- a->child->prev = n;
2635
- }
2636
-
2637
- return a;
2638
- }
2639
-
2640
- CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2641
- {
2642
- size_t i = 0;
2643
- cJSON *n = NULL;
2644
- cJSON *p = NULL;
2645
- cJSON *a = NULL;
2646
-
2647
- if ((count < 0) || (numbers == NULL))
2648
- {
2649
- return NULL;
2650
- }
2651
-
2652
- a = cJSON_CreateArray();
2653
-
2654
- for(i = 0; a && (i < (size_t)count); i++)
2655
- {
2656
- n = cJSON_CreateNumber((double)numbers[i]);
2657
- if(!n)
2658
- {
2659
- cJSON_Delete(a);
2660
- return NULL;
2661
- }
2662
- if(!i)
2663
- {
2664
- a->child = n;
2665
- }
2666
- else
2667
- {
2668
- suffix_object(p, n);
2669
- }
2670
- p = n;
2671
- }
2672
-
2673
- if (a && a->child) {
2674
- a->child->prev = n;
2675
- }
2676
-
2677
- return a;
2678
- }
2679
-
2680
- CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2681
- {
2682
- size_t i = 0;
2683
- cJSON *n = NULL;
2684
- cJSON *p = NULL;
2685
- cJSON *a = NULL;
2686
-
2687
- if ((count < 0) || (numbers == NULL))
2688
- {
2689
- return NULL;
2690
- }
2691
-
2692
- a = cJSON_CreateArray();
2693
-
2694
- for(i = 0; a && (i < (size_t)count); i++)
2695
- {
2696
- n = cJSON_CreateNumber(numbers[i]);
2697
- if(!n)
2698
- {
2699
- cJSON_Delete(a);
2700
- return NULL;
2701
- }
2702
- if(!i)
2703
- {
2704
- a->child = n;
2705
- }
2706
- else
2707
- {
2708
- suffix_object(p, n);
2709
- }
2710
- p = n;
2711
- }
2712
-
2713
- if (a && a->child) {
2714
- a->child->prev = n;
2715
- }
2716
-
2717
- return a;
2718
- }
2719
-
2720
- CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2721
- {
2722
- size_t i = 0;
2723
- cJSON *n = NULL;
2724
- cJSON *p = NULL;
2725
- cJSON *a = NULL;
2726
-
2727
- if ((count < 0) || (strings == NULL))
2728
- {
2729
- return NULL;
2730
- }
2731
-
2732
- a = cJSON_CreateArray();
2733
-
2734
- for(i = 0; a && (i < (size_t)count); i++)
2735
- {
2736
- n = cJSON_CreateString(strings[i]);
2737
- if(!n)
2738
- {
2739
- cJSON_Delete(a);
2740
- return NULL;
2741
- }
2742
- if(!i)
2743
- {
2744
- a->child = n;
2745
- }
2746
- else
2747
- {
2748
- suffix_object(p, n);
2749
- }
2750
- p = n;
2751
- }
2752
-
2753
- if (a && a->child) {
2754
- a->child->prev = n;
2755
- }
2756
-
2757
- return a;
2758
- }
2759
-
2760
- /* Duplication */
2761
- CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2762
- {
2763
- cJSON *newitem = NULL;
2764
- cJSON *child = NULL;
2765
- cJSON *next = NULL;
2766
- cJSON *newchild = NULL;
2767
-
2768
- /* Bail on bad ptr */
2769
- if (!item)
2770
- {
2771
- goto fail;
2772
- }
2773
- /* Create new item */
2774
- newitem = cJSON_New_Item(&global_hooks);
2775
- if (!newitem)
2776
- {
2777
- goto fail;
2778
- }
2779
- /* Copy over all vars */
2780
- newitem->type = item->type & (~cJSON_IsReference);
2781
- newitem->valueint = item->valueint;
2782
- newitem->valuedouble = item->valuedouble;
2783
- if (item->valuestring)
2784
- {
2785
- newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2786
- if (!newitem->valuestring)
2787
- {
2788
- goto fail;
2789
- }
2790
- }
2791
- if (item->string)
2792
- {
2793
- newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2794
- if (!newitem->string)
2795
- {
2796
- goto fail;
2797
- }
2798
- }
2799
- /* If non recurse, then we're done! */
2800
- if (!recurse)
2801
- {
2802
- return newitem;
2803
- }
2804
- /* Walk the ->next chain for the child. */
2805
- child = item->child;
2806
- while (child != NULL)
2807
- {
2808
- newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the chain */
2809
- if (!newchild)
2810
- {
2811
- goto fail;
2812
- }
2813
- if (next != NULL)
2814
- {
2815
- /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2816
- next->next = newchild;
2817
- newchild->prev = next;
2818
- next = newchild;
2819
- }
2820
- else
2821
- {
2822
- /* Set newitem->child and move to it */
2823
- newitem->child = newchild;
2824
- next = newchild;
2825
- }
2826
- child = child->next;
2827
- }
2828
- if (newitem && newitem->child)
2829
- {
2830
- newitem->child->prev = newchild;
2831
- }
2832
-
2833
- return newitem;
2834
-
2835
- fail:
2836
- if (newitem != NULL)
2837
- {
2838
- cJSON_Delete(newitem);
2839
- }
2840
-
2841
- return NULL;
2842
- }
2843
-
2844
- static void skip_oneline_comment(char **input)
2845
- {
2846
- *input += static_strlen("//");
2847
-
2848
- for (; (*input)[0] != '\0'; ++(*input))
2849
- {
2850
- if ((*input)[0] == '\n') {
2851
- *input += static_strlen("\n");
2852
- return;
2853
- }
2854
- }
2855
- }
2856
-
2857
- static void skip_multiline_comment(char **input)
2858
- {
2859
- *input += static_strlen("/*");
2860
-
2861
- for (; (*input)[0] != '\0'; ++(*input))
2862
- {
2863
- if (((*input)[0] == '*') && ((*input)[1] == '/'))
2864
- {
2865
- *input += static_strlen("*/");
2866
- return;
2867
- }
2868
- }
2869
- }
2870
-
2871
- static void minify_string(char **input, char **output) {
2872
- (*output)[0] = (*input)[0];
2873
- *input += static_strlen("\"");
2874
- *output += static_strlen("\"");
2875
-
2876
-
2877
- for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2878
- (*output)[0] = (*input)[0];
2879
-
2880
- if ((*input)[0] == '\"') {
2881
- (*output)[0] = '\"';
2882
- *input += static_strlen("\"");
2883
- *output += static_strlen("\"");
2884
- return;
2885
- } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2886
- (*output)[1] = (*input)[1];
2887
- *input += static_strlen("\"");
2888
- *output += static_strlen("\"");
2889
- }
2890
- }
2891
- }
2892
-
2893
- CJSON_PUBLIC(void) cJSON_Minify(char *json)
2894
- {
2895
- char *into = json;
2896
-
2897
- if (json == NULL)
2898
- {
2899
- return;
2900
- }
2901
-
2902
- while (json[0] != '\0')
2903
- {
2904
- switch (json[0])
2905
- {
2906
- case ' ':
2907
- case '\t':
2908
- case '\r':
2909
- case '\n':
2910
- json++;
2911
- break;
2912
-
2913
- case '/':
2914
- if (json[1] == '/')
2915
- {
2916
- skip_oneline_comment(&json);
2917
- }
2918
- else if (json[1] == '*')
2919
- {
2920
- skip_multiline_comment(&json);
2921
- } else {
2922
- json++;
2923
- }
2924
- break;
2925
-
2926
- case '\"':
2927
- minify_string(&json, (char**)&into);
2928
- break;
2929
-
2930
- default:
2931
- into[0] = json[0];
2932
- json++;
2933
- into++;
2934
- }
2935
- }
2936
-
2937
- /* and null-terminate. */
2938
- *into = '\0';
2939
- }
2940
-
2941
- CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2942
- {
2943
- if (item == NULL)
2944
- {
2945
- return false;
2946
- }
2947
-
2948
- return (item->type & 0xFF) == cJSON_Invalid;
2949
- }
2950
-
2951
- CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2952
- {
2953
- if (item == NULL)
2954
- {
2955
- return false;
2956
- }
2957
-
2958
- return (item->type & 0xFF) == cJSON_False;
2959
- }
2960
-
2961
- CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2962
- {
2963
- if (item == NULL)
2964
- {
2965
- return false;
2966
- }
2967
-
2968
- return (item->type & 0xff) == cJSON_True;
2969
- }
2970
-
2971
-
2972
- CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2973
- {
2974
- if (item == NULL)
2975
- {
2976
- return false;
2977
- }
2978
-
2979
- return (item->type & (cJSON_True | cJSON_False)) != 0;
2980
- }
2981
- CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2982
- {
2983
- if (item == NULL)
2984
- {
2985
- return false;
2986
- }
2987
-
2988
- return (item->type & 0xFF) == cJSON_NULL;
2989
- }
2990
-
2991
- CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2992
- {
2993
- if (item == NULL)
2994
- {
2995
- return false;
2996
- }
2997
-
2998
- return (item->type & 0xFF) == cJSON_Number;
2999
- }
3000
-
3001
- CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
3002
- {
3003
- if (item == NULL)
3004
- {
3005
- return false;
3006
- }
3007
-
3008
- return (item->type & 0xFF) == cJSON_String;
3009
- }
3010
-
3011
- CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
3012
- {
3013
- if (item == NULL)
3014
- {
3015
- return false;
3016
- }
3017
-
3018
- return (item->type & 0xFF) == cJSON_Array;
3019
- }
3020
-
3021
- CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
3022
- {
3023
- if (item == NULL)
3024
- {
3025
- return false;
3026
- }
3027
-
3028
- return (item->type & 0xFF) == cJSON_Object;
3029
- }
3030
-
3031
- CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
3032
- {
3033
- if (item == NULL)
3034
- {
3035
- return false;
3036
- }
3037
-
3038
- return (item->type & 0xFF) == cJSON_Raw;
3039
- }
3040
-
3041
- CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
3042
- {
3043
- if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
3044
- {
3045
- return false;
3046
- }
3047
-
3048
- /* check if type is valid */
3049
- switch (a->type & 0xFF)
3050
- {
3051
- case cJSON_False:
3052
- case cJSON_True:
3053
- case cJSON_NULL:
3054
- case cJSON_Number:
3055
- case cJSON_String:
3056
- case cJSON_Raw:
3057
- case cJSON_Array:
3058
- case cJSON_Object:
3059
- break;
3060
-
3061
- default:
3062
- return false;
3063
- }
3064
-
3065
- /* identical objects are equal */
3066
- if (a == b)
3067
- {
3068
- return true;
3069
- }
3070
-
3071
- switch (a->type & 0xFF)
3072
- {
3073
- /* in these cases and equal type is enough */
3074
- case cJSON_False:
3075
- case cJSON_True:
3076
- case cJSON_NULL:
3077
- return true;
3078
-
3079
- case cJSON_Number:
3080
- if (compare_double(a->valuedouble, b->valuedouble))
3081
- {
3082
- return true;
3083
- }
3084
- return false;
3085
-
3086
- case cJSON_String:
3087
- case cJSON_Raw:
3088
- if ((a->valuestring == NULL) || (b->valuestring == NULL))
3089
- {
3090
- return false;
3091
- }
3092
- if (strcmp(a->valuestring, b->valuestring) == 0)
3093
- {
3094
- return true;
3095
- }
3096
-
3097
- return false;
3098
-
3099
- case cJSON_Array:
3100
- {
3101
- cJSON *a_element = a->child;
3102
- cJSON *b_element = b->child;
3103
-
3104
- for (; (a_element != NULL) && (b_element != NULL);)
3105
- {
3106
- if (!cJSON_Compare(a_element, b_element, case_sensitive))
3107
- {
3108
- return false;
3109
- }
3110
-
3111
- a_element = a_element->next;
3112
- b_element = b_element->next;
3113
- }
3114
-
3115
- /* one of the arrays is longer than the other */
3116
- if (a_element != b_element) {
3117
- return false;
3118
- }
3119
-
3120
- return true;
3121
- }
3122
-
3123
- case cJSON_Object:
3124
- {
3125
- cJSON *a_element = NULL;
3126
- cJSON *b_element = NULL;
3127
- cJSON_ArrayForEach(a_element, a)
3128
- {
3129
- /* TODO This has O(n^2) runtime, which is horrible! */
3130
- b_element = get_object_item(b, a_element->string, case_sensitive);
3131
- if (b_element == NULL)
3132
- {
3133
- return false;
3134
- }
3135
-
3136
- if (!cJSON_Compare(a_element, b_element, case_sensitive))
3137
- {
3138
- return false;
3139
- }
3140
- }
3141
-
3142
- /* doing this twice, once on a and b to prevent true comparison if a subset of b
3143
- * TODO: Do this the proper way. */
3144
- cJSON_ArrayForEach(b_element, b)
3145
- {
3146
- a_element = get_object_item(a, b_element->string, case_sensitive);
3147
- if (a_element == NULL)
3148
- {
3149
- return false;
3150
- }
3151
-
3152
- if (!cJSON_Compare(b_element, a_element, case_sensitive))
3153
- {
3154
- return false;
3155
- }
3156
- }
3157
-
3158
- return true;
3159
- }
3160
-
3161
- default:
3162
- return false;
3163
- }
3164
- }
3165
-
3166
- CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3167
- {
3168
- return global_hooks.allocate(size);
3169
- }
3170
-
3171
- CJSON_PUBLIC(void) cJSON_free(void *object)
3172
- {
3173
- global_hooks.deallocate(object);
3174
- }