Coverage Report

Created: 2025-07-18 06:44

/src/cjson/cJSON.c
Line
Count
Source (jump to first uncovered line)
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.38M
#define true ((cJSON_bool)1)
66
67
#ifdef false
68
#undef false
69
#endif
70
84.7k
#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
13.7k
#define isinf(d) (isnan((d - d)) && !isnan(d))
75
#endif
76
#ifndef isnan
77
55.0k
#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 != 18)
121
    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
122
#endif
123
124
CJSON_PUBLIC(const char*) cJSON_Version(void)
125
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
52.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
743k
{
243
743k
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
244
743k
    if (node)
245
743k
    {
246
743k
        memset(node, '\0', sizeof(cJSON));
247
743k
    }
248
249
743k
    return node;
250
743k
}
251
252
/* Delete a cJSON structure. */
253
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
254
296k
{
255
296k
    cJSON *next = NULL;
256
1.04M
    while (item != NULL)
257
743k
    {
258
743k
        next = item->next;
259
743k
        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
260
240k
        {
261
240k
            cJSON_Delete(item->child);
262
240k
        }
263
743k
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
264
4.51k
        {
265
4.51k
            global_hooks.deallocate(item->valuestring);
266
4.51k
            item->valuestring = NULL;
267
4.51k
        }
268
743k
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
269
20.8k
        {
270
20.8k
            global_hooks.deallocate(item->string);
271
20.8k
            item->string = NULL;
272
20.8k
        }
273
743k
        global_hooks.deallocate(item);
274
743k
        item = next;
275
743k
    }
276
296k
}
277
278
/* get the decimal point character of the current locale */
279
static unsigned char get_decimal_point(void)
280
43.0k
{
281
43.0k
#ifdef ENABLE_LOCALES
282
43.0k
    struct lconv *lconv = localeconv();
283
43.0k
    return (unsigned char) lconv->decimal_point[0];
284
#else
285
    return '.';
286
#endif
287
43.0k
}
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.45M
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
300
/* check if the buffer can be accessed at the given index (starting with 0) */
301
18.4M
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
302
3.86M
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
303
/* get a pointer to the buffer at the position */
304
12.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
29.2k
{
309
29.2k
    double number = 0;
310
29.2k
    unsigned char *after_end = NULL;
311
29.2k
    unsigned char *number_c_string;
312
29.2k
    unsigned char decimal_point = get_decimal_point();
313
29.2k
    size_t i = 0;
314
29.2k
    size_t number_string_length = 0;
315
29.2k
    cJSON_bool has_decimal_point = false;
316
317
29.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
229k
    for (i = 0; can_access_at_index(input_buffer, i); i++)
326
229k
    {
327
229k
        switch (buffer_at_offset(input_buffer)[i])
328
229k
        {
329
64.4k
            case '0':
330
85.6k
            case '1':
331
91.2k
            case '2':
332
95.0k
            case '3':
333
101k
            case '4':
334
127k
            case '5':
335
136k
            case '6':
336
142k
            case '7':
337
153k
            case '8':
338
178k
            case '9':
339
179k
            case '+':
340
191k
            case '-':
341
194k
            case 'e':
342
196k
            case 'E':
343
196k
                number_string_length++;
344
196k
                break;
345
346
3.00k
            case '.':
347
3.00k
                number_string_length++;
348
3.00k
                has_decimal_point = true;
349
3.00k
                break;
350
351
29.2k
            default:
352
29.2k
                goto loop_end;
353
229k
        }
354
229k
    }
355
29.2k
loop_end:
356
    /* malloc for temporary buffer, add 1 for '\0' */
357
29.2k
    number_c_string = (unsigned char *) input_buffer->hooks.allocate(number_string_length + 1);
358
29.2k
    if (number_c_string == NULL)
359
0
    {
360
0
        return false; /* allocation failure */
361
0
    }
362
363
29.2k
    memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length);
364
29.2k
    number_c_string[number_string_length] = '\0';
365
366
29.2k
    if (has_decimal_point)
367
670
    {
368
134k
        for (i = 0; i < number_string_length; i++)
369
133k
        {
370
133k
            if (number_c_string[i] == '.')
371
3.00k
            {
372
                /* replace '.' with the decimal point of the current locale (for strtod) */
373
3.00k
                number_c_string[i] = decimal_point;
374
3.00k
            }
375
133k
        }
376
670
    }
377
378
29.2k
    number = strtod((const char*)number_c_string, (char**)&after_end);
379
29.2k
    if (number_c_string == after_end)
380
19
    {
381
        /* free the temporary buffer */
382
19
        input_buffer->hooks.deallocate(number_c_string);
383
19
        return false; /* parse_error */
384
19
    }
385
386
29.2k
    item->valuedouble = number;
387
388
    /* use saturation in case of overflow */
389
29.2k
    if (number >= INT_MAX)
390
3.57k
    {
391
3.57k
        item->valueint = INT_MAX;
392
3.57k
    }
393
25.7k
    else if (number <= (double)INT_MIN)
394
476
    {
395
476
        item->valueint = INT_MIN;
396
476
    }
397
25.2k
    else
398
25.2k
    {
399
25.2k
        item->valueint = (int)number;
400
25.2k
    }
401
402
29.2k
    item->type = cJSON_Number;
403
404
29.2k
    input_buffer->offset += (size_t)(after_end - number_c_string);
405
    /* free the temporary buffer */
406
29.2k
    input_buffer->hooks.deallocate(number_c_string);
407
29.2k
    return true;
