Annotation of embedaddon/iperf/src/cjson.c, revision 1.1.1.3

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

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