LCOV - code coverage report
Current view: top level - vppinfra - cJSON.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 406 1372 29.6 %
Date: 2023-10-26 01:39:38 Functions: 39 115 33.9 %

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

Generated by: LCOV version 1.14