408
29.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
1.77M
{
487
1.77M
    unsigned char *newbuffer = NULL;
488
1.77M
    size_t newsize = 0;
489
490
1.77M
    if ((p == NULL) || (p->buffer == NULL))
491
0
    {
492
0
        return NULL;
493
0
    }
494
495
1.77M
    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
1.77M
    if (needed > INT_MAX)
502
0
    {
503
        /* sizes bigger than INT_MAX are currently not supported */
504
0
        return NULL;
505
0
    }
506
507
1.77M
    needed += p->offset + 1;
508
1.77M
    if (needed <= p->length)
509
1.76M
    {
510
1.76M
        return p->buffer + p->offset;
511
1.76M
    }
512
513
1.55k
    if (p->noalloc) {
514
0
        return NULL;
515
0
    }
516
517
    /* calculate new buffer size */
518
1.55k
    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.55k
    else
531
1.55k
    {
532
1.55k
        newsize = needed * 2;
533
1.55k
    }
534
535
1.55k
    if (p->hooks.reallocate != NULL)
536
1.55k
    {
537
        /* reallocate with realloc if available */
538
1.55k
        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
539
1.55k
        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.55k
    }
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.55k
    p->length = newsize;
565
1.55k
    p->buffer = newbuffer;
566
567
1.55k
    return newbuffer + p->offset;
568
1.55k
}
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
671k
{
573
671k
    const unsigned char *buffer_pointer = NULL;
574
671k
    if ((buffer == NULL) || (buffer->buffer == NULL))
575
0
    {
576
0
        return;
577
0
    }
578
671k
    buffer_pointer = buffer->buffer + buffer->offset;
579
580
671k
    buffer->offset += strlen((const char*)buffer_pointer);
581
671k
}
582
583
/* securely comparison of floating-point variables */
584
static cJSON_bool compare_double(double a, double b)
585
836
{
586
836
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
587
836
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
588
836
}
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
13.7k
{
593
13.7k
    unsigned char *output_pointer = NULL;
594
13.7k
    double d = item->valuedouble;
595
13.7k
    int length = 0;
596
13.7k
    size_t i = 0;
597
13.7k
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
598
13.7k
    unsigned char decimal_point = get_decimal_point();
599
13.7k
    double test = 0.0;
600
601
13.7k
    if (output_buffer == NULL)
602
0
    {
603
0
        return false;
604
0
    }
605
606
    /* This checks for NaN and Infinity */
607
13.7k
    if (isnan(d) || isinf(d))
608
194
    {
609
194
        length = sprintf((char*)number_buffer, "null");
610
194
    }
611
13.5k
    else if(d == (double)item->valueint)
612
12.6k
    {
613
12.6k
        length = sprintf((char*)number_buffer, "%d", item->valueint);
614
12.6k
    }
615
836
    else
616
836
    {
617
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
618
836
        length = sprintf((char*)number_buffer, "%1.15g", d);
619
620
        /* Check whether the original double can be recovered */
621
836
        if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
622
389
        {
623
            /* If not, print with 17 decimal places of precision */
624
389
            length = sprintf((char*)number_buffer, "%1.17g", d);
625
389
        }
626
836
    }
627
628
    /* sprintf failed or buffer overrun occurred */
629
13.7k
    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
13.7k
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
636
13.7k
    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
40.6k
    for (i = 0; i < ((size_t)length); i++)
644
26.9k
    {
645
26.9k
        if (number_buffer[i] == decimal_point)
646
417
        {
647
417
            output_pointer[i] = '.';
648
417
            continue;
649
417
        }
650
651
26.5k
        output_pointer[i] = number_buffer[i];
652
26.5k
    }
653
13.7k
    output_pointer[i] = '\0';
654
655
13.7k
    output_buffer->offset += (size_t)length;
656
657
13.7k
    return true;
658
13.7k
}
659
660
/* parse 4 digit hexadecimal number */
661
static unsigned parse_hex4(const unsigned char * const input)
662
64.3k
{
663
64.3k
    unsigned int h = 0;
664
64.3k
    size_t i = 0;
665
666
252k
    for (i = 0; i < 4; i++)
667
214k
    {
668
        /* parse digit */
669
214k
        if ((input[i] >= '0') && (input[i] <= '9'))
670
68.1k
        {
671
68.1k
            h += (unsigned int) input[i] - '0';
672
68.1k
        }
673
146k
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
674
24.0k
        {
675
24.0k
            h += (unsigned int) 10 + input[i] - 'A';
676
24.0k
        }
677
122k
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
678
95.5k
        {
679
95.5k
            h += (unsigned int) 10 + input[i] - 'a';
680
95.5k
        }
681
27.1k
        else /* invalid */
682
27.1k
        {
683
27.1k
            return 0;
684
27.1k
        }
685
686
187k
        if (i < 3)
687
150k
        {
688
            /* shift left to make place for the next nibble */
689
150k
            h = h << 4;
690
150k
        }
691
187k
    }
692
693
37.2k
    return h;
694
64.3k
}
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
59.4k
{
700
59.4k
    long unsigned int codepoint = 0;
701
59.4k
    unsigned int first_code = 0;
702
59.4k
    const unsigned char *first_sequence = input_pointer;
703
59.4k
    unsigned char utf8_length = 0;
704
59.4k
    unsigned char utf8_position = 0;
705
59.4k
    unsigned char sequence_length = 0;
706
59.4k
    unsigned char first_byte_mark = 0;
707
708
59.4k
    if ((input_end - first_sequence) < 6)
709
3
    {
710
        /* input ends unexpectedly */
711
3
        goto fail;
712
3
    }
713
714
    /* get the first utf16 sequence */
715
59.4k
    first_code = parse_hex4(first_sequence + 2);
716
717
    /* check that the code is valid */
718
59.4k
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
719
17
    {
720
17
        goto fail;
721
17
    }
722
723
    /* UTF16 surrogate pair */
724
59.3k
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
725
5.02k
    {
726
5.02k
        const unsigned char *second_sequence = first_sequence + 6;
727
5.02k
        unsigned int second_code = 0;
728
5.02k
        sequence_length = 12; /* \uXXXX\uXXXX */
729
730
5.02k
        if ((input_end - second_sequence) < 6)
731
18
        {
732
            /* input ends unexpectedly */
733
18
            goto fail;
734
18
        }
735
736
5.00k
        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
737
28
        {
738
            /* missing second half of the surrogate pair */
739
28
            goto fail;
740
28
        }
741
742
        /* get the second utf16 sequence */
743
4.97k
        second_code = parse_hex4(second_sequence + 2);
744
        /* check that the code is valid */
745
4.97k
        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
746
59
        {
747
            /* invalid second half of the surrogate pair */
748
59
            goto fail;
749
59
        }
750
751
752
        /* calculate the unicode codepoint from the surrogate pair */
753
4.91k
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
754
4.91k
    }
755
54.3k
    else
756
54.3k
    {
757
54.3k
        sequence_length = 6; /* \uXXXX */
758
54.3k
        codepoint = first_code;
759
54.3k
    }
760
761
    /* encode as UTF-8
762
     * takes at maximum 4 bytes to encode:
763
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
764
59.2k
    if (codepoint < 0x80)
765
29.7k
    {
766
        /* normal ascii, encoding 0xxxxxxx */
767
29.7k
        utf8_length = 1;
768
29.7k
    }
