Coverage Report

Created: 2026-08-30 07:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vulkan-loader/loader/cJSON.c
Line
Count
Source
1
/*
2
  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
3
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
  of this software and associated documentation files (the "Software"), to deal
6
  in the Software without restriction, including without limitation the rights
7
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
  copies of the Software, and to permit persons to whom the Software is
9
  furnished to do so, subject to the following conditions:
10
11
  The above copyright notice and this permission notice shall be included in
12
  all copies or substantial portions of the Software.
13
14
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
  THE SOFTWARE.
21
*/
22
23
/* cJSON */
24
/* JSON parser in C. */
25
26
/* disable warnings about old C89 functions in MSVC */
27
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
28
#define _CRT_SECURE_NO_DEPRECATE
29
#endif
30
31
#ifdef __GNUC__
32
#pragma GCC visibility push(default)
33
#endif
34
#if defined(_MSC_VER)
35
#pragma warning(push)
36
/* disable warning about single line comments in system headers */
37
#pragma warning(disable : 4001)
38
#endif
39
40
#include <string.h>
41
#include <stdio.h>
42
#include <math.h>
43
#include <stdlib.h>
44
#include <limits.h>
45
#include <ctype.h>
46
#include <float.h>
47
48
#ifdef ENABLE_LOCALES
49
#include <locale.h>
50
#endif
51
52
#if defined(_MSC_VER)
53
#pragma warning(pop)
54
#endif
55
#ifdef __GNUC__
56
#pragma GCC visibility pop
57
#endif
58
59
#include "cJSON.h"
60
61
#include "allocation.h"
62
63
/* define our own boolean type */
64
#ifdef true
65
#undef true
66
#endif
67
20.3M
#define true ((cJSON_bool)1)
68
69
#ifdef false
70
#undef false
71
#endif
72
70.2k
#define false ((cJSON_bool)0)
73
74
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
75
#ifndef isinf
76
#define isinf(d) (isnan((d - d)) && !isnan(d))
77
#endif
78
#ifndef isnan
79
#define isnan(d) (d != d)
80
#endif
81
82
#ifndef NAN
83
#ifdef _WIN32
84
#define NAN sqrt(-1.0)
85
#else
86
#define NAN 0.0 / 0.0
87
#endif
88
#endif
89
90
typedef struct {
91
    const unsigned char *json;
92
    size_t position;
93
} error;
94
static error global_error = {NULL, 0};
95
96
0
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) { return (const char *)(global_error.json + global_error.position); }
97
98
0
CJSON_PUBLIC(char *) loader_cJSON_GetStringValue(const cJSON *const item) {
99
0
    if (!loader_cJSON_IsString(item)) {
100
0
        return NULL;
101
0
    }
102
103
0
    return item->valuestring;
104
0
}
105
106
0
CJSON_PUBLIC(double) loader_cJSON_GetNumberValue(const cJSON *const item) {
107
0
    if (!loader_cJSON_IsNumber(item)) {
108
0
        return (double)NAN;
109
0
    }
110
111
0
    return item->valuedouble;
112
0
}
113
114
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
115
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18)
116
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
117
#endif
118
119
/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
120
0
static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) {
121
0
    if ((string1 == NULL) || (string2 == NULL)) {
122
0
        return 1;
123
0
    }
124
125
0
    if (string1 == string2) {
126
0
        return 0;
127
0
    }
128
129
0
    for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) {
130
0
        if (*string1 == '\0') {
131
0
            return 0;
132
0
        }
133
0
    }
134
135
0
    return tolower(*string1) - tolower(*string2);
136
0
}
137
138
/* strlen of character literals resolved at compile time */
139
0
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
140
141
/* Internal constructor. */
142
9.17M
static cJSON *cJSON_New_Item(const VkAllocationCallbacks *pAllocator) {
143
9.17M
    cJSON *node = (cJSON *)loader_calloc(pAllocator, sizeof(cJSON), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
144
9.17M
    if (NULL != node) {
145
9.17M
        node->pAllocator = pAllocator;
146
9.17M
    }
147
9.17M
    return node;
148
9.17M
}
149
150
/* Delete a cJSON structure. */
151
1.30M
TEST_FUNCTION_EXPORT CJSON_PUBLIC(void) loader_cJSON_Delete(cJSON *item) {
152
1.30M
    cJSON *next = NULL;
153
10.4M
    while (item != NULL) {
154
9.17M
        next = item->next;
155
9.17M
        if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
156
1.23M
            loader_cJSON_Delete(item->child);
157
1.23M
        }
158
9.17M
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
159
6.98k
            loader_free(item->pAllocator, item->valuestring);
160
6.98k
            item->valuestring = NULL;
161
6.98k
        }
162
9.17M
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
163
1.68M
            loader_free(item->pAllocator, item->string);
164
1.68M
            item->string = NULL;
165
1.68M
        }
166
9.17M
        loader_free(item->pAllocator, item);
167
9.17M
        item = next;
168
9.17M
    }
169
1.30M
}
170
171
/* get the decimal point character of the current locale */
172
3.81M
static unsigned char get_decimal_point(void) {
173
#ifdef ENABLE_LOCALES
174
    struct lconv *lconv = localeconv();
175
    return (unsigned char)lconv->decimal_point[0];
176
#else
177
3.81M
    return '.';
178
3.81M
#endif
179
3.81M
}
180
181
typedef struct {
182
    const unsigned char *content;
183
    size_t length;
184
    size_t offset;
185
    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
186
    const VkAllocationCallbacks *pAllocator;
187
} parse_buffer;
188
189
/* check if the given size is left to read in a given parse buffer (starting with 1) */
190
55.0M
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
191
/* check if the buffer can be accessed at the given index (starting with 0) */
192
212M
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
193
50.5M
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
194
/* get a pointer to the buffer at the position */
195
154M
#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
196
197
/* Parse the input text to generate a number, and populate the result into item. */
198
2.22M
static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) {
199
2.22M
    double number = 0;
200
2.22M
    unsigned char *after_end = NULL;
201
2.22M
    unsigned char number_c_string[64];
202
2.22M
    unsigned char decimal_point = get_decimal_point();
203
2.22M
    size_t i = 0;
204
205
2.22M
    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
206
0
        return false;
207
0
    }
208
209
    /* copy the number into a temporary buffer and replace '.' with the decimal point
210
     * of the current locale (for strtod)
211
     * This also takes care of '\0' not necessarily being available for marking the end of the input */
212
5.97M
    for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) {
213
5.97M
        switch (buffer_at_offset(input_buffer)[i]) {
214
620k
            case '0':
215
773k
            case '1':
216
1.03M
            case '2':
217
1.36M
            case '3':
218
1.64M
            case '4':
219
1.69M
            case '5':
220
2.77M
            case '6':
221
2.94M
            case '7':
222
3.17M
            case '8':
223
3.62M
            case '9':
224
3.62M
            case '+':
225
3.63M
            case '-':
226
3.72M
            case 'e':
227
3.73M
            case 'E':
228
3.73M
                number_c_string[i] = buffer_at_offset(input_buffer)[i];
229
3.73M
                break;
230
231
8.69k
            case '.':
232
8.69k
                number_c_string[i] = decimal_point;
233
8.69k
                break;
234
235
2.22M
            default:
236
2.22M
                goto loop_end;
237
5.97M
        }
238
5.97M
    }
239
2.22M
loop_end:
240
2.22M
    number_c_string[i] = '\0';
241
242
2.22M
    number = strtod((const char *)number_c_string, (char **)&after_end);
243
2.22M
    if (number_c_string == after_end) {
244
38
        return false; /* parse_error */
245
38
    }
246
247
2.22M
    item->valuedouble = number;
248
249
    /* use saturation in case of overflow */
250
2.22M
    if (number >= INT_MAX) {
251
111k
        item->valueint = INT_MAX;
252
2.11M
    } else if (number <= (double)INT_MIN) {
253
1.03k
        item->valueint = INT_MIN;
254
2.11M
    } else {
255
2.11M
        item->valueint = (int)number;
256
2.11M
    }
