File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / iperf / src / cjson.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:14:54 2023 UTC (9 months ago) by misho
Branches: iperf, MAIN
CVS tags: v3_15, HEAD
Version 3.15

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>