769
29.4k
    else if (codepoint < 0x800)
770
7.83k
    {
771
        /* two bytes, encoding 110xxxxx 10xxxxxx */
772
7.83k
        utf8_length = 2;
773
7.83k
        first_byte_mark = 0xC0; /* 11000000 */
774
7.83k
    }
775
21.6k
    else if (codepoint < 0x10000)
776
16.7k
    {
777
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
778
16.7k
        utf8_length = 3;
779
16.7k
        first_byte_mark = 0xE0; /* 11100000 */
780
16.7k
    }
781
4.91k
    else if (codepoint <= 0x10FFFF)
782
4.91k
    {
783
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
784
4.91k
        utf8_length = 4;
785
4.91k
        first_byte_mark = 0xF0; /* 11110000 */
786
4.91k
    }
787
0
    else
788
0
    {
789
        /* invalid unicode codepoint */
790
0
        goto fail;
791
0
    }
792
793
    /* encode as utf8 */
794
115k
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
795
56.0k
    {
796
        /* 10xxxxxx */
797
56.0k
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
798
56.0k
        codepoint >>= 6;
799
56.0k
    }
800
    /* encode first byte */
801
59.2k
    if (utf8_length > 1)
802
29.4k
    {
803
29.4k
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
804
29.4k
    }
805
29.7k
    else
806
29.7k
    {
807
29.7k
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
808
29.7k
    }
809
810
59.2k
    *output_pointer += utf8_length;
811
812
59.2k
    return sequence_length;
813
814
125
fail:
815
125
    return 0;
816
59.2k
}
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
25.7k
{
821
25.7k
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
822
25.7k
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
823
25.7k
    unsigned char *output_pointer = NULL;
824
25.7k
    unsigned char *output = NULL;
825
826
    /* not a string */
827
25.7k
    if (buffer_at_offset(input_buffer)[0] != '\"')
828
139
    {
829
139
        goto fail;
830
139
    }
831
832
25.6k
    {
833
        /* calculate approximate size of the output (overestimate) */
834
25.6k
        size_t allocation_length = 0;
835
25.6k
        size_t skipped_bytes = 0;
836
25.3M
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
837
25.3M
        {
838
            /* is escape sequence */
839
25.3M
            if (input_end[0] == '\\')
840
169k
            {
841
169k
                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
169k
                skipped_bytes++;
847
169k
                input_end++;
848
169k
            }
849
25.3M
            input_end++;
850
25.3M
        }
851
25.6k
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
852
68
        {
853
68
            goto fail; /* string ended unexpectedly */
854
68
        }
855
856
        /* This is at most how much we need for the output */
857
25.5k
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
858
25.5k
        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
859
25.5k
        if (output == NULL)
860
0
        {
861
0
            goto fail; /* allocation failure */
862
0
        }
863
25.5k
    }
864
865
25.5k
    output_pointer = output;
866
    /* loop through the string literal */
867
24.1M
    while (input_pointer < input_end)
868
24.0M
    {
869
24.0M
        if (*input_pointer != '\\')
870
23.9M
        {
871
23.9M
            *output_pointer++ = *input_pointer++;
872
23.9M
        }
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.39k
                case 'b':
885
9.39k
                    *output_pointer++ = '\b';
886
9.39k
                    break;
887
2.56k
                case 'f':
888
2.56k
                    *output_pointer++ = '\f';
889
2.56k
                    break;
890
4.40k
                case 'n':
891
4.40k
                    *output_pointer++ = '\n';
892
4.40k
                    break;
893
6.44k
                case 'r':
894
6.44k
                    *output_pointer++ = '\r';
895
6.44k
                    break;
896
9.92k
                case 't':
897
9.92k
                    *output_pointer++ = '\t';
898
9.92k
                    break;
899
17.0k
                case '\"':
900
34.3k
                case '\\':
901
54.0k
                case '/':
902
54.0k
                    *output_pointer++ = input_pointer[1];
903
54.0k
                    break;
904
905
                /* UTF-16 literal */
906
59.4k
                case 'u':
907
59.4k
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
908
59.4k
                    if (sequence_length == 0)
909
125
                    {
910
                        /* failed to convert UTF16-literal to UTF-8 */
911
125
                        goto fail;
912
125
                    }
913
59.2k
                    break;
914
915
59.2k
                default:
916
13
                    goto fail;
917
146k
            }
918
146k
            input_pointer += sequence_length;
919
146k
        }