257
258
2.22M
    item->type = cJSON_Number;
259
260
2.22M
    input_buffer->offset += (size_t)(after_end - number_c_string);
261
2.22M
    return true;
262
2.22M
}
263
264
typedef struct {
265
    unsigned char *buffer;
266
    size_t length;
267
    size_t offset;
268
    size_t depth; /* current nesting depth (for formatted printing) */
269
    cJSON_bool noalloc;
270
    cJSON_bool format; /* is this print a formatted print */
271
    const VkAllocationCallbacks *pAllocator;
272
} printbuffer;
273
274
/* realloc printbuffer if necessary to have at least "needed" bytes more */
275
26.9M
static unsigned char *ensure(printbuffer *const p, size_t needed, bool *out_of_memory) {
276
26.9M
    unsigned char *newbuffer = NULL;
277
26.9M
    size_t newsize = 0;
278
279
26.9M
    if ((p == NULL) || (p->buffer == NULL)) {
280
0
        return NULL;
281
0
    }
282
283
26.9M
    if ((p->length > 0) && (p->offset >= p->length)) {
284
        /* make sure that offset is valid */
285
0
        return NULL;
286
0
    }
287
288
26.9M
    if (needed > INT_MAX) {
289
        /* sizes bigger than INT_MAX are currently not supported */
290
0
        return NULL;
291
0
    }
292
293
26.9M
    needed += p->offset + 1;
294
26.9M
    if (needed <= p->length) {
295
26.9M
        return p->buffer + p->offset;
296
26.9M
    }
297
298
6.23k
    if (p->noalloc) {
299
0
        return NULL;
300
0
    }
301
302
    /* calculate new buffer size */
303
6.23k
    if (needed > (INT_MAX / 2)) {
304
        /* overflow of int, use INT_MAX if possible */
305
0
        if (needed <= INT_MAX) {
306
0
            newsize = INT_MAX;
307
0
        } else {
308
0
            return NULL;
309
0
        }
310
6.23k
    } else {
311
6.23k
        newsize = needed * 2;
312
6.23k
    }
313
314
6.23k
    newbuffer = (unsigned char *)loader_realloc(p->pAllocator, p->buffer, p->length, newsize, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
315
6.23k
    if (newbuffer == NULL) {
316
0
        *out_of_memory = true;
317
0
        loader_free(p->pAllocator, p->buffer);
318
0
        p->length = 0;
319
0
        p->buffer = NULL;
320
321
0
        return NULL;
322
0
    }
323
324
6.23k
    p->length = newsize;
325
6.23k
    p->buffer = newbuffer;
326
327
6.23k
    return newbuffer + p->offset;
328
6.23k
}
329
330
/* calculate the new length of the string in a printbuffer and update the offset */
331
9.60M
static void update_offset(printbuffer *const buffer) {
332
9.60M
    const unsigned char *buffer_pointer = NULL;
333
9.60M
    if ((buffer == NULL) || (buffer->buffer == NULL)) {
334
0
        return;
335
0
    }
336
9.60M
    buffer_pointer = buffer->buffer + buffer->offset;
337
338
9.60M
    buffer->offset += strlen((const char *)buffer_pointer);
339
9.60M
}
340
341
/* securely comparison of floating-point variables */
342
8.10k
static cJSON_bool compare_double(double a, double b) {
343
8.10k
    double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
344
8.10k
    return (fabs(a - b) <= maxVal * DBL_EPSILON);
345
8.10k
}
346
347
/* Render the number nicely from the given item into a string. */
348
1.58M
static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
349
1.58M
    unsigned char *output_pointer = NULL;
350
1.58M
    double d = item->valuedouble;
351
1.58M
    int length = 0;
352
1.58M
    size_t i = 0;
353
1.58M
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
354
1.58M
    unsigned char decimal_point = get_decimal_point();
355
1.58M
    double test = 0.0;
356
357
1.58M
    if (output_buffer == NULL) {
358
0
        return false;
359
0
    }
360
361
    /* This checks for NaN and Infinity */
362
1.58M
    if (isnan(d) || isinf(d)) {
363
555
        length = snprintf((char *)number_buffer, 26, "null");
364
1.58M
    } else if (d == (double)item->valueint) {
365
1.57M
        length = snprintf((char *)number_buffer, 26, "%d", item->valueint);
366
1.57M
    } else {
367
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
368
8.10k
        length = snprintf((char *)number_buffer, 26, "%1.15g", d);
369
370
        /* Check whether the original double can be recovered */
371
8.10k
        if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) {
372
            /* If not, print with 17 decimal places of precision */
373
6.05k
            length = snprintf((char *)number_buffer, 26, "%1.17g", d);
374
6.05k
        }
375
8.10k
    }
376
377
    /* snprintf failed or buffer overrun occurred */
378
1.58M
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
379
0
        return false;
380
0
    }
381
382
    /* reserve appropriate space in the output */
383
1.58M
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""), out_of_memory);
384
1.58M
    if (output_pointer == NULL) {
385
0
        return false;
386
0
    }
387
388
    /* copy the printed number to the output and replace locale
389
     * dependent decimal point with '.' */
390
3.36M
    for (i = 0; i < ((size_t)length); i++) {
391
1.77M
        if (number_buffer[i] == decimal_point) {
392
6.05k
            output_pointer[i] = '.';
393
6.05k
            continue;
394
6.05k
        }
395
396
1.77M
        output_pointer[i] = number_buffer[i];
397
1.77M
    }
398
1.58M
    output_pointer[i] = '\0';
399
400
1.58M
    output_buffer->offset += (size_t)length;
401
402
1.58M
    return true;
403
1.58M
}
404
405
/* parse 4 digit hexadecimal number */
406
476k
static unsigned parse_hex4(const unsigned char *const input) {
407
476k
    unsigned int h = 0;
408
476k
    size_t i = 0;
409
410
1.78M
    for (i = 0; i < 4; i++) {
411
        /* parse digit */
412
1.52M
        if ((input[i] >= '0') && (input[i] <= '9')) {
413
750k
            h += (unsigned int)input[i] - '0';
414
771k
        } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
415
270k
            h += (unsigned int)10 + input[i] - 'A';
416
500k
        } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
417
284k
            h += (unsigned int)10 + input[i] - 'a';
418
284k
        } else /* invalid */
419
216k
        {
420
216k
            return 0;
421
216k
        }
422
423
1.30M
        if (i < 3) {
424
            /* shift left to make place for the next nibble */
425
1.04M
            h = h << 4;
426
1.04M
        }
427
1.30M
    }
428
429
260k
    return h;
430
476k
}
431
432
/* converts a UTF-16 literal to UTF-8
433
 * A literal can be one or two sequences of the form \uXXXX */
434
static unsigned char utf16_literal_to_utf8(const unsigned char *const input_pointer, const unsigned char *const input_end,
435
474k
                                           unsigned char **output_pointer) {
436
474k
    long unsigned int codepoint = 0;
437
474k
    unsigned int first_code = 0;
438
474k
    const unsigned char *first_sequence = input_pointer;
439
474k
    unsigned char utf8_length = 0;
440
474k
    unsigned char utf8_position = 0;
441
474k
    unsigned char sequence_length = 0;
442
474k
    unsigned char first_byte_mark = 0;
443
444
474k
    if ((input_end - first_sequence) < 6) {
445
        /* input ends unexpectedly */
446
10
        goto fail;
447
10
    }
448
449
    /* get the first utf16 sequence */
450
474k
    first_code = parse_hex4(first_sequence + 2);
451
452
    /* check that the code is valid */
453
474k
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
454
16
        goto fail;
455
16
    }
456
457
    /* UTF16 surrogate pair */
458
473k
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
459
2.74k
        const unsigned char *second_sequence = first_sequence + 6;
460
2.74k
        unsigned int second_code = 0;
461
2.74k
        sequence_length = 12; /* \uXXXX\uXXXX */
