Coverage Report

Created: 2026-05-30 06:34

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