920
24.0M
    }
921
922
    /* zero terminate the output */
923
25.4k
    *output_pointer = '\0';
924
925
25.4k
    item->type = cJSON_String;
926
25.4k
    item->valuestring = (char*)output;
927
928
25.4k
    input_buffer->offset = (size_t) (input_end - input_buffer->content);
929
25.4k
    input_buffer->offset++;
930
931
25.4k
    return true;
932
933
345
fail:
934
345
    if (output != NULL)
935
138
    {
936
138
        input_buffer->hooks.deallocate(output);
937
138
        output = NULL;
938
138
    }
939
940
345
    if (input_pointer != NULL)
941
345
    {
942
345
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
943
345
    }
944
945
345
    return false;
946
25.5k
}
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
12.0k
{
951
12.0k
    const unsigned char *input_pointer = NULL;
952
12.0k
    unsigned char *output = NULL;
953
12.0k
    unsigned char *output_pointer = NULL;
954
12.0k
    size_t output_length = 0;
955
    /* numbers of additional characters needed for escaping */
956
12.0k
    size_t escape_characters = 0;
957
958
12.0k
    if (output_buffer == NULL)
959
0
    {
960
0
        return false;
961
0
    }
962
963
    /* empty string */
964
12.0k
    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
8.56M
    for (input_pointer = input; *input_pointer; input_pointer++)
978
8.54M
    {
979
8.54M
        switch (*input_pointer)
980
8.54M
        {
981
1.25k
            case '\"':
982
4.79k
            case '\\':
983
9.76k
            case '\b':
984
15.9k
            case '\f':
985
93.7k
            case '\n':
986
102k
            case '\r':
987
104k
            case '\t':
988
                /* one character escape sequence */
989
104k
                escape_characters++;
990
104k
                break;
991
8.44M
            default:
992
8.44M
                if (*input_pointer < 32)
993
5.71M
                {
994
                    /* UTF-16 escape sequence uXXXX */
995
5.71M
                    escape_characters += 5;
996
5.71M
                }
997
8.44M
                break;
998
8.54M
        }
999
8.54M
    }
1000
12.0k
    output_length = (size_t)(input_pointer - input) + escape_characters;
1001
1002
12.0k
    output = ensure(output_buffer, output_length + sizeof("\"\""));
1003
12.0k
    if (output == NULL)
1004
0
    {
1005
0
        return false;
1006
0
    }
1007
1008
    /* no characters have to be escaped */
1009
12.0k
    if (escape_characters == 0)
1010
11.5k
    {
1011
11.5k
        output[0] = '\"';
1012
11.5k
        memcpy(output + 1, input, output_length);
1013
11.5k
        output[output_length + 1] = '\"';
1014
11.5k
        output[output_length + 2] = '\0';
1015
1016
11.5k
        return true;
1017
11.5k
    }
1018
1019
546
    output[0] = '\"';
1020
546
    output_pointer = output + 1;
1021
    /* copy the string */
1022
8.54M
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
1023
8.54M
    {
1024
8.54M
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1025
2.72M
        {
1026
            /* normal character, copy */
1027
2.72M
            *output_pointer = *input_pointer;
1028
2.72M
        }
1029
5.81M
        else
1030
5.81M
        {
1031
            /* character needs to be escaped */
1032
5.81M
            *output_pointer++ = '\\';
1033
5.81M
            switch (*input_pointer)
1034
5.81M
            {
1035
3.53k
                case '\\':
1036
3.53k
                    *output_pointer = '\\';
1037
3.53k
                    break;
1038
1.25k
                case '\"':
1039
1.25k
                    *output_pointer = '\"';
1040
1.25k
                    break;
1041
4.96k
                case '\b':
1042
4.96k
                    *output_pointer = 'b';
1043
4.96k
                    break;
1044
6.15k
                case '\f':
1045
6.15k
                    *output_pointer = 'f';
1046
6.15k
                    break;
1047
77.8k
                case '\n':
1048
77.8k
                    *output_pointer = 'n';
1049
77.8k
                    break;
1050
9.23k
                case '\r':
1051
9.23k
                    *output_pointer = 'r';
1052
9.23k
                    break;
1053
1.45k
                case '\t':
1054
1.45k
                    *output_pointer = 't';
1055
1.45k
                    break;
1056
5.71M
                default:
1057
                    /* escape and print as unicode codepoint */
1058
5.71M
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
1059
5.71M
                    output_pointer += 4;
1060
5.71M
                    break;
1061
5.81M
            }
1062
5.81M
        }
1063
8.54M
    }
1064
546
    output[output_length + 1] = '\"';
1065
546
    output[output_length + 2] = '\0';
1066
1067
546
    return true;
1068
546
}
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
895
{
1073
895
    return print_string_ptr((unsigned char*)item->valuestring, p);
1074
895
}
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.18M
{
1087
2.18M
    if ((buffer == NULL) || (buffer->content == NULL))
1088
0
    {
1089
0
        return NULL;
1090
0
    }
1091
1092
2.18M
    if (cannot_access_at_index(buffer, 0))
1093
0
    {
1094
0
        return buffer;
1095
0
    }
1096
1097
3.49M
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1098
1.31M
    {
1099
1.31M
       buffer->offset++;
1100
1.31M
    }
1101
1102
2.18M
    if (buffer->offset == buffer->length)
1103
907
    {
1104
907
        buffer->offset--;
1105
907
    }
1106
1107
2.18M
    return buffer;
1108
2.18M
}
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
1.97k
{
1113
1.97k
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1114
0
    {
1115
0
        return NULL;
1116
0
    }
1117
1118
1.97k
    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1119
77
    {
1120
77
        buffer->offset += 3;
1121
77
    }
1122
1123
1.97k
    return buffer;
1124
1.97k
}
1125
1126
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1127
1.97k
{
1128
1.97k
    size_t buffer_length;
1129
1130
1.97k
    if (NULL == value)
1131
0
    {
1132
0
        return NULL;
1133
0
    }
1134
1135
    /* Adding null character size due to require_null_terminated. */
1136
1.97k
    buffer_length = strlen(value) + sizeof("");
1137
1138
1.97k
    return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1139
1.97k
}
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
1.97k
{
1144
1.97k
    parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1145
1.97k
    cJSON *item = NULL;
1146
1147
    /* reset error position */
1148
1.97k
    global_error.json = NULL;
1149
1.97k
    global_error.position = 0;
1150
1151
1.97k
    if (value == NULL || 0 == buffer_length)
1152
0
    {
1153
0
        goto fail;
1154
0
    }
1155
1156
1.97k
    buffer.content = (const unsigned char*)value;
1157
1.97k
    buffer.length = buffer_length;
1158
1.97k
    buffer.offset = 0;
1159
1.97k
    buffer.hooks = global_hooks;
1160
1161
1.97k
    item = cJSON_New_Item(&global_hooks);
1162
1.97k
    if (item == NULL) /* memory fail */
1163
0
    {
1164
0
        goto fail;
1165
0
    }
1166
1167
1.97k
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1168
875
    {
1169
        /* parse failure. ep is set. */
1170
875
        goto fail;
1171
875
    }
1172
1173
    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1174
1.10k
    if (require_null_terminated)
1175
338
    {
1176
338
        buffer_skip_whitespace(&buffer);
1177
338
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1178
42
        {
1179
42
            goto fail;
1180
42
        }
1181
338
    }
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
917
fail:
1190
917
    if (item != NULL)
1191
917
    {
1192
917
        cJSON_Delete(item);
1193
917
    }
1194
1195
917
    if (value != NULL)
1196
917
    {
1197
917
        error local_error;
1198
917
        local_error.json = (const unsigned char*)value;
1199
917
        local_error.position = 0;
1200
1201
917
        if (buffer.offset < buffer.length)
1202
797
        {
1203
797
            local_error.position = buffer.offset;
1204
797
        }
1205
120
        else if (buffer.length > 0)
1206
120
        {
1207
120
            local_error.position = buffer.length - 1;
1208
120
        }
1209
1210
917
        if (return_parse_end != NULL)
1211
0
        {
1212
0
            *return_parse_end = (const char*)local_error.json + local_error.position;
1213
0
        }
1214
1215
917
        global_error = local_error;
1216
917
    }
1217
1218
917
    return NULL;
1219
1.10k
}
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
559
{
1236
559
    static const size_t default_buffer_size = 256;
1237
559
    printbuffer buffer[1];
1238
559
    unsigned char *printed = NULL;
1239
1240
559
    memset(buffer, 0, sizeof(buffer));
1241
1242
    /* create buffer */
1243
559
    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1244
559
    buffer->length = default_buffer_size;
1245
559
    buffer->format = format;
1246
559
    buffer->hooks = *hooks;
1247
559
    if (buffer->buffer == NULL)
1248
0
    {
1249
0
        goto fail;
1250
0
    }
1251
1252
    /* print the value */
1253
559
    if (!print_value(item, buffer))
1254
0
    {
1255
0
        goto fail;
1256
0
    }
1257
559
    update_offset(buffer);
1258
1259
    /* check if reallocate is available */
1260
559
    if (hooks->reallocate != NULL)
1261
559
    {
1262
559
        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1263
559
        if (printed == NULL) {
1264
0
            goto fail;
1265
0
        }
1266
559
        buffer->buffer = NULL;
1267
559
    }
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
559
    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
559
}
1300
1301
/* Render a cJSON item/entity/structure to text. */
1302
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1303
296
{
1304
296
    return (char*)print(item, true, &global_hooks);
1305
296
}
1306
1307
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1308
263
{
1309
263
    return (char*)print(item, false, &global_hooks);
1310
263
}
1311
1312
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1313
503
{
1314
503
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1315
1316
503
    if (prebuffer < 0)
1317
0
    {
1318
0
        return NULL;
1319
0
    }
1320
1321
503
    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1322
503
    if (!p.buffer)
1323
0
    {
1324
0
        return NULL;
1325
0
    }
1326
1327
503
    p.length = (size_t)prebuffer;
1328
503
    p.offset = 0;
1329
503
    p.noalloc = false;
1330
503
    p.format = fmt;
1331
503
    p.hooks = global_hooks;
1332
1333
503
    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
503
    return (char*)p.buffer;
1341
503
}
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
743k
{
1365
743k
    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
743k
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1373
520
    {
1374
520
        item->type = cJSON_NULL;
1375
520
        input_buffer->offset += 4;
1376
520
        return true;
1377
520
    }
1378
    /* false */
1379
742k
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1380
590
    {
1381
590
        item->type = cJSON_False;
1382
590
        input_buffer->offset += 5;
1383
590
        return true;
1384
590
    }
1385
    /* true */
1386
742k
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1387
469
    {
1388
469
        item->type = cJSON_True;
1389
469
        item->valueint = 1;
1390
469
        input_buffer->offset += 4;
1391
469
        return true;
1392
469
    }
1393
    /* string */
1394
741k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1395
4.71k
    {
1396
4.71k
        return parse_string(item, input_buffer);
1397
4.71k
    }
1398
    /* number */
1399
737k
    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
29.2k
    {
1401
29.2k
        return parse_number(item, input_buffer);
1402
29.2k
    }
1403
    /* array */
1404
707k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1405
284k
    {
1406
284k
        return parse_array(item, input_buffer);
1407
284k
    }
1408
    /* object */
1409
423k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1410
422k
    {
1411
422k
        return parse_object(item, input_buffer);
1412
422k
    }
1413
1414
319
    return false;
1415
423k
}
1416
1417
/* Render a value to text. */
1418
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1419
660k
{
1420
660k
    unsigned char *output = NULL;
1421
1422
660k
    if ((item == NULL) || (output_buffer == NULL))
1423
0
    {
1424
0
        return false;
1425
0
    }
1426
1427
660k
    switch ((item->type) & 0xFF)
1428
660k
    {
1429
326
        case cJSON_NULL:
1430
326
            output = ensure(output_buffer, 5);
1431
326
            if (output == NULL)
1432
0
            {
1433
0
                return false;
1434
0
            }
1435
326
            strcpy((char*)output, "null");
1436
326
            return true;
1437
1438
294
        case cJSON_False:
1439
294
            output = ensure(output_buffer, 6);
1440
294
            if (output == NULL)
1441
0
            {
1442
0
                return false;
1443
0
            }
1444
294
            strcpy((char*)output, "false");
1445
294
            return true;
1446
1447
209
        case cJSON_True:
1448
209
            output = ensure(output_buffer, 5);
1449
209
            if (output == NULL)
1450
0
            {
1451
0
                return false;
1452
0
            }
1453
209
            strcpy((char*)output, "true");
1454
209
            return true;
1455
1456
13.7k
        case cJSON_Number:
1457
13.7k
            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
895
        case cJSON_String:
1478
895
            return print_string(item, output_buffer);
1479
1480
230k
        case cJSON_Array:
1481
230k
            return print_array(item, output_buffer);
1482
1483
414k
        case cJSON_Object:
1484
414k
            return print_object(item, output_buffer);
1485
1486
0
        default:
1487
0
            return false;
1488
660k
    }
1489
660k
}
1490
1491
/* Build an array from input text. */
1492
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1493
284k
{
1494
284k
    cJSON *head = NULL; /* head of the linked list */
1495
284k
    cJSON *current_item = NULL;
1496
1497
284k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1498
1
    {
1499
1
        return false; /* to deeply nested */
1500
1
    }
1501
284k
    input_buffer->depth++;
1502
1503
284k
    if (buffer_at_offset(input_buffer)[0] != '[')
1504
0
    {
1505
        /* not an array */
1506
0
        goto fail;
1507
0
    }
1508
1509
284k
    input_buffer->offset++;
1510
284k
    buffer_skip_whitespace(input_buffer);
1511
284k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1512
2.90k
    {
1513
        /* empty array */
1514
2.90k
        goto success;
1515
2.90k
    }
1516
1517
    /* check if we skipped to the end of the buffer */
1518
281k
    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
281k
    input_buffer->offset--;
1526
    /* loop through the comma separated array elements */
1527
281k
    do
1528
720k
    {
1529
        /* allocate next item */
1530
720k
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1531
720k
        if (new_item == NULL)
1532
0
        {
1533
0
            goto fail; /* allocation failure */
1534
0
        }
1535
1536
        /* attach next item to list */
1537
720k
        if (head == NULL)
1538
281k
        {
1539
            /* start the linked list */
1540
281k
            current_item = head = new_item;
1541
281k
        }
1542
438k
        else
1543
438k
        {
1544
            /* add to the end and advance */
1545
438k
            current_item->next = new_item;
1546
438k
            new_item->prev = current_item;
1547
438k
            current_item = new_item;
1548
438k
        }
1549
1550
        /* parse next value */
1551
720k
        input_buffer->offset++;
1552
720k
        buffer_skip_whitespace(input_buffer);
1553
720k
        if (!parse_value(current_item, input_buffer))
1554
50.4k
        {
1555
50.4k
            goto fail; /* failed to parse value */
1556
50.4k
        }
1557
670k
        buffer_skip_whitespace(input_buffer);
1558
670k
    }
1559
670k
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1560
1561
231k
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1562
121
    {
1563
121
        goto fail; /* expected end of array */
1564
121
    }
1565
1566
234k
success:
1567
234k
    input_buffer->depth--;
1568
1569
234k
    if (head != NULL) {
1570
231k
        head->prev = current_item;
1571
231k
    }
1572
1573
234k
    item->type = cJSON_Array;
1574
234k
    item->child = head;
1575
1576
234k
    input_buffer->offset++;
1577
1578
234k
    return true;
1579
1580
50.5k
fail:
1581
50.5k
    if (head != NULL)
1582
50.5k
    {
1583
50.5k
        cJSON_Delete(head);
1584
50.5k
    }
1585
1586
50.5k
    return false;
1587
231k
}
1588
1589
/* Render an array to text */
1590
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1591
230k
{
1592
230k
    unsigned char *output_pointer = NULL;
1593
230k
    size_t length = 0;
1594
230k
    cJSON *current_element = item->child;
1595
1596
230k
    if (output_buffer == NULL)
1597
0
    {
1598
0
        return false;
1599
0
    }
1600
1601
    /* Compose the output array. */
1602
    /* opening square bracket */
1603
230k
    output_pointer = ensure(output_buffer, 1);
1604
230k
    if (output_pointer == NULL)
1605
0
    {
1606
0
        return false;
1607
0
    }
1608
1609
230k
    *output_pointer = '[';
1610
230k
    output_buffer->offset++;
1611
230k
    output_buffer->depth++;
1612
1613
879k
    while (current_element != NULL)
1614
648k
    {
1615
648k
        if (!print_value(current_element, output_buffer))
1616
0
        {
1617
0
            return false;
1618
0
        }
1619
648k
        update_offset(output_buffer);
1620
648k
        if (current_element->next)
1621
420k
        {
1622
420k
            length = (size_t) (output_buffer->format ? 2 : 1);
1623
420k
            output_pointer = ensure(output_buffer, length + 1);
1624
420k
            if (output_pointer == NULL)
1625
0
            {
1626
0
                return false;
1627
0
            }
1628
420k
            *output_pointer++ = ',';
1629
420k
            if(output_buffer->format)
1630
419k
            {
1631
419k
                *output_pointer++ = ' ';
1632
419k
            }
1633
420k
            *output_pointer = '\0';
1634
420k
            output_buffer->offset += length;
1635
420k
        }
1636
648k
        current_element = current_element->next;
1637
648k
    }
1638
1639
230k
    output_pointer = ensure(output_buffer, 2);
1640
230k
    if (output_pointer == NULL)
1641
0
    {
1642
0
        return false;
1643
0
    }
1644
230k
    *output_pointer++ = ']';
1645
230k
    *output_pointer = '\0';
1646
230k
    output_buffer->depth--;
1647
1648
230k
    return true;
1649
230k
}
1650
1651
/* Build an object from the text. */
1652
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1653
422k
{
1654
422k
    cJSON *head = NULL; /* linked list head */
1655
422k
    cJSON *current_item = NULL;
1656
1657
422k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1658
2
    {
1659
2
        return false; /* to deeply nested */
1660
2
    }
1661
422k
    input_buffer->depth++;
1662
1663
422k
    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
422k
    input_buffer->offset++;
1669
422k
    buffer_skip_whitespace(input_buffer);
1670
422k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1671
409k
    {
1672
409k
        goto success; /* empty object */
1673
409k
    }
1674
1675
    /* check if we skipped to the end of the buffer */
1676
12.8k
    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
12.8k
    input_buffer->offset--;
1684
    /* loop through the comma separated array elements */
1685
12.8k
    do
1686
21.0k
    {
1687
        /* allocate next item */
1688
21.0k
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1689
21.0k
        if (new_item == NULL)
1690
0
        {
1691
0
            goto fail; /* allocation failure */
1692
0
        }
1693
1694
        /* attach next item to list */
1695
21.0k
        if (head == NULL)
1696
12.8k
        {
1697
            /* start the linked list */
1698
12.8k
            current_item = head = new_item;
1699
12.8k
        }
1700
8.22k
        else
1701
8.22k
        {
1702
            /* add to the end and advance */
1703
8.22k
            current_item->next = new_item;
1704
8.22k
            new_item->prev = current_item;
1705
8.22k
            current_item = new_item;
1706
8.22k
        }
1707
1708
21.0k
        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
21.0k
        input_buffer->offset++;
1715
21.0k
        buffer_skip_whitespace(input_buffer);
1716
21.0k
        if (!parse_string(current_item, input_buffer))
1717
147
        {
1718
147
            goto fail; /* failed to parse name */
1719
147
        }
1720
20.8k
        buffer_skip_whitespace(input_buffer);
1721
1722
        /* swap valuestring and string, because we parsed the name */
1723
20.8k
        current_item->string = current_item->valuestring;
1724
20.8k
        current_item->valuestring = NULL;
1725
1726
20.8k
        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
20.8k
        input_buffer->offset++;
1733
20.8k
        buffer_skip_whitespace(input_buffer);
1734
20.8k
        if (!parse_value(current_item, input_buffer))
1735
3.23k
        {
1736
3.23k
            goto fail; /* failed to parse value */
1737
3.23k
        }
1738
17.6k
        buffer_skip_whitespace(input_buffer);
1739
17.6k
    }
1740
17.6k
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1741
1742
9.39k
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1743
38
    {
1744
38
        goto fail; /* expected end of object */
1745
38
    }
1746
1747
419k
success:
1748
419k
    input_buffer->depth--;
1749
1750
419k
    if (head != NULL) {
1751
9.35k
        head->prev = current_item;
1752
9.35k
    }
1753
1754
419k
    item->type = cJSON_Object;
1755
419k
    item->child = head;
1756
1757
419k
    input_buffer->offset++;
1758
419k
    return true;
1759
1760
3.45k
fail:
1761
3.45k
    if (head != NULL)
1762
3.45k
    {
1763
3.45k
        cJSON_Delete(head);
1764
3.45k
    }
1765
1766
3.45k
    return false;
1767
9.39k
}
1768
1769
/* Render an object to text. */
1770
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1771
414k
{
1772
414k
    unsigned char *output_pointer = NULL;
1773
414k
    size_t length = 0;
1774
414k
    cJSON *current_item = item->child;
1775
1776
414k
    if (output_buffer == NULL)
1777
0
    {
1778
0
        return false;
1779
0
    }
1780
1781
    /* Compose the output: */
1782
414k
    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1783
414k
    output_pointer = ensure(output_buffer, length + 1);
1784
414k
    if (output_pointer == NULL)
1785
0
    {
1786
0
        return false;
1787
0
    }
1788
1789
414k
    *output_pointer++ = '{';
1790
414k
    output_buffer->depth++;
1791
414k
    if (output_buffer->format)
1792
414k
    {
1793
414k
        *output_pointer++ = '\n';
1794
414k
    }
1795
414k
    output_buffer->offset += length;
1796
1797
426k
    while (current_item)
1798
11.1k
    {
1799
11.1k
        if (output_buffer->format)
1800
10.8k
        {
1801
10.8k
            size_t i;
1802
10.8k
            output_pointer = ensure(output_buffer, output_buffer->depth);
1803
10.8k
            if (output_pointer == NULL)
1804
0
            {
1805
0
                return false;
1806
0
            }
1807
4.48M
            for (i = 0; i < output_buffer->depth; i++)
1808
4.47M
            {
1809
4.47M
                *output_pointer++ = '\t';
1810
4.47M
            }
1811
10.8k
            output_buffer->offset += output_buffer->depth;
1812
10.8k
        }
1813
1814
        /* print key */
1815
11.1k
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1816
0
        {
1817
0
            return false;
1818
0
        }
1819
11.1k
        update_offset(output_buffer);
1820
1821
11.1k
        length = (size_t) (output_buffer->format ? 2 : 1);
1822
11.1k
        output_pointer = ensure(output_buffer, length);
1823
11.1k
        if (output_pointer == NULL)
1824
0
        {
1825
0
            return false;
1826
0
        }
1827
11.1k
        *output_pointer++ = ':';
1828
11.1k
        if (output_buffer->format)
1829
10.8k
        {
1830
10.8k
            *output_pointer++ = '\t';
1831
10.8k
        }
1832
11.1k
        output_buffer->offset += length;
1833
1834
        /* print value */
1835
11.1k
        if (!print_value(current_item, output_buffer))
1836
0
        {
1837
0
            return false;
1838
0
        }
1839
11.1k
        update_offset(output_buffer);
1840
1841
        /* print comma if not last */
1842
11.1k
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1843
11.1k
        output_pointer = ensure(output_buffer, length + 1);
1844
11.1k
        if (output_pointer == NULL)
1845
0
        {
1846
0
            return false;
1847
0
        }
1848
11.1k
        if (current_item->next)
1849
2.47k
        {
1850
2.47k
            *output_pointer++ = ',';
1851
2.47k
        }
1852
1853
11.1k
        if (output_buffer->format)
1854
10.8k
        {
1855
10.8k
            *output_pointer++ = '\n';
1856
10.8k
        }
1857
11.1k
        *output_pointer = '\0';
1858
11.1k
        output_buffer->offset += length;
1859
1860
11.1k
        current_item = current_item->next;
1861
11.1k
    }
1862
1863
414k
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1864
414k
    if (output_pointer == NULL)
1865
0
    {
1866
0
        return false;
1867
0
    }
1868
414k
    if (output_buffer->format)
1869
414k
    {
1870
414k
        size_t i;
1871
219M
        for (i = 0; i < (output_buffer->depth - 1); i++)
1872
219M
        {
1873
219M
            *output_pointer++ = '\t';
1874
219M
        }
1875
414k
    }
1876
414k
    *output_pointer++ = '}';
1877
414k
    *output_pointer = '\0';
1878
414k
    output_buffer->depth--;
1879
1880
414k
    return true;
1881
414k
}
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
498
{
2862
498
    *input += static_strlen("//");
2863
2864
14.2k
    for (; (*input)[0] != '\0'; ++(*input))
2865
14.2k
    {
2866
14.2k
        if ((*input)[0] == '\n') {
2867
474
            *input += static_strlen("\n");
2868
474
            return;
2869
474
        }
2870
14.2k
    }
2871
498
}
2872
2873
static void skip_multiline_comment(char **input)
2874
239
{
2875
239
    *input += static_strlen("/*");
2876
2877
853
    for (; (*input)[0] != '\0'; ++(*input))
2878
808
    {
2879
808
        if (((*input)[0] == '*') && ((*input)[1] == '/'))
2880
194
        {
2881
194
            *input += static_strlen("*/");
2882
194
            return;
2883
194
        }
2884
808
    }
2885
239
}
2886
2887
11.8k
static void minify_string(char **input, char **output) {
2888
11.8k
    (*output)[0] = (*input)[0];
2889
11.8k
    *input += static_strlen("\"");
2890
11.8k
    *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
11.8k
            (*output)[0] = '\"';
2898
11.8k
            *input += static_strlen("\"");
2899
11.8k
            *output += static_strlen("\"");
2900
11.8k
            return;
2901
11.4M
        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2902
1.67k
            (*output)[1] = (*input)[1];
2903
1.67k
            *input += static_strlen("\"");
2904
1.67k
            *output += static_strlen("\"");
2905
1.67k
        }