462
463
2.74k
        if ((input_end - second_sequence) < 6) {
464
            /* input ends unexpectedly */
465
17
            goto fail;
466
17
        }
467
468
2.73k
        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
469
            /* missing second half of the surrogate pair */
470
28
            goto fail;
471
28
        }
472
473
        /* get the second utf16 sequence */
474
2.70k
        second_code = parse_hex4(second_sequence + 2);
475
        /* check that the code is valid */
476
2.70k
        if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
477
            /* invalid second half of the surrogate pair */
478
56
            goto fail;
479
56
        }
480
481
        /* calculate the unicode codepoint from the surrogate pair */
482
2.64k
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
483
471k
    } else {
484
471k
        sequence_length = 6; /* \uXXXX */
485
471k
        codepoint = first_code;
486
471k
    }
487
488
    /* encode as UTF-8
489
     * takes at maximum 4 bytes to encode:
490
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
491
473k
    if (codepoint < 0x80) {
492
        /* normal ascii, encoding 0xxxxxxx */
493
239k
        utf8_length = 1;
494
239k
    } else if (codepoint < 0x800) {
495
        /* two bytes, encoding 110xxxxx 10xxxxxx */
496
200k
        utf8_length = 2;
497
200k
        first_byte_mark = 0xC0; /* 11000000 */
498
200k
    } else if (codepoint < 0x10000) {
499
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
500
31.8k
        utf8_length = 3;
501
31.8k
        first_byte_mark = 0xE0; /* 11100000 */
502
31.8k
    } else if (codepoint <= 0x10FFFF) {
503
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
504
2.64k
        utf8_length = 4;
505
2.64k
        first_byte_mark = 0xF0; /* 11110000 */
506
2.64k
    } else {
507
        /* invalid unicode codepoint */
508
0
        goto fail;
509
0
    }
510
511
    /* encode as utf8 */
512
745k
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) {
513
        /* 10xxxxxx */
514
271k
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
515
271k
        codepoint >>= 6;
516
271k
    }
517
    /* encode first byte */
518
473k
    if (utf8_length > 1) {
519
234k
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
520
239k
    } else {
521
239k
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
522
239k
    }
523
524
473k
    *output_pointer += utf8_length;
525
526
473k
    return sequence_length;
527
528
127
fail:
529
127
    return 0;
530
473k
}
531
532
/* Parse the input text into an unescaped cinput, and populate item. */
533
1.69M
static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
534
1.69M
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
535
1.69M
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
536
1.69M
    unsigned char *output_pointer = NULL;
537
1.69M
    unsigned char *output = NULL;
538
539
    /* not a string */
540
1.69M
    if (buffer_at_offset(input_buffer)[0] != '\"') {
541
134
        goto fail;
542
134
    }
543
544
1.69M
    {
545
        /* calculate approximate size of the output (overestimate) */
546
1.69M
        size_t allocation_length = 0;
547
1.69M
        size_t skipped_bytes = 0;
548
41.6M
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) {
549
            /* is escape sequence */
550
39.9M
            if (input_end[0] == '\\') {
551
1.03M
                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) {
552
                    /* prevent buffer overflow when last input character is a backslash */
553
0
                    goto fail;
554
0
                }
555
1.03M
                skipped_bytes++;
556
1.03M
                input_end++;
557
1.03M
            }
558
39.9M
            input_end++;
559
39.9M
        }
560
1.69M
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) {
561
85
            goto fail; /* string ended unexpectedly */
562
85
        }
563
564
        /* This is at most how much we need for the output */
565
1.69M
        allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
566
1.69M
        output = (unsigned char *)loader_calloc(input_buffer->pAllocator, allocation_length + sizeof(""),
567
1.69M
                                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
568
1.69M
        if (output == NULL) {
569
0
            *out_of_memory = true;
570
0
            goto fail; /* allocation failure */
571
0
        }
572
1.69M
    }
573
574
1.69M
    output_pointer = output;
575
    /* loop through the string literal */
576
31.6M
    while (input_pointer < input_end) {
577
29.9M
        if (*input_pointer != '\\') {
578
29.4M
            *output_pointer++ = *input_pointer++;
579
29.4M
        }
580
        /* escape sequence */
581
564k
        else {
582
564k
            unsigned char sequence_length = 2;
583
564k
            if ((input_end - input_pointer) < 1) {
584
0
                goto fail;
585
0
            }
586
587
564k
            switch (input_pointer[1]) {
588
51.4k
                case 'b':
589
51.4k
                    *output_pointer++ = '\b';
590
51.4k
                    break;
591
940
                case 'f':
592
940
                    *output_pointer++ = '\f';
593
940
                    break;
594
7.74k
                case 'n':
595
7.74k
                    *output_pointer++ = '\n';
596
7.74k
                    break;
597
2.79k
                case 'r':
598
2.79k
                    *output_pointer++ = '\r';
599
2.79k
                    break;
600
20.6k
                case 't':
601
20.6k
                    *output_pointer++ = '\t';
602
20.6k
                    break;
603
3.85k
                case '\"':
604
4.62k
                case '\\':
605
7.15k
                case '/':
606
7.15k
                    *output_pointer++ = input_pointer[1];
607
7.15k
                    break;
608
609
                /* UTF-16 literal */
610
474k
                case 'u':
611
474k
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
612
474k
                    if (sequence_length == 0) {
613
                        /* failed to convert UTF16-literal to UTF-8 */
614
127
                        goto fail;
615
127
                    }
616
473k
                    break;
617
618
473k
                default:
619
27
                    goto fail;
620
564k
            }
621
564k
            input_pointer += sequence_length;
622
564k
        }
623
29.9M
    }
624
625
    /* zero terminate the output */
626
1.69M
    *output_pointer = '\0';
627
628
1.69M
    item->type = cJSON_String;
629
1.69M
    item->valuestring = (char *)output;
630
631
1.69M
    input_buffer->offset = (size_t)(input_end - input_buffer->content);
632
1.69M
    input_buffer->offset++;
633
634
1.69M
    return true;
635
636
373
fail:
637
373
    if (output != NULL) {
638
154
        loader_free(input_buffer->pAllocator, output);
639
154
        output = NULL;
640
154
    }
641
642
373
    if (input_pointer != NULL) {
643
373
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
644
373
    }
645
646
373
    return false;
