File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / iperf / src / cjson.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:36:46 2021 UTC (3 years, 4 months ago) by misho
Branches: iperf, MAIN
CVS tags: v3_3_9, HEAD
iperf 3.3.9

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

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