2906
11.4M
    }
2907
11.8k
}
2908
2909
CJSON_PUBLIC(void) cJSON_Minify(char *json)
2910
853
{
2911
853
    char *into = json;
2912
2913
853
    if (json == NULL)
2914
0
    {
2915
0
        return;
2916
0
    }
2917
2918
1.79M
    while (json[0] != '\0')
2919
1.79M
    {
2920
1.79M
        switch (json[0])
2921
1.79M
        {
2922
448
            case ' ':
2923
654
            case '\t':
2924
2.24k
            case '\r':
2925
3.46k
            case '\n':
2926
3.46k
                json++;
2927
3.46k
                break;
2928
2929
1.16k
            case '/':
2930
1.16k
                if (json[1] == '/')
2931
498
                {
2932
498
                    skip_oneline_comment(&json);
2933
498
                }
2934
668
                else if (json[1] == '*')
2935
239
                {
2936
239
                    skip_multiline_comment(&json);
2937
429
                } else {
2938
429
                    json++;
2939
429
                }
2940
1.16k
                break;
2941
2942
11.8k
            case '\"':
2943
11.8k
                minify_string(&json, (char**)&into);
2944
11.8k
                break;
2945
2946
1.77M
            default:
2947
1.77M
                into[0] = json[0];
2948
1.77M
                json++;
2949
1.77M
                into++;
2950
1.79M
        }
2951
1.79M
    }
2952
2953
    /* and null-terminate. */
2954
853
    *into = '\0';
2955
853
}
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
0
    object = NULL;
3191
0
}