647
1.69M
}
648
649
/* Render the cstring provided to an escaped version that can be printed. */
650
1.57M
static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer, bool *out_of_memory) {
651
1.57M
    const unsigned char *input_pointer = NULL;
652
1.57M
    unsigned char *output = NULL;
653
1.57M
    unsigned char *output_pointer = NULL;
654
1.57M
    size_t output_length = 0;
655
    /* numbers of additional characters needed for escaping */
656
1.57M
    size_t escape_characters = 0;
657
658
1.57M
    if (output_buffer == NULL) {
659
0
        return false;
660
0
    }
661
662
    /* empty string */
663
1.57M
    if (input == NULL) {
664
0
        output = ensure(output_buffer, sizeof(""), out_of_memory);
665
0
        if (output == NULL) {
666
0
            return false;
667
0
        }
668
669
0
        return true;
670
0
    }
671
672
    /* set "flag" to 1 if something needs to be escaped */
673
11.9M
    for (input_pointer = input; *input_pointer; input_pointer++) {
674
10.4M
        switch (*input_pointer) {
675
275
            case '\"':
676
713
            case '\\':
677
1.68k
            case '\b':
678
4.79k
            case '\f':
679
5.43k
            case '\n':
680
6.54k
            case '\r':
681
7.72k
            case '\t':
682
                /* one character escape sequence */
683
7.72k
                escape_characters++;
684
7.72k
                break;
685
10.3M
            default:
686
10.3M
                if (*input_pointer < 32) {
687
                    /* UTF-16 escape sequence uXXXX */
688
5.88M
                    escape_characters += 5;
689
5.88M
                }
690
10.3M
                break;
691
10.4M
        }
692
10.4M
    }
693
1.57M
    output_length = (size_t)(input_pointer - input) + escape_characters;
694
695
1.57M
    output = ensure(output_buffer, output_length + sizeof(""), out_of_memory);
696
1.57M
    if (output == NULL) {
697
0
        return false;
698
0
    }
699
700
    /* no characters have to be escaped */
701
1.57M
    if (escape_characters == 0) {
702
1.55M
        memcpy(output, input, output_length);
703
1.55M
        output[output_length] = '\0';
704
705
1.55M
        return true;
706
1.55M
    }
707
708
18.5k
    output_pointer = output;
709
    /* copy the string */
710
9.45M
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) {
711
9.43M
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) {
712
            /* normal character, copy */
713
3.54M
            *output_pointer = *input_pointer;
714
5.88M
        } else {
715
            // Loader specific modification - don't add a backslash because that will 'double up' any existing back slashes.
716
            // This change was added right after vulkan's public release, so while it may not be a problem, there are plenty
717
            // of API calls made which might not work if the paths have "\\"" in them
718
            /* character needs to be escaped */
719
            //*output_pointer++ = '\\';
720
5.88M
            switch (*input_pointer) {
721
438
                case '\\':
722
438
                    *output_pointer = '\\';
723
438
                    break;
724
275
                case '\"':
725
275
                    *output_pointer = '\"';
726
275
                    break;
727
971
                case '\b':
728
971
                    *output_pointer = '\b';
729
971
                    break;
730
3.10k
                case '\f':
731
3.10k
                    *output_pointer = '\f';
732
3.10k
                    break;
733
638
                case '\n':
734
638
                    *output_pointer = '\n';
735
638
                    break;
736
1.11k
                case '\r':
737
1.11k
                    *output_pointer = '\r';
738
1.11k
                    break;
739
1.17k
                case '\t':
740
1.17k
                    *output_pointer = '\t';
741
1.17k
                    break;
742
5.88M
                default:
743
                    /* escape and print as unicode codepoint */
744
5.88M
                    snprintf((char *)output_pointer, output_length - (size_t)(output_pointer - output), "u%04x", *input_pointer);
745
5.88M
                    output_pointer += 4;
746
5.88M
                    break;
747
5.88M
            }
748
5.88M
        }
749
9.43M
    }
750
    // The loader-specific escaping above emits one byte where the standard form emits two, so the written
751
    // length is shorter than output_length. Terminate at the actual end, otherwise the bytes between it and
752
    // output_length (uninitialized when the caller buffer is not zeroed) get read back as part of the string.
753
18.5k
    *output_pointer = '\0';
754
755
18.5k
    return true;
756
18.5k
}
757
758
/* Invoke print_string_ptr (which is useful) on an item. */
759
5.76k
static cJSON_bool print_string(const cJSON *const item, printbuffer *const p, bool *out_of_memory) {
760
5.76k
    return print_string_ptr((unsigned char *)item->valuestring, p, out_of_memory);
761
5.76k
}
762
763
/* Predeclare these prototypes. */
764
static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory);
765
static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory);
766
static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory);
767
static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory);
768
static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory);
769
static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory);
770
771
/* Utility to jump whitespace and cr/lf */
772
28.5M
static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) {
773
28.5M
    if ((buffer == NULL) || (buffer->content == NULL)) {
774
0
        return NULL;
775
0
    }
776
777
28.5M
    if (cannot_access_at_index(buffer, 0)) {
778
0
        return buffer;
779
0
    }
780
781
34.9M
    while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
782
6.36M
        buffer->offset++;
783
6.36M
    }
784
785
28.5M
    if (buffer->offset == buffer->length) {
786
696
        buffer->offset--;
787
696
    }
788
789
28.5M
    return buffer;
790
28.5M
}
791
792
/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
793
2.94k
static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) {
794
2.94k
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) {
795
0
        return NULL;
796
0
    }
797
798
2.94k
    if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) {
799
22
        buffer->offset += 3;
800
22
    }
801
802
2.94k
    return buffer;
803
2.94k
}
804
805
CJSON_PUBLIC(cJSON *)
806
loader_cJSON_ParseWithOpts(const VkAllocationCallbacks *pAllocator, const char *value, const char **return_parse_end,
807
0
                           cJSON_bool require_null_terminated, bool *out_of_memory) {
808
0
    size_t buffer_length;
809
810
0
    if (NULL == value) {
811
0
        return NULL;
812
0
    }
813
814
    /* Adding null character size due to require_null_terminated. */
815
0
    buffer_length = strlen(value) + sizeof("");
816
817
0
    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, return_parse_end, require_null_terminated,
818
0
                                            out_of_memory);
819
0
}
820
821
/* Parse an object - create a new root, and populate. */
822
CJSON_PUBLIC(cJSON *)
823
loader_cJSON_ParseWithLengthOpts(const VkAllocationCallbacks *pAllocator, const char *value, size_t buffer_length,
824
2.94k
                                 const char **return_parse_end, cJSON_bool require_null_terminated, bool *out_of_memory) {
825
2.94k
    parse_buffer buffer = {0, 0, 0, 0, 0};
826
2.94k
    cJSON *item = NULL;
827
828
    /* reset error position */
829
    // global_error.json = NULL;
830
    // global_error.position = 0;
831
832
2.94k
    if (value == NULL || 0 == buffer_length) {
833
0
        goto fail;
834
0
    }
835
836
2.94k
    buffer.content = (const unsigned char *)value;
837
2.94k
    buffer.length = buffer_length;
838
2.94k
    buffer.offset = 0;
839
2.94k
    buffer.pAllocator = pAllocator;
840
841
2.94k
    item = cJSON_New_Item(pAllocator);
842
2.94k
    if (item == NULL) /* memory fail */
843
0
    {
844
0
        *out_of_memory = true;
845
0
        goto fail;
846
0
    }
847
848
2.94k
    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)), out_of_memory)) {
849
        /* parse failure. ep is set. */
850
1.07k
        goto fail;
851
1.07k
    }
852
853
    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
854
1.87k
    if (require_null_terminated) {
855
0
        buffer_skip_whitespace(&buffer);
856
0
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') {
857
0
            goto fail;
858
0
        }
859
0
    }
860
1.87k
    if (return_parse_end) {
861
0
        *return_parse_end = (const char *)buffer_at_offset(&buffer);
862
0
    }
863
864
1.87k
    return item;
865
866
1.07k
fail:
867
1.07k
    if (item != NULL) {
868
1.07k
        loader_cJSON_Delete(item);
869
1.07k
    }
870
871
1.07k
    if (value != NULL) {
872
1.07k
        error local_error;
873
1.07k
        local_error.json = (const unsigned char *)value;
874
1.07k
        local_error.position = 0;
875
876
1.07k
        if (buffer.offset < buffer.length) {
877
961
            local_error.position = buffer.offset;
878
961
        } else if (buffer.length > 0) {
879
115
            local_error.position = buffer.length - 1;
880
115
        }
881
882
1.07k
        if (return_parse_end != NULL) {
883
0
            *return_parse_end = (const char *)local_error.json + local_error.position;
884
0
        }
885
886
        // global_error = local_error;
887
1.07k
    }
888
889
1.07k
    return NULL;
