Coverage Report

Created: 2026-01-10 06:28

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