LCOV - code coverage report
Current view: top level - ballet/json - cJSON.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 637 2288 27.8 %
Date: 2026-01-23 05:02:40 Functions: 38 113 33.6 %

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

Generated by: LCOV version 1.14