890
1.87k
}
891
892
/* Default options for loader_cJSON_Parse */
893
0
CJSON_PUBLIC(cJSON *) loader_cJSON_Parse(const VkAllocationCallbacks *pAllocator, const char *value, bool *out_of_memory) {
894
0
    return loader_cJSON_ParseWithOpts(pAllocator, value, 0, 0, out_of_memory);
895
0
}
896
897
CJSON_PUBLIC(cJSON *)
898
loader_cJSON_ParseWithLength(const VkAllocationCallbacks *pAllocator, const char *value, size_t buffer_length,
899
2.94k
                             bool *out_of_memory) {
900
2.94k
    return loader_cJSON_ParseWithLengthOpts(pAllocator, value, buffer_length, 0, 0, out_of_memory);
901
2.94k
}
902
903
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
904
905
1.87k
static unsigned char *print(const cJSON *const item, cJSON_bool format, bool *out_of_memory) {
906
1.87k
    static const size_t default_buffer_size = 256;
907
1.87k
    printbuffer buffer[1];
908
1.87k
    unsigned char *printed = NULL;
909
910
1.87k
    memset(buffer, 0, sizeof(buffer));
911
912
    /* create buffer */
913
1.87k
    buffer->buffer = (unsigned char *)loader_calloc(item->pAllocator, default_buffer_size, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
914
1.87k
    buffer->length = default_buffer_size;
915
1.87k
    buffer->format = format;
916
1.87k
    buffer->pAllocator = item->pAllocator;
917
1.87k
    if (buffer->buffer == NULL) {
918
0
        *out_of_memory = true;
919
0
        goto fail;
920
0
    }
921
922
    /* print the value */
923
1.87k
    if (!print_value(item, buffer, out_of_memory)) {
924
0
        goto fail;
925
0
    }
926
1.87k
    update_offset(buffer);
927
928
1.87k
    printed = (unsigned char *)loader_realloc(item->pAllocator, buffer->buffer, buffer->length, buffer->offset + 1,
929
1.87k
                                              VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
930
1.87k
    if (printed == NULL) {
931
0
        *out_of_memory = true;
932
0
        goto fail;
933
0
    }
934
1.87k
    buffer->buffer = NULL;
935
936
1.87k
    return printed;
937
938
0
fail:
939
0
    if (buffer->buffer != NULL) {
940
0
        loader_free(item->pAllocator, buffer->buffer);
941
0
        buffer->buffer = NULL;
942
0
    }
943
944
0
    if (printed != NULL) {
945
0
        loader_free(item->pAllocator, printed);
946
0
        printed = NULL;
947
0
    }
948
949
0
    return NULL;
950
1.87k
}
951
952
/* Render a cJSON item/entity/structure to text. */
953
1.87k
TEST_FUNCTION_EXPORT CJSON_PUBLIC(char *) loader_cJSON_Print(const cJSON *item, bool *out_of_memory) {
954
1.87k
    return (char *)print(item, true, out_of_memory);
955
1.87k
}
956
957
0
CJSON_PUBLIC(char *) loader_cJSON_PrintUnformatted(const cJSON *item, bool *out_of_memory) {
958
0
    return (char *)print(item, false, out_of_memory);
959
0
}
960
961
CJSON_PUBLIC(char *)
962
0
loader_cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt, bool *out_of_memory) {
963
0
    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
964
965
0
    if (prebuffer < 0) {
966
0
        return NULL;
967
0
    }
968
969
0
    p.buffer = (unsigned char *)loader_alloc(item->pAllocator, (size_t)prebuffer, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
970
0
    if (!p.buffer) {
971
0
        return NULL;
972
0
    }
973
974
0
    p.length = (size_t)prebuffer;
975
0
    p.offset = 0;
976
0
    p.noalloc = false;
977
0
    p.format = fmt;
978
0
    p.pAllocator = item->pAllocator;
979
980
0
    if (!print_value(item, &p, out_of_memory)) {
981
0
        loader_free(item->pAllocator, p.buffer);
982
0
        p.buffer = NULL;
983
0
        return NULL;
984
0
    }
985
986
0
    return (char *)p.buffer;
987
0
}
988
989
TEST_FUNCTION_EXPORT CJSON_PUBLIC(cJSON_bool)
990
0
    loader_cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) {
991
0
    printbuffer p = {0, 0, 0, 0, 0, 0, 0};
992
993
0
    if ((length < 0) || (buffer == NULL)) {
994
0
        return false;
995
0
    }
996
997
0
    p.buffer = (unsigned char *)buffer;
998
0
    p.length = (size_t)length;
999
0
    p.offset = 0;
1000
0
    p.noalloc = true;
1001
0
    p.format = format;
1002
0
    p.pAllocator = item->pAllocator;
1003
0
    bool out_of_memory = false;
1004
0
    return print_value(item, &p, &out_of_memory);
1005
0
}
1006
1007
/* Parser core - when encountering text, process appropriately. */
1008
9.17M
static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1009
9.17M
    if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
1010
0
        return false; /* no input */
1011
0
    }
1012
1013
    /* parse the different types of values */
1014
    /* null */
1015
9.17M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) {
1016
3.06k
        item->type = cJSON_NULL;
1017
3.06k
        input_buffer->offset += 4;
1018
3.06k
        return true;
1019
3.06k
    }
1020
    /* false */
1021
9.17M
    if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) {
1022
2.87k
        item->type = cJSON_False;
1023
2.87k
        input_buffer->offset += 5;
1024
2.87k
        return true;
1025
2.87k
    }
1026
    /* true */
1027
9.16M
    if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) {
1028
9.41k
        item->type = cJSON_True;
1029
9.41k
        item->valueint = 1;
1030
9.41k
        input_buffer->offset += 4;
1031
9.41k
        return true;
1032
9.41k
    }
1033
    /* string */
1034
9.15M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) {
1035
7.19k
        return parse_string(item, input_buffer, out_of_memory);
1036
7.19k
    }
1037
    /* number */
1038
9.15M
    if (can_access_at_index(input_buffer, 0) &&
1039
9.15M
        ((buffer_at_offset(input_buffer)[0] == '-') ||
1040
9.14M
         ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) {
1041
2.22M
        return parse_number(item, input_buffer);
1042
2.22M
    }
1043
    /* array */
1044
6.92M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) {
1045
354k
        return parse_array(item, input_buffer, out_of_memory);
1046
354k
    }
1047
    /* object */
1048
6.56M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) {
1049
6.56M
        return parse_object(item, input_buffer, out_of_memory);
1050
6.56M
    }
1051
1052
317
    return false;
1053
6.56M
}
1054
1055
/* Render a value to text. */
1056
8.03M
static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1057
8.03M
    unsigned char *output = NULL;
1058
1059
8.03M
    if ((item == NULL) || (output_buffer == NULL)) {
1060
0
        return false;
1061
0
    }
1062
1063
8.03M
    switch ((item->type) & 0xFF) {
1064
2.73k
        case cJSON_NULL:
1065
2.73k
            output = ensure(output_buffer, 5, out_of_memory);
1066
2.73k
            if (output == NULL) {
1067
0
                return false;
1068
0
            }
1069
2.73k
            strcpy((char *)output, "null");
1070
2.73k
            return true;
1071
1072
2.09k
        case cJSON_False:
1073
2.09k
            output = ensure(output_buffer, 6, out_of_memory);
1074
2.09k
            if (output == NULL) {
1075
0
                return false;
1076
0
            }
1077
2.09k
            strcpy((char *)output, "false");
1078
2.09k
            return true;
1079
1080
8.13k
        case cJSON_True:
1081
8.13k
            output = ensure(output_buffer, 5, out_of_memory);
1082
8.13k
            if (output == NULL) {
1083
0
                return false;
1084
0
            }
1085
8.13k
            strcpy((char *)output, "true");
1086
8.13k
            return true;
1087
1088
1.58M
        case cJSON_Number:
1089
1.58M
            return print_number(item, output_buffer, out_of_memory);
1090
1091
0
        case cJSON_Raw: {
1092
0
            size_t raw_length = 0;
1093
0
            if (item->valuestring == NULL) {
1094
0
                return false;
1095
0
            }
1096
1097
0
            raw_length = strlen(item->valuestring) + sizeof("");
1098
0
            output = ensure(output_buffer, raw_length, out_of_memory);
1099
0
            if (output == NULL) {
1100
0
                return false;
1101
0
            }
1102
0
            memcpy(output, item->valuestring, raw_length);
1103
0
            return true;
1104
0
        }
1105
1106
5.76k
        case cJSON_String:
1107
5.76k
            return print_string(item, output_buffer, out_of_memory);
1108
1109
291k
        case cJSON_Array:
1110
291k
            return print_array(item, output_buffer, out_of_memory);
1111
1112
6.13M
        case cJSON_Object:
1113
6.13M
            return print_object(item, output_buffer, out_of_memory);
1114
1115
0
        default:
1116
0
            return false;
1117
8.03M
    }
1118
8.03M
}
1119
1120
/* Build an array from input text. */
1121
354k
static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1122
354k
    cJSON *head = NULL; /* head of the linked list */
1123
354k
    cJSON *current_item = NULL;
1124
1125
354k
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1126
8
        return false; /* to deeply nested */
1127
8
    }
1128
354k
    input_buffer->depth++;
1129
1130
354k
    if (buffer_at_offset(input_buffer)[0] != '[') {
1131
        /* not an array */
1132
0
        goto fail;
1133
0
    }
1134
1135
354k
    input_buffer->offset++;
1136
354k
    buffer_skip_whitespace(input_buffer);
1137
354k
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) {
1138
        /* empty array */
1139
15.6k
        goto success;
1140
15.6k
    }
1141
1142
    /* check if we skipped to the end of the buffer */
1143
338k
    if (cannot_access_at_index(input_buffer, 0)) {
1144
0
        input_buffer->offset--;
1145
0
        goto fail;
1146
0
    }
1147
1148
    /* step back to character in front of the first element */
1149
338k
    input_buffer->offset--;
1150
    /* loop through the comma separated array elements */
1151
7.48M
    do {
1152
        /* allocate next item */
1153
7.48M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1154
7.48M
        if (new_item == NULL) {
1155
0
            *out_of_memory = true;
1156
0
            goto fail; /* allocation failure */
1157
0
        }
1158
1159
        /* attach next item to list */
1160
7.48M
        if (head == NULL) {
1161
            /* start the linked list */
1162
338k
            current_item = head = new_item;
1163
7.14M
        } else {
1164
            /* add to the end and advance */
1165
7.14M
            current_item->next = new_item;
1166
7.14M
            new_item->prev = current_item;
1167
7.14M
            current_item = new_item;
1168
7.14M
        }
1169
1170
        /* parse next value */
1171
7.48M
        input_buffer->offset++;
1172
7.48M
        buffer_skip_whitespace(input_buffer);
1173
7.48M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1174
60.4k
            goto fail; /* failed to parse value */
1175
60.4k
        }
1176
7.42M
        buffer_skip_whitespace(input_buffer);
1177
7.42M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1178
1179
278k
    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') {
1180
271
        goto fail; /* expected end of array */
1181
271
    }
1182
1183
293k
success:
1184
293k
    input_buffer->depth--;
1185
1186
293k
    if (head != NULL) {
1187
278k
        head->prev = current_item;
1188
278k
    }
1189
1190
293k
    item->type = cJSON_Array;
1191
293k
    item->child = head;
1192
1193
293k
    input_buffer->offset++;
1194
1195
293k
    return true;
1196
1197
60.7k
fail:
1198
60.7k
    if (head != NULL) {
1199
60.7k
        loader_cJSON_Delete(head);
1200
60.7k
    }
1201
1202
60.7k
    return false;
1203
278k
}
1204
1205
/* Render an array to text */
1206
291k
static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1207
291k
    unsigned char *output_pointer = NULL;
1208
291k
    size_t length = 0;
1209
291k
    cJSON *current_element = item->child;
1210
1211
291k
    if (output_buffer == NULL) {
1212
0
        return false;
1213
0
    }
1214
1215
    /* Compose the output array. */
1216
    /* opening square bracket */
1217
291k
    output_pointer = ensure(output_buffer, 1, out_of_memory);
1218
291k
    if (output_pointer == NULL) {
1219
0
        return false;
1220
0
    }
1221
1222
291k
    *output_pointer = '[';
1223
291k
    output_buffer->offset++;
1224
291k
    output_buffer->depth++;
1225
1226
6.74M
    while (current_element != NULL) {
1227
6.45M
        if (!print_value(current_element, output_buffer, out_of_memory)) {
1228
0
            return false;
1229
0
        }
1230
6.45M
        update_offset(output_buffer);
1231
6.45M
        if (current_element->next) {
1232
6.18M
            length = (size_t)(output_buffer->format ? 2 : 1);
1233
6.18M
            output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1234
6.18M
            if (output_pointer == NULL) {
1235
0
                return false;
1236
0
            }
1237
6.18M
            *output_pointer++ = ',';
1238
6.18M
            if (output_buffer->format) {
1239
6.18M
                *output_pointer++ = ' ';
1240
6.18M
            }
1241
6.18M
            *output_pointer = '\0';
1242
6.18M
            output_buffer->offset += length;
1243
6.18M
        }
1244
6.45M
        current_element = current_element->next;
1245
6.45M
    }
1246
1247
291k
    output_pointer = ensure(output_buffer, 2, out_of_memory);
1248
291k
    if (output_pointer == NULL) {
1249
0
        return false;
1250
0
    }
1251
291k
    *output_pointer++ = ']';
1252
291k
    *output_pointer = '\0';
1253
291k
    output_buffer->depth--;
1254
1255
291k
    return true;
1256
291k
}
1257
1258
/* Build an object from the text. */
1259
6.56M
static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer, bool *out_of_memory) {
1260
6.56M
    cJSON *head = NULL; /* linked list head */
1261
6.56M
    cJSON *current_item = NULL;
1262
1263
6.56M
    if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
1264
2
        return false; /* to deeply nested */
1265
2
    }
1266
6.56M
    input_buffer->depth++;
1267
1268
6.56M
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) {
1269
0
        goto fail; /* not an object */
1270
0
    }
1271
1272
6.56M
    input_buffer->offset++;
1273
6.56M
    buffer_skip_whitespace(input_buffer);
1274
6.56M
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) {
1275
5.60M
        goto success; /* empty object */
1276
5.60M
    }
1277
1278
    /* check if we skipped to the end of the buffer */
1279
966k
    if (cannot_access_at_index(input_buffer, 0)) {
1280
0
        input_buffer->offset--;
1281
0
        goto fail;
1282
0
    }
1283
1284
    /* step back to character in front of the first element */
1285
966k
    input_buffer->offset--;
1286
    /* loop through the comma separated array elements */
1287
1.68M
    do {
1288
        /* allocate next item */
1289
1.68M
        cJSON *new_item = cJSON_New_Item(input_buffer->pAllocator);
1290
1.68M
        if (new_item == NULL) {
1291
0
            *out_of_memory = true;
1292
0
            goto fail; /* allocation failure */
1293
0
        }
1294
1295
        /* attach next item to list */
1296
1.68M
        if (head == NULL) {
1297
            /* start the linked list */
1298
966k
            current_item = head = new_item;
1299
966k
        } else {
1300
            /* add to the end and advance */
1301
716k
            current_item->next = new_item;
1302
716k
            new_item->prev = current_item;
1303
716k
            current_item = new_item;
1304
716k
        }
1305
1306
1.68M
        if (cannot_access_at_index(input_buffer, 1)) {
1307
0
            goto fail; /* nothing comes after the comma */
1308
0
        }
1309
1310
        /* parse the name of the child */
1311
1.68M
        input_buffer->offset++;
1312
1.68M
        buffer_skip_whitespace(input_buffer);
1313
1.68M
        if (!parse_string(current_item, input_buffer, out_of_memory)) {
1314
167
            goto fail; /* failed to parse name */
1315
167
        }
1316
1.68M
        buffer_skip_whitespace(input_buffer);
1317
1318
        /* swap valuestring and string, because we parsed the name */
1319
1.68M
        current_item->string = current_item->valuestring;
1320
1.68M
        current_item->valuestring = NULL;
1321
1322
1.68M
        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) {
1323
32
            goto fail; /* invalid object */
1324
32
        }
1325
1326
        /* parse the value */
1327
1.68M
        input_buffer->offset++;
1328
1.68M
        buffer_skip_whitespace(input_buffer);
1329
1.68M
        if (!parse_value(current_item, input_buffer, out_of_memory)) {
1330
8.58k
            goto fail; /* failed to parse value */
1331
8.58k
        }
1332
1.67M
        buffer_skip_whitespace(input_buffer);
1333
1.67M
    } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1334
1335
957k
    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) {
1336
35
        goto fail; /* expected end of object */
1337
35
    }
1338
1339
6.56M
success:
1340
6.56M
    input_buffer->depth--;
1341
1342
6.56M
    if (head != NULL) {
1343
957k
        head->prev = current_item;
1344
957k
    }
1345
1346
6.56M
    item->type = cJSON_Object;
1347
6.56M
    item->child = head;
1348
1349
6.56M
    input_buffer->offset++;
1350
6.56M
    return true;
1351
1352
8.81k
fail:
1353
8.81k
    if (head != NULL) {
1354
8.81k
        loader_cJSON_Delete(head);
1355
8.81k
    }
1356
1357
8.81k
    return false;
1358
957k
}
1359
1360
/* Render an object to text. */
1361
6.13M
static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer, bool *out_of_memory) {
1362
6.13M
    unsigned char *output_pointer = NULL;
1363
6.13M
    size_t length = 0;
1364
6.13M
    cJSON *current_item = item->child;
1365
1366
6.13M
    if (output_buffer == NULL) {
1367
0
        return false;
1368
0
    }
1369
1370
    /* Compose the output: */
1371
6.13M
    length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
1372
6.13M
    output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1373
6.13M
    if (output_pointer == NULL) {
1374
0
        return false;
1375
0
    }
1376
1377
6.13M
    *output_pointer++ = '{';
1378
6.13M
    output_buffer->depth++;
1379
6.13M
    if (output_buffer->format) {
1380
6.13M
        *output_pointer++ = '\n';
1381
6.13M
    }
1382
6.13M
    output_buffer->offset += length;
1383
1384
7.70M
    while (current_item) {
1385
1.57M
        if (output_buffer->format) {
1386
1.57M
            size_t i;
1387
1.57M
            output_pointer = ensure(output_buffer, output_buffer->depth, out_of_memory);
1388
1.57M
            if (output_pointer == NULL) {
1389
0
                return false;
1390
0
            }
1391
759M
            for (i = 0; i < output_buffer->depth; i++) {
1392
758M
                *output_pointer++ = '\t';
1393
758M
            }
1394
1.57M
            output_buffer->offset += output_buffer->depth;
1395
1.57M
        }
1396
1397
        /* print key */
1398
1.57M
        if (!print_string_ptr((unsigned char *)current_item->string, output_buffer, out_of_memory)) {
1399
0
            return false;
1400
0
        }
1401
1.57M
        update_offset(output_buffer);
1402
1403
1.57M
        length = (size_t)(output_buffer->format ? 2 : 1);
1404
1.57M
        output_pointer = ensure(output_buffer, length, out_of_memory);
1405
1.57M
        if (output_pointer == NULL) {
1406
0
            return false;
1407
0
        }
1408
1.57M
        *output_pointer++ = ':';
1409
1.57M
        if (output_buffer->format) {
1410
1.57M
            *output_pointer++ = '\t';
1411
1.57M
        }
1412
1.57M
        output_buffer->offset += length;
1413
1414
        /* print value */
1415
1.57M
        if (!print_value(current_item, output_buffer, out_of_memory)) {
1416
0
            return false;
1417
0
        }
1418
1.57M
        update_offset(output_buffer);
1419
1420
        /* print comma if not last */
1421
1.57M
        length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1422
1.57M
        output_pointer = ensure(output_buffer, length + 1, out_of_memory);
1423
1.57M
        if (output_pointer == NULL) {
1424
0
            return false;
1425
0
        }
1426
1.57M
        if (current_item->next) {
1427
682k
            *output_pointer++ = ',';
1428
682k
        }
1429
1430
1.57M
        if (output_buffer->format) {
1431
1.57M
            *output_pointer++ = '\n';
1432
1.57M
        }
1433
1.57M
        *output_pointer = '\0';
1434
1.57M
        output_buffer->offset += length;
1435
1436
1.57M
        current_item = current_item->next;
1437
1.57M
    }
1438
1439
6.13M
    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2, out_of_memory);
1440
6.13M
    if (output_pointer == NULL) {
1441
0
        return false;
1442
0
    }
1443
6.13M
    if (output_buffer->format) {
1444
6.13M
        size_t i;
1445
4.81G
        for (i = 0; i < (output_buffer->depth - 1); i++) {
1446
4.80G
            *output_pointer++ = '\t';
1447
4.80G
        }
1448
6.13M
    }
1449
6.13M
    *output_pointer++ = '}';
1450
6.13M
    *output_pointer = '\0';
1451
6.13M
    output_buffer->depth--;
1452
1453
6.13M
    return true;
1454
6.13M
}
1455
1456
/* Get Array size/item / object item. */
1457
0
CJSON_PUBLIC(int) loader_cJSON_GetArraySize(const cJSON *array) {
1458
0
    cJSON *child = NULL;
1459
0
    size_t size = 0;
1460
1461
0
    if (array == NULL) {
1462
0
        return 0;
1463
0
    }
1464
1465
0
    child = array->child;
1466
1467
0
    while (child != NULL) {
1468
0
        size++;
1469
0
        child = child->next;
1470
0
    }
1471
1472
    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1473
1474
0
    return (int)size;
1475
0
}
1476
1477
0
static cJSON *get_array_item(const cJSON *array, size_t index) {
1478
0
    cJSON *current_child = NULL;
1479
1480
0
    if (array == NULL) {
1481
0
        return NULL;
1482
0
    }
1483
1484
0
    current_child = array->child;
1485
0
    while ((current_child != NULL) && (index > 0)) {
1486
0
        index--;
1487
0
        current_child = current_child->next;
1488
0
    }
1489
1490
0
    return current_child;
1491
0
}
1492
1493
0
CJSON_PUBLIC(cJSON *) loader_cJSON_GetArrayItem(const cJSON *array, int index) {
1494
0
    if (index < 0) {
1495
0
        return NULL;
1496
0
    }
1497
1498
0
    return get_array_item(array, (size_t)index);
1499
0
}
1500
1501
0
static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) {
1502
0
    cJSON *current_element = NULL;
1503
1504
0
    if ((object == NULL) || (name == NULL)) {
1505
0
        return NULL;
1506
0
    }
1507
1508
0
    current_element = object->child;
1509
0
    if (case_sensitive) {
1510
0
        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) {
1511
0
            current_element = current_element->next;
1512
0
        }
1513
0
    } else {
1514
0
        while ((current_element != NULL) &&
1515
0
               (case_insensitive_strcmp((const unsigned char *)name, (const unsigned char *)(current_element->string)) != 0)) {
1516
0
            current_element = current_element->next;
1517
0
        }
1518
0
    }
1519
1520
0
    if ((current_element == NULL) || (current_element->string == NULL)) {
1521
0
        return NULL;
1522
0
    }
1523
1524
0
    return current_element;
1525
0
}
1526
1527
0
CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItem(const cJSON *const object, const char *const string) {
1528
0
    return get_object_item(object, string, false);
1529
0
}
1530
1531
0
CJSON_PUBLIC(cJSON *) loader_cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string) {
1532
0
    return get_object_item(object, string, true);
1533
0
}
1534
1535
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_HasObjectItem(const cJSON *object, const char *string) {
1536
0
    return loader_cJSON_GetObjectItem(object, string) ? 1 : 0;
1537
0
}
1538
1539
0
static void skip_oneline_comment(char **input) {
1540
0
    *input += static_strlen("//");
1541
1542
0
    for (; (*input)[0] != '\0'; ++(*input)) {
1543
0
        if ((*input)[0] == '\n') {
1544
0
            *input += static_strlen("\n");
1545
0
            return;
1546
0
        }
1547
0
    }
1548
0
}
1549
1550
0
static void skip_multiline_comment(char **input) {
1551
0
    *input += static_strlen("/*");
1552
1553
0
    for (; (*input)[0] != '\0'; ++(*input)) {
1554
0
        if (((*input)[0] == '*') && ((*input)[1] == '/')) {
1555
0
            *input += static_strlen("*/");
1556
0
            return;
1557
0
        }
1558
0
    }
1559
0
}
1560
1561
0
static void minify_string(char **input, char **output) {
1562
0
    (*output)[0] = (*input)[0];
1563
0
    *input += static_strlen("\"");
1564
0
    *output += static_strlen("\"");
1565
1566
0
    for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
1567
0
        (*output)[0] = (*input)[0];
1568
1569
0
        if ((*input)[0] == '\"') {
1570
0
            (*output)[0] = '\"';
1571
0
            *input += static_strlen("\"");
1572
0
            *output += static_strlen("\"");
1573
0
            return;
1574
0
        } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
1575
0
            (*output)[1] = (*input)[1];
1576
0
            *input += static_strlen("\"");
1577
0
            *output += static_strlen("\"");
1578
0
        }
1579
0
    }
1580
0
}
1581
1582
0
CJSON_PUBLIC(void) loader_cJSON_Minify(char *json) {
1583
0
    char *into = json;
1584
1585
0
    if (json == NULL) {
1586
0
        return;
1587
0
    }
1588
1589
0
    while (json[0] != '\0') {
1590
0
        switch (json[0]) {
1591
0
            case ' ':
1592
0
            case '\t':
1593
0
            case '\r':
1594
0
            case '\n':
1595
0
                json++;
1596
0
                break;
1597
1598
0
            case '/':
1599
0
                if (json[1] == '/') {
1600
0
                    skip_oneline_comment(&json);
1601
0
                } else if (json[1] == '*') {
1602
0
                    skip_multiline_comment(&json);
1603
0
                } else {
1604
0
                    json++;
1605
0
                }
1606
0
                break;
1607
1608
0
            case '\"':
1609
0
                minify_string(&json, (char **)&into);
1610
0
                break;
1611
1612
0
            default:
1613
0
                into[0] = json[0];
1614
0
                json++;
1615
0
                into++;
1616
0
        }
1617
0
    }
1618
1619
    /* and null-terminate. */
1620
0
    *into = '\0';
1621
0
}
1622
1623
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsInvalid(const cJSON *const item) {
1624
0
    if (item == NULL) {
1625
0
        return false;
1626
0
    }
1627
1628
0
    return (item->type & 0xFF) == cJSON_Invalid;
1629
0
}
1630
1631
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsFalse(const cJSON *const item) {
1632
0
    if (item == NULL) {
1633
0
        return false;
1634
0
    }
1635
1636
0
    return (item->type & 0xFF) == cJSON_False;
1637
0
}
1638
1639
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsTrue(const cJSON *const item) {
1640
0
    if (item == NULL) {
1641
0
        return false;
1642
0
    }
1643
1644
0
    return (item->type & 0xff) == cJSON_True;
1645
0
}
1646
1647
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsBool(const cJSON *const item) {
1648
0
    if (item == NULL) {
1649
0
        return false;
1650
0
    }
1651
1652
0
    return (item->type & (cJSON_True | cJSON_False)) != 0;
1653
0
}
1654
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsNull(const cJSON *const item) {
1655
0
    if (item == NULL) {
1656
0
        return false;
1657
0
    }
1658
1659
0
    return (item->type & 0xFF) == cJSON_NULL;
1660
0
}
1661
1662
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsNumber(const cJSON *const item) {
1663
0
    if (item == NULL) {
1664
0
        return false;
1665
0
    }
1666
1667
0
    return (item->type & 0xFF) == cJSON_Number;
1668
0
}
1669
1670
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsString(const cJSON *const item) {
1671
0
    if (item == NULL) {
1672
0
        return false;
1673
0
    }
1674
1675
0
    return (item->type & 0xFF) == cJSON_String;
1676
0
}
1677
1678
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsArray(const cJSON *const item) {
1679
0
    if (item == NULL) {
1680
0
        return false;
1681
0
    }
1682
1683
0
    return (item->type & 0xFF) == cJSON_Array;
1684
0
}
1685
1686
0
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) {
1687
0
    if (item == NULL) {
1688
0
        return false;
1689
0
    }
1690
1691
0
    return (item->type & 0xFF) == cJSON_Object;
1692
0
}
1693
1694
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_IsRaw(const cJSON *const item) {
1695
0
    if (item == NULL) {
1696
0
        return false;
1697
0
    }
1698
1699
0
    return (item->type & 0xFF) == cJSON_Raw;
1700
0
}
1701
1702
0
CJSON_PUBLIC(cJSON_bool) loader_cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) {
1703
0
    if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) {
1704
0
        return false;
1705
0
    }
1706
1707
    /* check if type is valid */
1708
0
    switch (a->type & 0xFF) {
1709
0
        case cJSON_False:
1710
0
        case cJSON_True:
1711
0
        case cJSON_NULL:
1712
0
        case cJSON_Number:
1713
0
        case cJSON_String:
1714
0
        case cJSON_Raw:
1715
0
        case cJSON_Array:
1716
0
        case cJSON_Object:
1717
0
            break;
1718
1719
0
        default:
1720
0
            return false;
1721
0
    }
1722
1723
    /* identical objects are equal */
1724
0
    if (a == b) {
1725
0
        return true;
1726
0
    }
1727
1728
0
    switch (a->type & 0xFF) {
1729
        /* in these cases and equal type is enough */
1730
0
        case cJSON_False:
1731
0
        case cJSON_True:
1732
0
        case cJSON_NULL:
1733
0
            return true;
1734
1735
0
        case cJSON_Number:
1736
0
            if (compare_double(a->valuedouble, b->valuedouble)) {
1737
0
                return true;
1738
0
            }
1739
0
            return false;
1740
1741
0
        case cJSON_String:
1742
0
        case cJSON_Raw:
1743
0
            if ((a->valuestring == NULL) || (b->valuestring == NULL)) {
1744
0
                return false;
1745
0
            }
1746
0
            if (strcmp(a->valuestring, b->valuestring) == 0) {
1747
0
                return true;
1748
0
            }
1749
1750
0
            return false;
1751
1752
0
        case cJSON_Array: {
1753
0
            cJSON *a_element = a->child;
1754
0
            cJSON *b_element = b->child;
1755
1756
0
            for (; (a_element != NULL) && (b_element != NULL);) {
1757
0
                if (!loader_cJSON_Compare(a_element, b_element, case_sensitive)) {
1758
0
                    return false;
1759
0
                }
1760
1761
0
                a_element = a_element->next;
1762
0
                b_element = b_element->next;
1763
0
            }
1764
1765
            /* one of the arrays is longer than the other */
1766
0
            if (a_element != b_element) {
1767
0
                return false;
1768
0
            }
1769
1770
0
            return true;
1771
0
        }
1772
1773
0
        case cJSON_Object: {
1774
0
            cJSON *a_element = NULL;
1775
0
            cJSON *b_element = NULL;
1776
0
            cJSON_ArrayForEach(a_element, a) {
1777
                /* TODO This has O(n^2) runtime, which is horrible! */
1778
0
                b_element = get_object_item(b, a_element->string, case_sensitive);
1779
0
                if (b_element == NULL) {
1780
0
                    return false;
1781
0
                }
1782
1783
0
                if (!loader_cJSON_Compare(a_element, b_element, case_sensitive)) {
1784
0
                    return false;
1785
0
                }
1786
0
            }
1787
1788
            /* doing this twice, once on a and b to prevent true comparison if a subset of b
1789
             * TODO: Do this the proper way, this is just a fix for now */
1790
0
            cJSON_ArrayForEach(b_element, b) {
1791
0
                a_element = get_object_item(a, b_element->string, case_sensitive);
1792
0
                if (a_element == NULL) {
1793
0
                    return false;
1794
0
                }
1795
1796
0
                if (!loader_cJSON_Compare(b_element, a_element, case_sensitive)) {
1797
0
                    return false;
1798
0
                }
1799
0
            }
1800
1801
0
            return true;
1802
0
        }
1803
1804
0
        default:
1805
0
            return false;
1806
0
    }
1807
0
}