19750e409Sopenharmony_ci/* 29750e409Sopenharmony_ci Copyright (c) 2009-2017 Dave Gamble and cJSON contributors 39750e409Sopenharmony_ci 49750e409Sopenharmony_ci Permission is hereby granted, free of charge, to any person obtaining a copy 59750e409Sopenharmony_ci of this software and associated documentation files (the "Software"), to deal 69750e409Sopenharmony_ci in the Software without restriction, including without limitation the rights 79750e409Sopenharmony_ci to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 89750e409Sopenharmony_ci copies of the Software, and to permit persons to whom the Software is 99750e409Sopenharmony_ci furnished to do so, subject to the following conditions: 109750e409Sopenharmony_ci 119750e409Sopenharmony_ci The above copyright notice and this permission notice shall be included in 129750e409Sopenharmony_ci all copies or substantial portions of the Software. 139750e409Sopenharmony_ci 149750e409Sopenharmony_ci THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 159750e409Sopenharmony_ci IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 169750e409Sopenharmony_ci FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 179750e409Sopenharmony_ci AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 189750e409Sopenharmony_ci LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 199750e409Sopenharmony_ci OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 209750e409Sopenharmony_ci THE SOFTWARE. 219750e409Sopenharmony_ci*/ 229750e409Sopenharmony_ci 239750e409Sopenharmony_ci/* cJSON */ 249750e409Sopenharmony_ci/* JSON parser in C. */ 259750e409Sopenharmony_ci 269750e409Sopenharmony_ci/* disable warnings about old C89 functions in MSVC */ 279750e409Sopenharmony_ci#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) 289750e409Sopenharmony_ci#define _CRT_SECURE_NO_DEPRECATE 299750e409Sopenharmony_ci#endif 309750e409Sopenharmony_ci 319750e409Sopenharmony_ci#ifdef __GNUC__ 329750e409Sopenharmony_ci#pragma GCC visibility push(default) 339750e409Sopenharmony_ci#endif 349750e409Sopenharmony_ci#if defined(_MSC_VER) 359750e409Sopenharmony_ci#pragma warning (push) 369750e409Sopenharmony_ci/* disable warning about single line comments in system headers */ 379750e409Sopenharmony_ci#pragma warning (disable : 4001) 389750e409Sopenharmony_ci#endif 399750e409Sopenharmony_ci 409750e409Sopenharmony_ci#include <string.h> 419750e409Sopenharmony_ci#include <stdio.h> 429750e409Sopenharmony_ci#include <math.h> 439750e409Sopenharmony_ci#include <stdlib.h> 449750e409Sopenharmony_ci#include <limits.h> 459750e409Sopenharmony_ci#include <ctype.h> 469750e409Sopenharmony_ci#include <float.h> 479750e409Sopenharmony_ci 489750e409Sopenharmony_ci#ifdef ENABLE_LOCALES 499750e409Sopenharmony_ci#include <locale.h> 509750e409Sopenharmony_ci#endif 519750e409Sopenharmony_ci 529750e409Sopenharmony_ci#if defined(_MSC_VER) 539750e409Sopenharmony_ci#pragma warning (pop) 549750e409Sopenharmony_ci#endif 559750e409Sopenharmony_ci#ifdef __GNUC__ 569750e409Sopenharmony_ci#pragma GCC visibility pop 579750e409Sopenharmony_ci#endif 589750e409Sopenharmony_ci 599750e409Sopenharmony_ci#include "cJSON.h" 609750e409Sopenharmony_ci 619750e409Sopenharmony_ci/* define our own boolean type */ 629750e409Sopenharmony_ci#ifdef true 639750e409Sopenharmony_ci#undef true 649750e409Sopenharmony_ci#endif 659750e409Sopenharmony_ci#define true ((cJSON_bool)1) 669750e409Sopenharmony_ci 679750e409Sopenharmony_ci#ifdef false 689750e409Sopenharmony_ci#undef false 699750e409Sopenharmony_ci#endif 709750e409Sopenharmony_ci#define false ((cJSON_bool)0) 719750e409Sopenharmony_ci 729750e409Sopenharmony_ci/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ 739750e409Sopenharmony_ci#ifndef isinf 749750e409Sopenharmony_ci#define isinf(d) (isnan((d - d)) && !isnan(d)) 759750e409Sopenharmony_ci#endif 769750e409Sopenharmony_ci#ifndef isnan 779750e409Sopenharmony_ci#define isnan(d) (d != d) 789750e409Sopenharmony_ci#endif 799750e409Sopenharmony_ci 809750e409Sopenharmony_ci#ifndef NAN 819750e409Sopenharmony_ci#ifdef _WIN32 829750e409Sopenharmony_ci#define NAN sqrt(-1.0) 839750e409Sopenharmony_ci#else 849750e409Sopenharmony_ci#define NAN 0.0/0.0 859750e409Sopenharmony_ci#endif 869750e409Sopenharmony_ci#endif 879750e409Sopenharmony_ci 889750e409Sopenharmony_citypedef struct { 899750e409Sopenharmony_ci const unsigned char *json; 909750e409Sopenharmony_ci size_t position; 919750e409Sopenharmony_ci} error; 929750e409Sopenharmony_cistatic error global_error = { NULL, 0 }; 939750e409Sopenharmony_ci 949750e409Sopenharmony_ciCJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) 959750e409Sopenharmony_ci{ 969750e409Sopenharmony_ci return (const char*) (global_error.json + global_error.position); 979750e409Sopenharmony_ci} 989750e409Sopenharmony_ci 999750e409Sopenharmony_ciCJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) 1009750e409Sopenharmony_ci{ 1019750e409Sopenharmony_ci if (!cJSON_IsString(item)) 1029750e409Sopenharmony_ci { 1039750e409Sopenharmony_ci return NULL; 1049750e409Sopenharmony_ci } 1059750e409Sopenharmony_ci 1069750e409Sopenharmony_ci return item->valuestring; 1079750e409Sopenharmony_ci} 1089750e409Sopenharmony_ci 1099750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 1109750e409Sopenharmony_ciCJSON_PUBLIC(long long *) cJSON_GetInt64NumberValue(cJSON * const item) 1119750e409Sopenharmony_ci{ 1129750e409Sopenharmony_ci if (!cJSON_IsInt64Number(item)) 1139750e409Sopenharmony_ci { 1149750e409Sopenharmony_ci return NULL; 1159750e409Sopenharmony_ci } 1169750e409Sopenharmony_ci 1179750e409Sopenharmony_ci return &(item->valueint); 1189750e409Sopenharmony_ci} 1199750e409Sopenharmony_ci#endif 1209750e409Sopenharmony_ci 1219750e409Sopenharmony_ciCJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) 1229750e409Sopenharmony_ci{ 1239750e409Sopenharmony_ci if (!cJSON_IsNumber(item)) 1249750e409Sopenharmony_ci { 1259750e409Sopenharmony_ci return (double) NAN; 1269750e409Sopenharmony_ci } 1279750e409Sopenharmony_ci 1289750e409Sopenharmony_ci return item->valuedouble; 1299750e409Sopenharmony_ci} 1309750e409Sopenharmony_ci 1319750e409Sopenharmony_ci/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ 1329750e409Sopenharmony_ci#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 17) 1339750e409Sopenharmony_ci #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. 1349750e409Sopenharmony_ci#endif 1359750e409Sopenharmony_ci 1369750e409Sopenharmony_ciCJSON_PUBLIC(const char*) cJSON_Version(void) 1379750e409Sopenharmony_ci{ 1389750e409Sopenharmony_ci static char version[15]; 1399750e409Sopenharmony_ci sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); 1409750e409Sopenharmony_ci 1419750e409Sopenharmony_ci return version; 1429750e409Sopenharmony_ci} 1439750e409Sopenharmony_ci 1449750e409Sopenharmony_ci/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ 1459750e409Sopenharmony_cistatic int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) 1469750e409Sopenharmony_ci{ 1479750e409Sopenharmony_ci if ((string1 == NULL) || (string2 == NULL)) 1489750e409Sopenharmony_ci { 1499750e409Sopenharmony_ci return 1; 1509750e409Sopenharmony_ci } 1519750e409Sopenharmony_ci 1529750e409Sopenharmony_ci if (string1 == string2) 1539750e409Sopenharmony_ci { 1549750e409Sopenharmony_ci return 0; 1559750e409Sopenharmony_ci } 1569750e409Sopenharmony_ci 1579750e409Sopenharmony_ci for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) 1589750e409Sopenharmony_ci { 1599750e409Sopenharmony_ci if (*string1 == '\0') 1609750e409Sopenharmony_ci { 1619750e409Sopenharmony_ci return 0; 1629750e409Sopenharmony_ci } 1639750e409Sopenharmony_ci } 1649750e409Sopenharmony_ci 1659750e409Sopenharmony_ci return tolower(*string1) - tolower(*string2); 1669750e409Sopenharmony_ci} 1679750e409Sopenharmony_ci 1689750e409Sopenharmony_citypedef struct internal_hooks 1699750e409Sopenharmony_ci{ 1709750e409Sopenharmony_ci void *(CJSON_CDECL *allocate)(size_t size); 1719750e409Sopenharmony_ci void (CJSON_CDECL *deallocate)(void *pointer); 1729750e409Sopenharmony_ci void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); 1739750e409Sopenharmony_ci} internal_hooks; 1749750e409Sopenharmony_ci 1759750e409Sopenharmony_ci#if defined(_MSC_VER) 1769750e409Sopenharmony_ci/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ 1779750e409Sopenharmony_cistatic void * CJSON_CDECL internal_malloc(size_t size) 1789750e409Sopenharmony_ci{ 1799750e409Sopenharmony_ci return malloc(size); 1809750e409Sopenharmony_ci} 1819750e409Sopenharmony_cistatic void CJSON_CDECL internal_free(void *pointer) 1829750e409Sopenharmony_ci{ 1839750e409Sopenharmony_ci free(pointer); 1849750e409Sopenharmony_ci} 1859750e409Sopenharmony_cistatic void * CJSON_CDECL internal_realloc(void *pointer, size_t size) 1869750e409Sopenharmony_ci{ 1879750e409Sopenharmony_ci return realloc(pointer, size); 1889750e409Sopenharmony_ci} 1899750e409Sopenharmony_ci#else 1909750e409Sopenharmony_ci#define internal_malloc malloc 1919750e409Sopenharmony_ci#define internal_free free 1929750e409Sopenharmony_ci#define internal_realloc realloc 1939750e409Sopenharmony_ci#endif 1949750e409Sopenharmony_ci 1959750e409Sopenharmony_ci/* strlen of character literals resolved at compile time */ 1969750e409Sopenharmony_ci#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) 1979750e409Sopenharmony_ci 1989750e409Sopenharmony_cistatic internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; 1999750e409Sopenharmony_ci 2009750e409Sopenharmony_cistatic unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) 2019750e409Sopenharmony_ci{ 2029750e409Sopenharmony_ci size_t length = 0; 2039750e409Sopenharmony_ci unsigned char *copy = NULL; 2049750e409Sopenharmony_ci 2059750e409Sopenharmony_ci if (string == NULL) 2069750e409Sopenharmony_ci { 2079750e409Sopenharmony_ci return NULL; 2089750e409Sopenharmony_ci } 2099750e409Sopenharmony_ci 2109750e409Sopenharmony_ci length = strlen((const char*)string) + sizeof(""); 2119750e409Sopenharmony_ci copy = (unsigned char*)hooks->allocate(length); 2129750e409Sopenharmony_ci if (copy == NULL) 2139750e409Sopenharmony_ci { 2149750e409Sopenharmony_ci return NULL; 2159750e409Sopenharmony_ci } 2169750e409Sopenharmony_ci memcpy(copy, string, length); 2179750e409Sopenharmony_ci 2189750e409Sopenharmony_ci return copy; 2199750e409Sopenharmony_ci} 2209750e409Sopenharmony_ci 2219750e409Sopenharmony_ciCJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) 2229750e409Sopenharmony_ci{ 2239750e409Sopenharmony_ci if (hooks == NULL) 2249750e409Sopenharmony_ci { 2259750e409Sopenharmony_ci /* Reset hooks */ 2269750e409Sopenharmony_ci global_hooks.allocate = malloc; 2279750e409Sopenharmony_ci global_hooks.deallocate = free; 2289750e409Sopenharmony_ci global_hooks.reallocate = realloc; 2299750e409Sopenharmony_ci return; 2309750e409Sopenharmony_ci } 2319750e409Sopenharmony_ci 2329750e409Sopenharmony_ci global_hooks.allocate = malloc; 2339750e409Sopenharmony_ci if (hooks->malloc_fn != NULL) 2349750e409Sopenharmony_ci { 2359750e409Sopenharmony_ci global_hooks.allocate = hooks->malloc_fn; 2369750e409Sopenharmony_ci } 2379750e409Sopenharmony_ci 2389750e409Sopenharmony_ci global_hooks.deallocate = free; 2399750e409Sopenharmony_ci if (hooks->free_fn != NULL) 2409750e409Sopenharmony_ci { 2419750e409Sopenharmony_ci global_hooks.deallocate = hooks->free_fn; 2429750e409Sopenharmony_ci } 2439750e409Sopenharmony_ci 2449750e409Sopenharmony_ci /* use realloc only if both free and malloc are used */ 2459750e409Sopenharmony_ci global_hooks.reallocate = NULL; 2469750e409Sopenharmony_ci if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) 2479750e409Sopenharmony_ci { 2489750e409Sopenharmony_ci global_hooks.reallocate = realloc; 2499750e409Sopenharmony_ci } 2509750e409Sopenharmony_ci} 2519750e409Sopenharmony_ci 2529750e409Sopenharmony_ci/* Internal constructor. */ 2539750e409Sopenharmony_cistatic cJSON *cJSON_New_Item(const internal_hooks * const hooks) 2549750e409Sopenharmony_ci{ 2559750e409Sopenharmony_ci cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); 2569750e409Sopenharmony_ci if (node) 2579750e409Sopenharmony_ci { 2589750e409Sopenharmony_ci memset(node, '\0', sizeof(cJSON)); 2599750e409Sopenharmony_ci } 2609750e409Sopenharmony_ci 2619750e409Sopenharmony_ci return node; 2629750e409Sopenharmony_ci} 2639750e409Sopenharmony_ci 2649750e409Sopenharmony_ci/* Delete a cJSON structure. */ 2659750e409Sopenharmony_ciCJSON_PUBLIC(void) cJSON_Delete(cJSON *item) 2669750e409Sopenharmony_ci{ 2679750e409Sopenharmony_ci cJSON *next = NULL; 2689750e409Sopenharmony_ci while (item != NULL) 2699750e409Sopenharmony_ci { 2709750e409Sopenharmony_ci next = item->next; 2719750e409Sopenharmony_ci if (!(item->type & cJSON_IsReference) && (item->child != NULL)) 2729750e409Sopenharmony_ci { 2739750e409Sopenharmony_ci cJSON_Delete(item->child); 2749750e409Sopenharmony_ci } 2759750e409Sopenharmony_ci if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) 2769750e409Sopenharmony_ci { 2779750e409Sopenharmony_ci global_hooks.deallocate(item->valuestring); 2789750e409Sopenharmony_ci item->valuestring = NULL; 2799750e409Sopenharmony_ci } 2809750e409Sopenharmony_ci if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) 2819750e409Sopenharmony_ci { 2829750e409Sopenharmony_ci global_hooks.deallocate(item->string); 2839750e409Sopenharmony_ci item->string = NULL; 2849750e409Sopenharmony_ci } 2859750e409Sopenharmony_ci if (next == item) 2869750e409Sopenharmony_ci { 2879750e409Sopenharmony_ci break; 2889750e409Sopenharmony_ci } 2899750e409Sopenharmony_ci global_hooks.deallocate(item); 2909750e409Sopenharmony_ci item = next; 2919750e409Sopenharmony_ci } 2929750e409Sopenharmony_ci} 2939750e409Sopenharmony_ci 2949750e409Sopenharmony_ci/* get the decimal point character of the current locale */ 2959750e409Sopenharmony_cistatic unsigned char get_decimal_point(void) 2969750e409Sopenharmony_ci{ 2979750e409Sopenharmony_ci#ifdef ENABLE_LOCALES 2989750e409Sopenharmony_ci struct lconv *lconv = localeconv(); 2999750e409Sopenharmony_ci return (unsigned char) lconv->decimal_point[0]; 3009750e409Sopenharmony_ci#else 3019750e409Sopenharmony_ci return '.'; 3029750e409Sopenharmony_ci#endif 3039750e409Sopenharmony_ci} 3049750e409Sopenharmony_ci 3059750e409Sopenharmony_citypedef struct 3069750e409Sopenharmony_ci{ 3079750e409Sopenharmony_ci const unsigned char *content; 3089750e409Sopenharmony_ci size_t length; 3099750e409Sopenharmony_ci size_t offset; 3109750e409Sopenharmony_ci size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ 3119750e409Sopenharmony_ci internal_hooks hooks; 3129750e409Sopenharmony_ci} parse_buffer; 3139750e409Sopenharmony_ci 3149750e409Sopenharmony_ci/* check if the given size is left to read in a given parse buffer (starting with 1) */ 3159750e409Sopenharmony_ci#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) 3169750e409Sopenharmony_ci/* check if the buffer can be accessed at the given index (starting with 0) */ 3179750e409Sopenharmony_ci#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) 3189750e409Sopenharmony_ci#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) 3199750e409Sopenharmony_ci/* get a pointer to the buffer at the position */ 3209750e409Sopenharmony_ci#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) 3219750e409Sopenharmony_ci 3229750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 3239750e409Sopenharmony_ci/* Parse the input text to generate a number, and populate the result into item. */ 3249750e409Sopenharmony_cistatic cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) 3259750e409Sopenharmony_ci{ 3269750e409Sopenharmony_ci double number = 0; 3279750e409Sopenharmony_ci long long integer = 0; 3289750e409Sopenharmony_ci unsigned char *after_end = NULL; 3299750e409Sopenharmony_ci unsigned char number_c_string[64]; 3309750e409Sopenharmony_ci unsigned char decimal_point = get_decimal_point(); 3319750e409Sopenharmony_ci size_t i = 0; 3329750e409Sopenharmony_ci cJSON_bool is_integer = true; 3339750e409Sopenharmony_ci 3349750e409Sopenharmony_ci if ((input_buffer == NULL) || (input_buffer->content == NULL)) 3359750e409Sopenharmony_ci { 3369750e409Sopenharmony_ci return false; 3379750e409Sopenharmony_ci } 3389750e409Sopenharmony_ci 3399750e409Sopenharmony_ci /* copy the number into a temporary buffer and replace '.' with the decimal point 3409750e409Sopenharmony_ci * of the current locale (for strtod) 3419750e409Sopenharmony_ci * This also takes care of '\0' not necessarily being available for marking the end of the input */ 3429750e409Sopenharmony_ci for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) 3439750e409Sopenharmony_ci { 3449750e409Sopenharmony_ci switch (buffer_at_offset(input_buffer)[i]) 3459750e409Sopenharmony_ci { 3469750e409Sopenharmony_ci case '0': 3479750e409Sopenharmony_ci case '1': 3489750e409Sopenharmony_ci case '2': 3499750e409Sopenharmony_ci case '3': 3509750e409Sopenharmony_ci case '4': 3519750e409Sopenharmony_ci case '5': 3529750e409Sopenharmony_ci case '6': 3539750e409Sopenharmony_ci case '7': 3549750e409Sopenharmony_ci case '8': 3559750e409Sopenharmony_ci case '9': 3569750e409Sopenharmony_ci case '+': 3579750e409Sopenharmony_ci case '-': 3589750e409Sopenharmony_ci number_c_string[i] = buffer_at_offset(input_buffer)[i]; 3599750e409Sopenharmony_ci break; 3609750e409Sopenharmony_ci case 'e': 3619750e409Sopenharmony_ci case 'E': 3629750e409Sopenharmony_ci number_c_string[i] = buffer_at_offset(input_buffer)[i]; 3639750e409Sopenharmony_ci is_integer = false; 3649750e409Sopenharmony_ci break; 3659750e409Sopenharmony_ci 3669750e409Sopenharmony_ci case '.': 3679750e409Sopenharmony_ci number_c_string[i] = decimal_point; 3689750e409Sopenharmony_ci is_integer = false; 3699750e409Sopenharmony_ci break; 3709750e409Sopenharmony_ci 3719750e409Sopenharmony_ci default: 3729750e409Sopenharmony_ci goto loop_end; 3739750e409Sopenharmony_ci } 3749750e409Sopenharmony_ci } 3759750e409Sopenharmony_ciloop_end: 3769750e409Sopenharmony_ci number_c_string[i] = '\0'; 3779750e409Sopenharmony_ci 3789750e409Sopenharmony_ci /* use guard clause to process the int64 case first */ 3799750e409Sopenharmony_ci if (is_integer) 3809750e409Sopenharmony_ci { 3819750e409Sopenharmony_ci /* for int64 values, set cJSON_IsInt64 */ 3829750e409Sopenharmony_ci item->type = cJSON_Number | cJSON_IsInt64; 3839750e409Sopenharmony_ci integer = strtoll((const char*)number_c_string, (char**)&after_end, 10); 3849750e409Sopenharmony_ci if (number_c_string == after_end) 3859750e409Sopenharmony_ci { 3869750e409Sopenharmony_ci return false; /* parse_error */ 3879750e409Sopenharmony_ci } 3889750e409Sopenharmony_ci item->valueint = integer; 3899750e409Sopenharmony_ci item->valuedouble = (double)integer; 3909750e409Sopenharmony_ci goto parse_end; 3919750e409Sopenharmony_ci } 3929750e409Sopenharmony_ci 3939750e409Sopenharmony_ci number = strtod((const char*)number_c_string, (char**)&after_end); 3949750e409Sopenharmony_ci if (number_c_string == after_end) 3959750e409Sopenharmony_ci { 3969750e409Sopenharmony_ci return false; /* parse_error */ 3979750e409Sopenharmony_ci } 3989750e409Sopenharmony_ci 3999750e409Sopenharmony_ci item->valuedouble = number; 4009750e409Sopenharmony_ci 4019750e409Sopenharmony_ci /* use saturation in case of overflow */ 4029750e409Sopenharmony_ci if (number >= (double)LLONG_MAX) 4039750e409Sopenharmony_ci { 4049750e409Sopenharmony_ci item->valueint = LLONG_MAX; 4059750e409Sopenharmony_ci } 4069750e409Sopenharmony_ci else if (number <= (double)LLONG_MIN) 4079750e409Sopenharmony_ci { 4089750e409Sopenharmony_ci item->valueint = LLONG_MIN; 4099750e409Sopenharmony_ci } 4109750e409Sopenharmony_ci else 4119750e409Sopenharmony_ci { 4129750e409Sopenharmony_ci item->valueint = (long long)number; 4139750e409Sopenharmony_ci } 4149750e409Sopenharmony_ci 4159750e409Sopenharmony_ci item->type = cJSON_Number; 4169750e409Sopenharmony_ci 4179750e409Sopenharmony_ciparse_end: 4189750e409Sopenharmony_ci input_buffer->offset += (size_t)(after_end - number_c_string); 4199750e409Sopenharmony_ci return true; 4209750e409Sopenharmony_ci} 4219750e409Sopenharmony_ci#else 4229750e409Sopenharmony_ci/* Parse the input text to generate a number, and populate the result into item. */ 4239750e409Sopenharmony_cistatic cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) 4249750e409Sopenharmony_ci{ 4259750e409Sopenharmony_ci double number = 0; 4269750e409Sopenharmony_ci unsigned char *after_end = NULL; 4279750e409Sopenharmony_ci unsigned char number_c_string[64]; 4289750e409Sopenharmony_ci unsigned char decimal_point = get_decimal_point(); 4299750e409Sopenharmony_ci size_t i = 0; 4309750e409Sopenharmony_ci 4319750e409Sopenharmony_ci if ((input_buffer == NULL) || (input_buffer->content == NULL)) 4329750e409Sopenharmony_ci { 4339750e409Sopenharmony_ci return false; 4349750e409Sopenharmony_ci } 4359750e409Sopenharmony_ci 4369750e409Sopenharmony_ci /* copy the number into a temporary buffer and replace '.' with the decimal point 4379750e409Sopenharmony_ci * of the current locale (for strtod) 4389750e409Sopenharmony_ci * This also takes care of '\0' not necessarily being available for marking the end of the input */ 4399750e409Sopenharmony_ci for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) 4409750e409Sopenharmony_ci { 4419750e409Sopenharmony_ci switch (buffer_at_offset(input_buffer)[i]) 4429750e409Sopenharmony_ci { 4439750e409Sopenharmony_ci case '0': 4449750e409Sopenharmony_ci case '1': 4459750e409Sopenharmony_ci case '2': 4469750e409Sopenharmony_ci case '3': 4479750e409Sopenharmony_ci case '4': 4489750e409Sopenharmony_ci case '5': 4499750e409Sopenharmony_ci case '6': 4509750e409Sopenharmony_ci case '7': 4519750e409Sopenharmony_ci case '8': 4529750e409Sopenharmony_ci case '9': 4539750e409Sopenharmony_ci case '+': 4549750e409Sopenharmony_ci case '-': 4559750e409Sopenharmony_ci case 'e': 4569750e409Sopenharmony_ci case 'E': 4579750e409Sopenharmony_ci number_c_string[i] = buffer_at_offset(input_buffer)[i]; 4589750e409Sopenharmony_ci break; 4599750e409Sopenharmony_ci 4609750e409Sopenharmony_ci case '.': 4619750e409Sopenharmony_ci number_c_string[i] = decimal_point; 4629750e409Sopenharmony_ci break; 4639750e409Sopenharmony_ci 4649750e409Sopenharmony_ci default: 4659750e409Sopenharmony_ci goto loop_end; 4669750e409Sopenharmony_ci } 4679750e409Sopenharmony_ci } 4689750e409Sopenharmony_ciloop_end: 4699750e409Sopenharmony_ci number_c_string[i] = '\0'; 4709750e409Sopenharmony_ci 4719750e409Sopenharmony_ci number = strtod((const char*)number_c_string, (char**)&after_end); 4729750e409Sopenharmony_ci if (number_c_string == after_end) 4739750e409Sopenharmony_ci { 4749750e409Sopenharmony_ci return false; /* parse_error */ 4759750e409Sopenharmony_ci } 4769750e409Sopenharmony_ci 4779750e409Sopenharmony_ci item->valuedouble = number; 4789750e409Sopenharmony_ci 4799750e409Sopenharmony_ci /* use saturation in case of overflow */ 4809750e409Sopenharmony_ci if (number >= INT_MAX) 4819750e409Sopenharmony_ci { 4829750e409Sopenharmony_ci item->valueint = INT_MAX; 4839750e409Sopenharmony_ci } 4849750e409Sopenharmony_ci else if (number <= (double)INT_MIN) 4859750e409Sopenharmony_ci { 4869750e409Sopenharmony_ci item->valueint = INT_MIN; 4879750e409Sopenharmony_ci } 4889750e409Sopenharmony_ci else 4899750e409Sopenharmony_ci { 4909750e409Sopenharmony_ci item->valueint = (int)number; 4919750e409Sopenharmony_ci } 4929750e409Sopenharmony_ci 4939750e409Sopenharmony_ci item->type = cJSON_Number; 4949750e409Sopenharmony_ci 4959750e409Sopenharmony_ci input_buffer->offset += (size_t)(after_end - number_c_string); 4969750e409Sopenharmony_ci return true; 4979750e409Sopenharmony_ci} 4989750e409Sopenharmony_ci#endif /* __CJSON_USE_INT64 */ 4999750e409Sopenharmony_ci 5009750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 5019750e409Sopenharmony_ciCJSON_PUBLIC(long long) cJSON_SetInt64NumberValue(cJSON * const object, const long long integer) 5029750e409Sopenharmony_ci{ 5039750e409Sopenharmony_ci if (object == NULL) 5049750e409Sopenharmony_ci { 5059750e409Sopenharmony_ci return integer; 5069750e409Sopenharmony_ci } 5079750e409Sopenharmony_ci 5089750e409Sopenharmony_ci /* check the type before setting values */ 5099750e409Sopenharmony_ci if (!(object->type & cJSON_Number) || !(object->type & cJSON_IsInt64)) 5109750e409Sopenharmony_ci { 5119750e409Sopenharmony_ci return integer; 5129750e409Sopenharmony_ci } 5139750e409Sopenharmony_ci 5149750e409Sopenharmony_ci object->valueint = integer; 5159750e409Sopenharmony_ci object->valuedouble = (double)integer; 5169750e409Sopenharmony_ci 5179750e409Sopenharmony_ci return integer; 5189750e409Sopenharmony_ci} 5199750e409Sopenharmony_ci#endif /* __CJSON_USE_INT64 */ 5209750e409Sopenharmony_ci 5219750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 5229750e409Sopenharmony_ci/* note that double max(DBL_MAX) is bigger than long long max(LLONG_MAX) */ 5239750e409Sopenharmony_ciCJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) 5249750e409Sopenharmony_ci{ 5259750e409Sopenharmony_ci if (number >= (double)LLONG_MAX) 5269750e409Sopenharmony_ci { 5279750e409Sopenharmony_ci object->valueint = LLONG_MAX; 5289750e409Sopenharmony_ci } 5299750e409Sopenharmony_ci else if (number <= (double)LLONG_MIN) 5309750e409Sopenharmony_ci { 5319750e409Sopenharmony_ci object->valueint = LLONG_MIN; 5329750e409Sopenharmony_ci } 5339750e409Sopenharmony_ci else 5349750e409Sopenharmony_ci { 5359750e409Sopenharmony_ci object->valueint = (long long)number; 5369750e409Sopenharmony_ci } 5379750e409Sopenharmony_ci 5389750e409Sopenharmony_ci return object->valuedouble = number; 5399750e409Sopenharmony_ci} 5409750e409Sopenharmony_ci#else 5419750e409Sopenharmony_ci/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ 5429750e409Sopenharmony_ciCJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) 5439750e409Sopenharmony_ci{ 5449750e409Sopenharmony_ci if (number >= INT_MAX) 5459750e409Sopenharmony_ci { 5469750e409Sopenharmony_ci object->valueint = INT_MAX; 5479750e409Sopenharmony_ci } 5489750e409Sopenharmony_ci else if (number <= (double)INT_MIN) 5499750e409Sopenharmony_ci { 5509750e409Sopenharmony_ci object->valueint = INT_MIN; 5519750e409Sopenharmony_ci } 5529750e409Sopenharmony_ci else 5539750e409Sopenharmony_ci { 5549750e409Sopenharmony_ci object->valueint = (int)number; 5559750e409Sopenharmony_ci } 5569750e409Sopenharmony_ci 5579750e409Sopenharmony_ci return object->valuedouble = number; 5589750e409Sopenharmony_ci} 5599750e409Sopenharmony_ci#endif /* #ifdef __CJSON_USE_INT64 */ 5609750e409Sopenharmony_ci 5619750e409Sopenharmony_ciCJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) 5629750e409Sopenharmony_ci{ 5639750e409Sopenharmony_ci char *copy = NULL; 5649750e409Sopenharmony_ci /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ 5659750e409Sopenharmony_ci if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference)) 5669750e409Sopenharmony_ci { 5679750e409Sopenharmony_ci return NULL; 5689750e409Sopenharmony_ci } 5699750e409Sopenharmony_ci /* return NULL if the object is corrupted */ 5709750e409Sopenharmony_ci if (object->valuestring == NULL || valuestring == NULL) 5719750e409Sopenharmony_ci { 5729750e409Sopenharmony_ci return NULL; 5739750e409Sopenharmony_ci } 5749750e409Sopenharmony_ci if (strlen(valuestring) <= strlen(object->valuestring)) 5759750e409Sopenharmony_ci { 5769750e409Sopenharmony_ci strcpy(object->valuestring, valuestring); 5779750e409Sopenharmony_ci return object->valuestring; 5789750e409Sopenharmony_ci } 5799750e409Sopenharmony_ci copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); 5809750e409Sopenharmony_ci if (copy == NULL) 5819750e409Sopenharmony_ci { 5829750e409Sopenharmony_ci return NULL; 5839750e409Sopenharmony_ci } 5849750e409Sopenharmony_ci if (object->valuestring != NULL) 5859750e409Sopenharmony_ci { 5869750e409Sopenharmony_ci cJSON_free(object->valuestring); 5879750e409Sopenharmony_ci } 5889750e409Sopenharmony_ci object->valuestring = copy; 5899750e409Sopenharmony_ci 5909750e409Sopenharmony_ci return copy; 5919750e409Sopenharmony_ci} 5929750e409Sopenharmony_ci 5939750e409Sopenharmony_citypedef struct 5949750e409Sopenharmony_ci{ 5959750e409Sopenharmony_ci unsigned char *buffer; 5969750e409Sopenharmony_ci size_t length; 5979750e409Sopenharmony_ci size_t offset; 5989750e409Sopenharmony_ci size_t depth; /* current nesting depth (for formatted printing) */ 5999750e409Sopenharmony_ci cJSON_bool noalloc; 6009750e409Sopenharmony_ci cJSON_bool format; /* is this print a formatted print */ 6019750e409Sopenharmony_ci internal_hooks hooks; 6029750e409Sopenharmony_ci} printbuffer; 6039750e409Sopenharmony_ci 6049750e409Sopenharmony_ci/* realloc printbuffer if necessary to have at least "needed" bytes more */ 6059750e409Sopenharmony_cistatic unsigned char* ensure(printbuffer * const p, size_t needed) 6069750e409Sopenharmony_ci{ 6079750e409Sopenharmony_ci unsigned char *newbuffer = NULL; 6089750e409Sopenharmony_ci size_t newsize = 0; 6099750e409Sopenharmony_ci 6109750e409Sopenharmony_ci if ((p == NULL) || (p->buffer == NULL)) 6119750e409Sopenharmony_ci { 6129750e409Sopenharmony_ci return NULL; 6139750e409Sopenharmony_ci } 6149750e409Sopenharmony_ci 6159750e409Sopenharmony_ci if ((p->length > 0) && (p->offset >= p->length)) 6169750e409Sopenharmony_ci { 6179750e409Sopenharmony_ci /* make sure that offset is valid */ 6189750e409Sopenharmony_ci return NULL; 6199750e409Sopenharmony_ci } 6209750e409Sopenharmony_ci 6219750e409Sopenharmony_ci if (needed > INT_MAX) 6229750e409Sopenharmony_ci { 6239750e409Sopenharmony_ci /* sizes bigger than INT_MAX are currently not supported */ 6249750e409Sopenharmony_ci return NULL; 6259750e409Sopenharmony_ci } 6269750e409Sopenharmony_ci 6279750e409Sopenharmony_ci needed += p->offset + 1; 6289750e409Sopenharmony_ci if (needed <= p->length) 6299750e409Sopenharmony_ci { 6309750e409Sopenharmony_ci return p->buffer + p->offset; 6319750e409Sopenharmony_ci } 6329750e409Sopenharmony_ci 6339750e409Sopenharmony_ci if (p->noalloc) { 6349750e409Sopenharmony_ci return NULL; 6359750e409Sopenharmony_ci } 6369750e409Sopenharmony_ci 6379750e409Sopenharmony_ci /* calculate new buffer size */ 6389750e409Sopenharmony_ci if (needed > (INT_MAX / 2)) 6399750e409Sopenharmony_ci { 6409750e409Sopenharmony_ci /* overflow of int, use INT_MAX if possible */ 6419750e409Sopenharmony_ci if (needed <= INT_MAX) 6429750e409Sopenharmony_ci { 6439750e409Sopenharmony_ci newsize = INT_MAX; 6449750e409Sopenharmony_ci } 6459750e409Sopenharmony_ci else 6469750e409Sopenharmony_ci { 6479750e409Sopenharmony_ci return NULL; 6489750e409Sopenharmony_ci } 6499750e409Sopenharmony_ci } 6509750e409Sopenharmony_ci else 6519750e409Sopenharmony_ci { 6529750e409Sopenharmony_ci newsize = needed * 2; 6539750e409Sopenharmony_ci } 6549750e409Sopenharmony_ci 6559750e409Sopenharmony_ci if (p->hooks.reallocate != NULL) 6569750e409Sopenharmony_ci { 6579750e409Sopenharmony_ci /* reallocate with realloc if available */ 6589750e409Sopenharmony_ci newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); 6599750e409Sopenharmony_ci if (newbuffer == NULL) 6609750e409Sopenharmony_ci { 6619750e409Sopenharmony_ci p->hooks.deallocate(p->buffer); 6629750e409Sopenharmony_ci p->length = 0; 6639750e409Sopenharmony_ci p->buffer = NULL; 6649750e409Sopenharmony_ci 6659750e409Sopenharmony_ci return NULL; 6669750e409Sopenharmony_ci } 6679750e409Sopenharmony_ci } 6689750e409Sopenharmony_ci else 6699750e409Sopenharmony_ci { 6709750e409Sopenharmony_ci /* otherwise reallocate manually */ 6719750e409Sopenharmony_ci newbuffer = (unsigned char*)p->hooks.allocate(newsize); 6729750e409Sopenharmony_ci if (!newbuffer) 6739750e409Sopenharmony_ci { 6749750e409Sopenharmony_ci p->hooks.deallocate(p->buffer); 6759750e409Sopenharmony_ci p->length = 0; 6769750e409Sopenharmony_ci p->buffer = NULL; 6779750e409Sopenharmony_ci 6789750e409Sopenharmony_ci return NULL; 6799750e409Sopenharmony_ci } 6809750e409Sopenharmony_ci 6819750e409Sopenharmony_ci memcpy(newbuffer, p->buffer, p->offset + 1); 6829750e409Sopenharmony_ci p->hooks.deallocate(p->buffer); 6839750e409Sopenharmony_ci } 6849750e409Sopenharmony_ci p->length = newsize; 6859750e409Sopenharmony_ci p->buffer = newbuffer; 6869750e409Sopenharmony_ci 6879750e409Sopenharmony_ci return newbuffer + p->offset; 6889750e409Sopenharmony_ci} 6899750e409Sopenharmony_ci 6909750e409Sopenharmony_ci/* calculate the new length of the string in a printbuffer and update the offset */ 6919750e409Sopenharmony_cistatic void update_offset(printbuffer * const buffer) 6929750e409Sopenharmony_ci{ 6939750e409Sopenharmony_ci const unsigned char *buffer_pointer = NULL; 6949750e409Sopenharmony_ci if ((buffer == NULL) || (buffer->buffer == NULL)) 6959750e409Sopenharmony_ci { 6969750e409Sopenharmony_ci return; 6979750e409Sopenharmony_ci } 6989750e409Sopenharmony_ci buffer_pointer = buffer->buffer + buffer->offset; 6999750e409Sopenharmony_ci 7009750e409Sopenharmony_ci buffer->offset += strlen((const char*)buffer_pointer); 7019750e409Sopenharmony_ci} 7029750e409Sopenharmony_ci 7039750e409Sopenharmony_ci/* securely comparison of floating-point variables */ 7049750e409Sopenharmony_cistatic cJSON_bool compare_double(double a, double b) 7059750e409Sopenharmony_ci{ 7069750e409Sopenharmony_ci double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); 7079750e409Sopenharmony_ci return (fabs(a - b) <= maxVal * DBL_EPSILON); 7089750e409Sopenharmony_ci} 7099750e409Sopenharmony_ci 7109750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 7119750e409Sopenharmony_ci/* Render the number nicely from the given item into a string. */ 7129750e409Sopenharmony_cistatic cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) 7139750e409Sopenharmony_ci{ 7149750e409Sopenharmony_ci unsigned char *output_pointer = NULL; 7159750e409Sopenharmony_ci double d = item->valuedouble; 7169750e409Sopenharmony_ci long long integer = item->valueint; 7179750e409Sopenharmony_ci int length = 0; 7189750e409Sopenharmony_ci size_t i = 0; 7199750e409Sopenharmony_ci unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ 7209750e409Sopenharmony_ci unsigned char decimal_point = get_decimal_point(); 7219750e409Sopenharmony_ci double test = 0.0; 7229750e409Sopenharmony_ci 7239750e409Sopenharmony_ci if (output_buffer == NULL) 7249750e409Sopenharmony_ci { 7259750e409Sopenharmony_ci return false; 7269750e409Sopenharmony_ci } 7279750e409Sopenharmony_ci 7289750e409Sopenharmony_ci if (item->type & cJSON_IsInt64) 7299750e409Sopenharmony_ci { 7309750e409Sopenharmony_ci /* use lld to print the long long integer */ 7319750e409Sopenharmony_ci length = sprintf((char*)number_buffer, "%lld", integer); 7329750e409Sopenharmony_ci } 7339750e409Sopenharmony_ci else /* item->type == cJSON_Number */ 7349750e409Sopenharmony_ci { 7359750e409Sopenharmony_ci /* This checks for NaN and Infinity */ 7369750e409Sopenharmony_ci if (isnan(d) || isinf(d)) 7379750e409Sopenharmony_ci { 7389750e409Sopenharmony_ci length = sprintf((char*)number_buffer, "null"); 7399750e409Sopenharmony_ci } 7409750e409Sopenharmony_ci else 7419750e409Sopenharmony_ci { 7429750e409Sopenharmony_ci /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ 7439750e409Sopenharmony_ci length = sprintf((char*)number_buffer, "%1.15g", d); 7449750e409Sopenharmony_ci 7459750e409Sopenharmony_ci /* Check whether the original double can be recovered */ 7469750e409Sopenharmony_ci if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) 7479750e409Sopenharmony_ci { 7489750e409Sopenharmony_ci /* If not, print with 17 decimal places of precision */ 7499750e409Sopenharmony_ci length = sprintf((char*)number_buffer, "%1.17g", d); 7509750e409Sopenharmony_ci } 7519750e409Sopenharmony_ci } 7529750e409Sopenharmony_ci } 7539750e409Sopenharmony_ci 7549750e409Sopenharmony_ci /* sprintf failed or buffer overrun occurred */ 7559750e409Sopenharmony_ci if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) 7569750e409Sopenharmony_ci { 7579750e409Sopenharmony_ci return false; 7589750e409Sopenharmony_ci } 7599750e409Sopenharmony_ci 7609750e409Sopenharmony_ci /* reserve appropriate space in the output */ 7619750e409Sopenharmony_ci output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); 7629750e409Sopenharmony_ci if (output_pointer == NULL) 7639750e409Sopenharmony_ci { 7649750e409Sopenharmony_ci return false; 7659750e409Sopenharmony_ci } 7669750e409Sopenharmony_ci 7679750e409Sopenharmony_ci /* copy the printed number to the output and replace locale 7689750e409Sopenharmony_ci * dependent decimal point with '.' */ 7699750e409Sopenharmony_ci for (i = 0; i < ((size_t)length); i++) 7709750e409Sopenharmony_ci { 7719750e409Sopenharmony_ci if (number_buffer[i] == decimal_point) 7729750e409Sopenharmony_ci { 7739750e409Sopenharmony_ci output_pointer[i] = '.'; 7749750e409Sopenharmony_ci continue; 7759750e409Sopenharmony_ci } 7769750e409Sopenharmony_ci 7779750e409Sopenharmony_ci output_pointer[i] = number_buffer[i]; 7789750e409Sopenharmony_ci } 7799750e409Sopenharmony_ci output_pointer[i] = '\0'; 7809750e409Sopenharmony_ci 7819750e409Sopenharmony_ci output_buffer->offset += (size_t)length; 7829750e409Sopenharmony_ci 7839750e409Sopenharmony_ci return true; 7849750e409Sopenharmony_ci} 7859750e409Sopenharmony_ci#else 7869750e409Sopenharmony_ci/* Render the number nicely from the given item into a string. */ 7879750e409Sopenharmony_cistatic cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) 7889750e409Sopenharmony_ci{ 7899750e409Sopenharmony_ci unsigned char *output_pointer = NULL; 7909750e409Sopenharmony_ci double d = item->valuedouble; 7919750e409Sopenharmony_ci int length = 0; 7929750e409Sopenharmony_ci size_t i = 0; 7939750e409Sopenharmony_ci unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ 7949750e409Sopenharmony_ci unsigned char decimal_point = get_decimal_point(); 7959750e409Sopenharmony_ci double test = 0.0; 7969750e409Sopenharmony_ci 7979750e409Sopenharmony_ci if (output_buffer == NULL) 7989750e409Sopenharmony_ci { 7999750e409Sopenharmony_ci return false; 8009750e409Sopenharmony_ci } 8019750e409Sopenharmony_ci 8029750e409Sopenharmony_ci /* This checks for NaN and Infinity */ 8039750e409Sopenharmony_ci if (isnan(d) || isinf(d)) 8049750e409Sopenharmony_ci { 8059750e409Sopenharmony_ci length = sprintf((char*)number_buffer, "null"); 8069750e409Sopenharmony_ci } 8079750e409Sopenharmony_ci else if(d == (double)item->valueint) 8089750e409Sopenharmony_ci { 8099750e409Sopenharmony_ci length = sprintf((char*)number_buffer, "%d", item->valueint); 8109750e409Sopenharmony_ci } 8119750e409Sopenharmony_ci else 8129750e409Sopenharmony_ci { 8139750e409Sopenharmony_ci /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ 8149750e409Sopenharmony_ci length = sprintf((char*)number_buffer, "%1.15g", d); 8159750e409Sopenharmony_ci 8169750e409Sopenharmony_ci /* Check whether the original double can be recovered */ 8179750e409Sopenharmony_ci if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) 8189750e409Sopenharmony_ci { 8199750e409Sopenharmony_ci /* If not, print with 17 decimal places of precision */ 8209750e409Sopenharmony_ci length = sprintf((char*)number_buffer, "%1.17g", d); 8219750e409Sopenharmony_ci } 8229750e409Sopenharmony_ci } 8239750e409Sopenharmony_ci 8249750e409Sopenharmony_ci /* sprintf failed or buffer overrun occurred */ 8259750e409Sopenharmony_ci if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) 8269750e409Sopenharmony_ci { 8279750e409Sopenharmony_ci return false; 8289750e409Sopenharmony_ci } 8299750e409Sopenharmony_ci 8309750e409Sopenharmony_ci /* reserve appropriate space in the output */ 8319750e409Sopenharmony_ci output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); 8329750e409Sopenharmony_ci if (output_pointer == NULL) 8339750e409Sopenharmony_ci { 8349750e409Sopenharmony_ci return false; 8359750e409Sopenharmony_ci } 8369750e409Sopenharmony_ci 8379750e409Sopenharmony_ci /* copy the printed number to the output and replace locale 8389750e409Sopenharmony_ci * dependent decimal point with '.' */ 8399750e409Sopenharmony_ci for (i = 0; i < ((size_t)length); i++) 8409750e409Sopenharmony_ci { 8419750e409Sopenharmony_ci if (number_buffer[i] == decimal_point) 8429750e409Sopenharmony_ci { 8439750e409Sopenharmony_ci output_pointer[i] = '.'; 8449750e409Sopenharmony_ci continue; 8459750e409Sopenharmony_ci } 8469750e409Sopenharmony_ci 8479750e409Sopenharmony_ci output_pointer[i] = number_buffer[i]; 8489750e409Sopenharmony_ci } 8499750e409Sopenharmony_ci output_pointer[i] = '\0'; 8509750e409Sopenharmony_ci 8519750e409Sopenharmony_ci output_buffer->offset += (size_t)length; 8529750e409Sopenharmony_ci 8539750e409Sopenharmony_ci return true; 8549750e409Sopenharmony_ci} 8559750e409Sopenharmony_ci#endif /* __CJSON_USE_INT64 */ 8569750e409Sopenharmony_ci 8579750e409Sopenharmony_ci/* parse 4 digit hexadecimal number */ 8589750e409Sopenharmony_cistatic unsigned parse_hex4(const unsigned char * const input) 8599750e409Sopenharmony_ci{ 8609750e409Sopenharmony_ci unsigned int h = 0; 8619750e409Sopenharmony_ci size_t i = 0; 8629750e409Sopenharmony_ci 8639750e409Sopenharmony_ci for (i = 0; i < 4; i++) 8649750e409Sopenharmony_ci { 8659750e409Sopenharmony_ci /* parse digit */ 8669750e409Sopenharmony_ci if ((input[i] >= '0') && (input[i] <= '9')) 8679750e409Sopenharmony_ci { 8689750e409Sopenharmony_ci h += (unsigned int) input[i] - '0'; 8699750e409Sopenharmony_ci } 8709750e409Sopenharmony_ci else if ((input[i] >= 'A') && (input[i] <= 'F')) 8719750e409Sopenharmony_ci { 8729750e409Sopenharmony_ci h += (unsigned int) 10 + input[i] - 'A'; 8739750e409Sopenharmony_ci } 8749750e409Sopenharmony_ci else if ((input[i] >= 'a') && (input[i] <= 'f')) 8759750e409Sopenharmony_ci { 8769750e409Sopenharmony_ci h += (unsigned int) 10 + input[i] - 'a'; 8779750e409Sopenharmony_ci } 8789750e409Sopenharmony_ci else /* invalid */ 8799750e409Sopenharmony_ci { 8809750e409Sopenharmony_ci return 0; 8819750e409Sopenharmony_ci } 8829750e409Sopenharmony_ci 8839750e409Sopenharmony_ci if (i < 3) 8849750e409Sopenharmony_ci { 8859750e409Sopenharmony_ci /* shift left to make place for the next nibble */ 8869750e409Sopenharmony_ci h = h << 4; 8879750e409Sopenharmony_ci } 8889750e409Sopenharmony_ci } 8899750e409Sopenharmony_ci 8909750e409Sopenharmony_ci return h; 8919750e409Sopenharmony_ci} 8929750e409Sopenharmony_ci 8939750e409Sopenharmony_ci/* converts a UTF-16 literal to UTF-8 8949750e409Sopenharmony_ci * A literal can be one or two sequences of the form \uXXXX */ 8959750e409Sopenharmony_cistatic unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) 8969750e409Sopenharmony_ci{ 8979750e409Sopenharmony_ci long unsigned int codepoint = 0; 8989750e409Sopenharmony_ci unsigned int first_code = 0; 8999750e409Sopenharmony_ci const unsigned char *first_sequence = input_pointer; 9009750e409Sopenharmony_ci unsigned char utf8_length = 0; 9019750e409Sopenharmony_ci unsigned char utf8_position = 0; 9029750e409Sopenharmony_ci unsigned char sequence_length = 0; 9039750e409Sopenharmony_ci unsigned char first_byte_mark = 0; 9049750e409Sopenharmony_ci 9059750e409Sopenharmony_ci if ((input_end - first_sequence) < 6) 9069750e409Sopenharmony_ci { 9079750e409Sopenharmony_ci /* input ends unexpectedly */ 9089750e409Sopenharmony_ci goto fail; 9099750e409Sopenharmony_ci } 9109750e409Sopenharmony_ci 9119750e409Sopenharmony_ci /* get the first utf16 sequence */ 9129750e409Sopenharmony_ci first_code = parse_hex4(first_sequence + 2); 9139750e409Sopenharmony_ci 9149750e409Sopenharmony_ci /* check that the code is valid */ 9159750e409Sopenharmony_ci if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) 9169750e409Sopenharmony_ci { 9179750e409Sopenharmony_ci goto fail; 9189750e409Sopenharmony_ci } 9199750e409Sopenharmony_ci 9209750e409Sopenharmony_ci /* UTF16 surrogate pair */ 9219750e409Sopenharmony_ci if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) 9229750e409Sopenharmony_ci { 9239750e409Sopenharmony_ci const unsigned char *second_sequence = first_sequence + 6; 9249750e409Sopenharmony_ci unsigned int second_code = 0; 9259750e409Sopenharmony_ci sequence_length = 12; /* \uXXXX\uXXXX */ 9269750e409Sopenharmony_ci 9279750e409Sopenharmony_ci if ((input_end - second_sequence) < 6) 9289750e409Sopenharmony_ci { 9299750e409Sopenharmony_ci /* input ends unexpectedly */ 9309750e409Sopenharmony_ci goto fail; 9319750e409Sopenharmony_ci } 9329750e409Sopenharmony_ci 9339750e409Sopenharmony_ci if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) 9349750e409Sopenharmony_ci { 9359750e409Sopenharmony_ci /* missing second half of the surrogate pair */ 9369750e409Sopenharmony_ci goto fail; 9379750e409Sopenharmony_ci } 9389750e409Sopenharmony_ci 9399750e409Sopenharmony_ci /* get the second utf16 sequence */ 9409750e409Sopenharmony_ci second_code = parse_hex4(second_sequence + 2); 9419750e409Sopenharmony_ci /* check that the code is valid */ 9429750e409Sopenharmony_ci if ((second_code < 0xDC00) || (second_code > 0xDFFF)) 9439750e409Sopenharmony_ci { 9449750e409Sopenharmony_ci /* invalid second half of the surrogate pair */ 9459750e409Sopenharmony_ci goto fail; 9469750e409Sopenharmony_ci } 9479750e409Sopenharmony_ci 9489750e409Sopenharmony_ci 9499750e409Sopenharmony_ci /* calculate the unicode codepoint from the surrogate pair */ 9509750e409Sopenharmony_ci codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); 9519750e409Sopenharmony_ci } 9529750e409Sopenharmony_ci else 9539750e409Sopenharmony_ci { 9549750e409Sopenharmony_ci sequence_length = 6; /* \uXXXX */ 9559750e409Sopenharmony_ci codepoint = first_code; 9569750e409Sopenharmony_ci } 9579750e409Sopenharmony_ci 9589750e409Sopenharmony_ci /* encode as UTF-8 9599750e409Sopenharmony_ci * takes at maximum 4 bytes to encode: 9609750e409Sopenharmony_ci * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ 9619750e409Sopenharmony_ci if (codepoint < 0x80) 9629750e409Sopenharmony_ci { 9639750e409Sopenharmony_ci /* normal ascii, encoding 0xxxxxxx */ 9649750e409Sopenharmony_ci utf8_length = 1; 9659750e409Sopenharmony_ci } 9669750e409Sopenharmony_ci else if (codepoint < 0x800) 9679750e409Sopenharmony_ci { 9689750e409Sopenharmony_ci /* two bytes, encoding 110xxxxx 10xxxxxx */ 9699750e409Sopenharmony_ci utf8_length = 2; 9709750e409Sopenharmony_ci first_byte_mark = 0xC0; /* 11000000 */ 9719750e409Sopenharmony_ci } 9729750e409Sopenharmony_ci else if (codepoint < 0x10000) 9739750e409Sopenharmony_ci { 9749750e409Sopenharmony_ci /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ 9759750e409Sopenharmony_ci utf8_length = 3; 9769750e409Sopenharmony_ci first_byte_mark = 0xE0; /* 11100000 */ 9779750e409Sopenharmony_ci } 9789750e409Sopenharmony_ci else if (codepoint <= 0x10FFFF) 9799750e409Sopenharmony_ci { 9809750e409Sopenharmony_ci /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ 9819750e409Sopenharmony_ci utf8_length = 4; 9829750e409Sopenharmony_ci first_byte_mark = 0xF0; /* 11110000 */ 9839750e409Sopenharmony_ci } 9849750e409Sopenharmony_ci else 9859750e409Sopenharmony_ci { 9869750e409Sopenharmony_ci /* invalid unicode codepoint */ 9879750e409Sopenharmony_ci goto fail; 9889750e409Sopenharmony_ci } 9899750e409Sopenharmony_ci 9909750e409Sopenharmony_ci /* encode as utf8 */ 9919750e409Sopenharmony_ci for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) 9929750e409Sopenharmony_ci { 9939750e409Sopenharmony_ci /* 10xxxxxx */ 9949750e409Sopenharmony_ci (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); 9959750e409Sopenharmony_ci codepoint >>= 6; 9969750e409Sopenharmony_ci } 9979750e409Sopenharmony_ci /* encode first byte */ 9989750e409Sopenharmony_ci if (utf8_length > 1) 9999750e409Sopenharmony_ci { 10009750e409Sopenharmony_ci (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); 10019750e409Sopenharmony_ci } 10029750e409Sopenharmony_ci else 10039750e409Sopenharmony_ci { 10049750e409Sopenharmony_ci (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); 10059750e409Sopenharmony_ci } 10069750e409Sopenharmony_ci 10079750e409Sopenharmony_ci *output_pointer += utf8_length; 10089750e409Sopenharmony_ci 10099750e409Sopenharmony_ci return sequence_length; 10109750e409Sopenharmony_ci 10119750e409Sopenharmony_cifail: 10129750e409Sopenharmony_ci return 0; 10139750e409Sopenharmony_ci} 10149750e409Sopenharmony_ci 10159750e409Sopenharmony_ci/* Parse the input text into an unescaped cinput, and populate item. */ 10169750e409Sopenharmony_cistatic cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) 10179750e409Sopenharmony_ci{ 10189750e409Sopenharmony_ci const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; 10199750e409Sopenharmony_ci const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; 10209750e409Sopenharmony_ci unsigned char *output_pointer = NULL; 10219750e409Sopenharmony_ci unsigned char *output = NULL; 10229750e409Sopenharmony_ci 10239750e409Sopenharmony_ci /* not a string */ 10249750e409Sopenharmony_ci if (buffer_at_offset(input_buffer)[0] != '\"') 10259750e409Sopenharmony_ci { 10269750e409Sopenharmony_ci goto fail; 10279750e409Sopenharmony_ci } 10289750e409Sopenharmony_ci 10299750e409Sopenharmony_ci { 10309750e409Sopenharmony_ci /* calculate approximate size of the output (overestimate) */ 10319750e409Sopenharmony_ci size_t allocation_length = 0; 10329750e409Sopenharmony_ci size_t skipped_bytes = 0; 10339750e409Sopenharmony_ci while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) 10349750e409Sopenharmony_ci { 10359750e409Sopenharmony_ci /* is escape sequence */ 10369750e409Sopenharmony_ci if (input_end[0] == '\\') 10379750e409Sopenharmony_ci { 10389750e409Sopenharmony_ci if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) 10399750e409Sopenharmony_ci { 10409750e409Sopenharmony_ci /* prevent buffer overflow when last input character is a backslash */ 10419750e409Sopenharmony_ci goto fail; 10429750e409Sopenharmony_ci } 10439750e409Sopenharmony_ci skipped_bytes++; 10449750e409Sopenharmony_ci input_end++; 10459750e409Sopenharmony_ci } 10469750e409Sopenharmony_ci input_end++; 10479750e409Sopenharmony_ci } 10489750e409Sopenharmony_ci if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) 10499750e409Sopenharmony_ci { 10509750e409Sopenharmony_ci goto fail; /* string ended unexpectedly */ 10519750e409Sopenharmony_ci } 10529750e409Sopenharmony_ci 10539750e409Sopenharmony_ci /* This is at most how much we need for the output */ 10549750e409Sopenharmony_ci allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; 10559750e409Sopenharmony_ci output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); 10569750e409Sopenharmony_ci if (output == NULL) 10579750e409Sopenharmony_ci { 10589750e409Sopenharmony_ci goto fail; /* allocation failure */ 10599750e409Sopenharmony_ci } 10609750e409Sopenharmony_ci } 10619750e409Sopenharmony_ci 10629750e409Sopenharmony_ci output_pointer = output; 10639750e409Sopenharmony_ci /* loop through the string literal */ 10649750e409Sopenharmony_ci while (input_pointer < input_end) 10659750e409Sopenharmony_ci { 10669750e409Sopenharmony_ci if (*input_pointer != '\\') 10679750e409Sopenharmony_ci { 10689750e409Sopenharmony_ci *output_pointer++ = *input_pointer++; 10699750e409Sopenharmony_ci } 10709750e409Sopenharmony_ci /* escape sequence */ 10719750e409Sopenharmony_ci else 10729750e409Sopenharmony_ci { 10739750e409Sopenharmony_ci unsigned char sequence_length = 2; 10749750e409Sopenharmony_ci if ((input_end - input_pointer) < 1) 10759750e409Sopenharmony_ci { 10769750e409Sopenharmony_ci goto fail; 10779750e409Sopenharmony_ci } 10789750e409Sopenharmony_ci 10799750e409Sopenharmony_ci switch (input_pointer[1]) 10809750e409Sopenharmony_ci { 10819750e409Sopenharmony_ci case 'b': 10829750e409Sopenharmony_ci *output_pointer++ = '\b'; 10839750e409Sopenharmony_ci break; 10849750e409Sopenharmony_ci case 'f': 10859750e409Sopenharmony_ci *output_pointer++ = '\f'; 10869750e409Sopenharmony_ci break; 10879750e409Sopenharmony_ci case 'n': 10889750e409Sopenharmony_ci *output_pointer++ = '\n'; 10899750e409Sopenharmony_ci break; 10909750e409Sopenharmony_ci case 'r': 10919750e409Sopenharmony_ci *output_pointer++ = '\r'; 10929750e409Sopenharmony_ci break; 10939750e409Sopenharmony_ci case 't': 10949750e409Sopenharmony_ci *output_pointer++ = '\t'; 10959750e409Sopenharmony_ci break; 10969750e409Sopenharmony_ci case '\"': 10979750e409Sopenharmony_ci case '\\': 10989750e409Sopenharmony_ci case '/': 10999750e409Sopenharmony_ci *output_pointer++ = input_pointer[1]; 11009750e409Sopenharmony_ci break; 11019750e409Sopenharmony_ci 11029750e409Sopenharmony_ci /* UTF-16 literal */ 11039750e409Sopenharmony_ci case 'u': 11049750e409Sopenharmony_ci sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); 11059750e409Sopenharmony_ci if (sequence_length == 0) 11069750e409Sopenharmony_ci { 11079750e409Sopenharmony_ci /* failed to convert UTF16-literal to UTF-8 */ 11089750e409Sopenharmony_ci goto fail; 11099750e409Sopenharmony_ci } 11109750e409Sopenharmony_ci break; 11119750e409Sopenharmony_ci 11129750e409Sopenharmony_ci default: 11139750e409Sopenharmony_ci goto fail; 11149750e409Sopenharmony_ci } 11159750e409Sopenharmony_ci input_pointer += sequence_length; 11169750e409Sopenharmony_ci } 11179750e409Sopenharmony_ci } 11189750e409Sopenharmony_ci 11199750e409Sopenharmony_ci /* zero terminate the output */ 11209750e409Sopenharmony_ci *output_pointer = '\0'; 11219750e409Sopenharmony_ci 11229750e409Sopenharmony_ci item->type = cJSON_String; 11239750e409Sopenharmony_ci item->valuestring = (char*)output; 11249750e409Sopenharmony_ci 11259750e409Sopenharmony_ci input_buffer->offset = (size_t) (input_end - input_buffer->content); 11269750e409Sopenharmony_ci input_buffer->offset++; 11279750e409Sopenharmony_ci 11289750e409Sopenharmony_ci return true; 11299750e409Sopenharmony_ci 11309750e409Sopenharmony_cifail: 11319750e409Sopenharmony_ci if (output != NULL) 11329750e409Sopenharmony_ci { 11339750e409Sopenharmony_ci input_buffer->hooks.deallocate(output); 11349750e409Sopenharmony_ci } 11359750e409Sopenharmony_ci 11369750e409Sopenharmony_ci if (input_pointer != NULL) 11379750e409Sopenharmony_ci { 11389750e409Sopenharmony_ci input_buffer->offset = (size_t)(input_pointer - input_buffer->content); 11399750e409Sopenharmony_ci } 11409750e409Sopenharmony_ci 11419750e409Sopenharmony_ci return false; 11429750e409Sopenharmony_ci} 11439750e409Sopenharmony_ci 11449750e409Sopenharmony_ci/* Render the cstring provided to an escaped version that can be printed. */ 11459750e409Sopenharmony_cistatic cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) 11469750e409Sopenharmony_ci{ 11479750e409Sopenharmony_ci const unsigned char *input_pointer = NULL; 11489750e409Sopenharmony_ci unsigned char *output = NULL; 11499750e409Sopenharmony_ci unsigned char *output_pointer = NULL; 11509750e409Sopenharmony_ci size_t output_length = 0; 11519750e409Sopenharmony_ci /* numbers of additional characters needed for escaping */ 11529750e409Sopenharmony_ci size_t escape_characters = 0; 11539750e409Sopenharmony_ci 11549750e409Sopenharmony_ci if (output_buffer == NULL) 11559750e409Sopenharmony_ci { 11569750e409Sopenharmony_ci return false; 11579750e409Sopenharmony_ci } 11589750e409Sopenharmony_ci 11599750e409Sopenharmony_ci /* empty string */ 11609750e409Sopenharmony_ci if (input == NULL) 11619750e409Sopenharmony_ci { 11629750e409Sopenharmony_ci output = ensure(output_buffer, sizeof("\"\"")); 11639750e409Sopenharmony_ci if (output == NULL) 11649750e409Sopenharmony_ci { 11659750e409Sopenharmony_ci return false; 11669750e409Sopenharmony_ci } 11679750e409Sopenharmony_ci strcpy((char*)output, "\"\""); 11689750e409Sopenharmony_ci 11699750e409Sopenharmony_ci return true; 11709750e409Sopenharmony_ci } 11719750e409Sopenharmony_ci 11729750e409Sopenharmony_ci /* set "flag" to 1 if something needs to be escaped */ 11739750e409Sopenharmony_ci for (input_pointer = input; *input_pointer; input_pointer++) 11749750e409Sopenharmony_ci { 11759750e409Sopenharmony_ci switch (*input_pointer) 11769750e409Sopenharmony_ci { 11779750e409Sopenharmony_ci case '\"': 11789750e409Sopenharmony_ci case '\\': 11799750e409Sopenharmony_ci case '\b': 11809750e409Sopenharmony_ci case '\f': 11819750e409Sopenharmony_ci case '\n': 11829750e409Sopenharmony_ci case '\r': 11839750e409Sopenharmony_ci case '\t': 11849750e409Sopenharmony_ci /* one character escape sequence */ 11859750e409Sopenharmony_ci escape_characters++; 11869750e409Sopenharmony_ci break; 11879750e409Sopenharmony_ci default: 11889750e409Sopenharmony_ci if (*input_pointer < 32) 11899750e409Sopenharmony_ci { 11909750e409Sopenharmony_ci /* UTF-16 escape sequence uXXXX */ 11919750e409Sopenharmony_ci escape_characters += 5; 11929750e409Sopenharmony_ci } 11939750e409Sopenharmony_ci break; 11949750e409Sopenharmony_ci } 11959750e409Sopenharmony_ci } 11969750e409Sopenharmony_ci output_length = (size_t)(input_pointer - input) + escape_characters; 11979750e409Sopenharmony_ci 11989750e409Sopenharmony_ci output = ensure(output_buffer, output_length + sizeof("\"\"")); 11999750e409Sopenharmony_ci if (output == NULL) 12009750e409Sopenharmony_ci { 12019750e409Sopenharmony_ci return false; 12029750e409Sopenharmony_ci } 12039750e409Sopenharmony_ci 12049750e409Sopenharmony_ci /* no characters have to be escaped */ 12059750e409Sopenharmony_ci if (escape_characters == 0) 12069750e409Sopenharmony_ci { 12079750e409Sopenharmony_ci output[0] = '\"'; 12089750e409Sopenharmony_ci memcpy(output + 1, input, output_length); 12099750e409Sopenharmony_ci output[output_length + 1] = '\"'; 12109750e409Sopenharmony_ci output[output_length + 2] = '\0'; 12119750e409Sopenharmony_ci 12129750e409Sopenharmony_ci return true; 12139750e409Sopenharmony_ci } 12149750e409Sopenharmony_ci 12159750e409Sopenharmony_ci output[0] = '\"'; 12169750e409Sopenharmony_ci output_pointer = output + 1; 12179750e409Sopenharmony_ci /* copy the string */ 12189750e409Sopenharmony_ci for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) 12199750e409Sopenharmony_ci { 12209750e409Sopenharmony_ci if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) 12219750e409Sopenharmony_ci { 12229750e409Sopenharmony_ci /* normal character, copy */ 12239750e409Sopenharmony_ci *output_pointer = *input_pointer; 12249750e409Sopenharmony_ci } 12259750e409Sopenharmony_ci else 12269750e409Sopenharmony_ci { 12279750e409Sopenharmony_ci /* character needs to be escaped */ 12289750e409Sopenharmony_ci *output_pointer++ = '\\'; 12299750e409Sopenharmony_ci switch (*input_pointer) 12309750e409Sopenharmony_ci { 12319750e409Sopenharmony_ci case '\\': 12329750e409Sopenharmony_ci *output_pointer = '\\'; 12339750e409Sopenharmony_ci break; 12349750e409Sopenharmony_ci case '\"': 12359750e409Sopenharmony_ci *output_pointer = '\"'; 12369750e409Sopenharmony_ci break; 12379750e409Sopenharmony_ci case '\b': 12389750e409Sopenharmony_ci *output_pointer = 'b'; 12399750e409Sopenharmony_ci break; 12409750e409Sopenharmony_ci case '\f': 12419750e409Sopenharmony_ci *output_pointer = 'f'; 12429750e409Sopenharmony_ci break; 12439750e409Sopenharmony_ci case '\n': 12449750e409Sopenharmony_ci *output_pointer = 'n'; 12459750e409Sopenharmony_ci break; 12469750e409Sopenharmony_ci case '\r': 12479750e409Sopenharmony_ci *output_pointer = 'r'; 12489750e409Sopenharmony_ci break; 12499750e409Sopenharmony_ci case '\t': 12509750e409Sopenharmony_ci *output_pointer = 't'; 12519750e409Sopenharmony_ci break; 12529750e409Sopenharmony_ci default: 12539750e409Sopenharmony_ci /* escape and print as unicode codepoint */ 12549750e409Sopenharmony_ci sprintf((char*)output_pointer, "u%04x", *input_pointer); 12559750e409Sopenharmony_ci output_pointer += 4; 12569750e409Sopenharmony_ci break; 12579750e409Sopenharmony_ci } 12589750e409Sopenharmony_ci } 12599750e409Sopenharmony_ci } 12609750e409Sopenharmony_ci output[output_length + 1] = '\"'; 12619750e409Sopenharmony_ci output[output_length + 2] = '\0'; 12629750e409Sopenharmony_ci 12639750e409Sopenharmony_ci return true; 12649750e409Sopenharmony_ci} 12659750e409Sopenharmony_ci 12669750e409Sopenharmony_ci/* Invoke print_string_ptr (which is useful) on an item. */ 12679750e409Sopenharmony_cistatic cJSON_bool print_string(const cJSON * const item, printbuffer * const p) 12689750e409Sopenharmony_ci{ 12699750e409Sopenharmony_ci return print_string_ptr((unsigned char*)item->valuestring, p); 12709750e409Sopenharmony_ci} 12719750e409Sopenharmony_ci 12729750e409Sopenharmony_ci/* Predeclare these prototypes. */ 12739750e409Sopenharmony_cistatic cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); 12749750e409Sopenharmony_cistatic cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); 12759750e409Sopenharmony_cistatic cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); 12769750e409Sopenharmony_cistatic cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); 12779750e409Sopenharmony_cistatic cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); 12789750e409Sopenharmony_cistatic cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); 12799750e409Sopenharmony_ci 12809750e409Sopenharmony_ci/* Utility to jump whitespace and cr/lf */ 12819750e409Sopenharmony_cistatic parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) 12829750e409Sopenharmony_ci{ 12839750e409Sopenharmony_ci if ((buffer == NULL) || (buffer->content == NULL)) 12849750e409Sopenharmony_ci { 12859750e409Sopenharmony_ci return NULL; 12869750e409Sopenharmony_ci } 12879750e409Sopenharmony_ci 12889750e409Sopenharmony_ci if (cannot_access_at_index(buffer, 0)) 12899750e409Sopenharmony_ci { 12909750e409Sopenharmony_ci return buffer; 12919750e409Sopenharmony_ci } 12929750e409Sopenharmony_ci 12939750e409Sopenharmony_ci while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) 12949750e409Sopenharmony_ci { 12959750e409Sopenharmony_ci buffer->offset++; 12969750e409Sopenharmony_ci } 12979750e409Sopenharmony_ci 12989750e409Sopenharmony_ci if (buffer->offset == buffer->length) 12999750e409Sopenharmony_ci { 13009750e409Sopenharmony_ci buffer->offset--; 13019750e409Sopenharmony_ci } 13029750e409Sopenharmony_ci 13039750e409Sopenharmony_ci return buffer; 13049750e409Sopenharmony_ci} 13059750e409Sopenharmony_ci 13069750e409Sopenharmony_ci/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ 13079750e409Sopenharmony_cistatic parse_buffer *skip_utf8_bom(parse_buffer * const buffer) 13089750e409Sopenharmony_ci{ 13099750e409Sopenharmony_ci if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) 13109750e409Sopenharmony_ci { 13119750e409Sopenharmony_ci return NULL; 13129750e409Sopenharmony_ci } 13139750e409Sopenharmony_ci 13149750e409Sopenharmony_ci if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) 13159750e409Sopenharmony_ci { 13169750e409Sopenharmony_ci buffer->offset += 3; 13179750e409Sopenharmony_ci } 13189750e409Sopenharmony_ci 13199750e409Sopenharmony_ci return buffer; 13209750e409Sopenharmony_ci} 13219750e409Sopenharmony_ci 13229750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) 13239750e409Sopenharmony_ci{ 13249750e409Sopenharmony_ci size_t buffer_length; 13259750e409Sopenharmony_ci 13269750e409Sopenharmony_ci if (NULL == value) 13279750e409Sopenharmony_ci { 13289750e409Sopenharmony_ci return NULL; 13299750e409Sopenharmony_ci } 13309750e409Sopenharmony_ci 13319750e409Sopenharmony_ci /* Adding null character size due to require_null_terminated. */ 13329750e409Sopenharmony_ci buffer_length = strlen(value) + sizeof(""); 13339750e409Sopenharmony_ci 13349750e409Sopenharmony_ci return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); 13359750e409Sopenharmony_ci} 13369750e409Sopenharmony_ci 13379750e409Sopenharmony_ci/* Parse an object - create a new root, and populate. */ 13389750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) 13399750e409Sopenharmony_ci{ 13409750e409Sopenharmony_ci parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; 13419750e409Sopenharmony_ci cJSON *item = NULL; 13429750e409Sopenharmony_ci 13439750e409Sopenharmony_ci /* reset error position */ 13449750e409Sopenharmony_ci global_error.json = NULL; 13459750e409Sopenharmony_ci global_error.position = 0; 13469750e409Sopenharmony_ci 13479750e409Sopenharmony_ci if (value == NULL || 0 == buffer_length) 13489750e409Sopenharmony_ci { 13499750e409Sopenharmony_ci goto fail; 13509750e409Sopenharmony_ci } 13519750e409Sopenharmony_ci 13529750e409Sopenharmony_ci buffer.content = (const unsigned char*)value; 13539750e409Sopenharmony_ci buffer.length = buffer_length; 13549750e409Sopenharmony_ci buffer.offset = 0; 13559750e409Sopenharmony_ci buffer.hooks = global_hooks; 13569750e409Sopenharmony_ci 13579750e409Sopenharmony_ci item = cJSON_New_Item(&global_hooks); 13589750e409Sopenharmony_ci if (item == NULL) /* memory fail */ 13599750e409Sopenharmony_ci { 13609750e409Sopenharmony_ci goto fail; 13619750e409Sopenharmony_ci } 13629750e409Sopenharmony_ci 13639750e409Sopenharmony_ci if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) 13649750e409Sopenharmony_ci { 13659750e409Sopenharmony_ci /* parse failure. ep is set. */ 13669750e409Sopenharmony_ci goto fail; 13679750e409Sopenharmony_ci } 13689750e409Sopenharmony_ci 13699750e409Sopenharmony_ci /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ 13709750e409Sopenharmony_ci if (require_null_terminated) 13719750e409Sopenharmony_ci { 13729750e409Sopenharmony_ci buffer_skip_whitespace(&buffer); 13739750e409Sopenharmony_ci if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') 13749750e409Sopenharmony_ci { 13759750e409Sopenharmony_ci goto fail; 13769750e409Sopenharmony_ci } 13779750e409Sopenharmony_ci } 13789750e409Sopenharmony_ci if (return_parse_end) 13799750e409Sopenharmony_ci { 13809750e409Sopenharmony_ci *return_parse_end = (const char*)buffer_at_offset(&buffer); 13819750e409Sopenharmony_ci } 13829750e409Sopenharmony_ci 13839750e409Sopenharmony_ci return item; 13849750e409Sopenharmony_ci 13859750e409Sopenharmony_cifail: 13869750e409Sopenharmony_ci if (item != NULL) 13879750e409Sopenharmony_ci { 13889750e409Sopenharmony_ci cJSON_Delete(item); 13899750e409Sopenharmony_ci } 13909750e409Sopenharmony_ci 13919750e409Sopenharmony_ci if (value != NULL) 13929750e409Sopenharmony_ci { 13939750e409Sopenharmony_ci error local_error; 13949750e409Sopenharmony_ci local_error.json = (const unsigned char*)value; 13959750e409Sopenharmony_ci local_error.position = 0; 13969750e409Sopenharmony_ci 13979750e409Sopenharmony_ci if (buffer.offset < buffer.length) 13989750e409Sopenharmony_ci { 13999750e409Sopenharmony_ci local_error.position = buffer.offset; 14009750e409Sopenharmony_ci } 14019750e409Sopenharmony_ci else if (buffer.length > 0) 14029750e409Sopenharmony_ci { 14039750e409Sopenharmony_ci local_error.position = buffer.length - 1; 14049750e409Sopenharmony_ci } 14059750e409Sopenharmony_ci 14069750e409Sopenharmony_ci if (return_parse_end != NULL) 14079750e409Sopenharmony_ci { 14089750e409Sopenharmony_ci *return_parse_end = (const char*)local_error.json + local_error.position; 14099750e409Sopenharmony_ci } 14109750e409Sopenharmony_ci 14119750e409Sopenharmony_ci global_error = local_error; 14129750e409Sopenharmony_ci } 14139750e409Sopenharmony_ci 14149750e409Sopenharmony_ci return NULL; 14159750e409Sopenharmony_ci} 14169750e409Sopenharmony_ci 14179750e409Sopenharmony_ci/* Default options for cJSON_Parse */ 14189750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) 14199750e409Sopenharmony_ci{ 14209750e409Sopenharmony_ci return cJSON_ParseWithOpts(value, 0, 0); 14219750e409Sopenharmony_ci} 14229750e409Sopenharmony_ci 14239750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) 14249750e409Sopenharmony_ci{ 14259750e409Sopenharmony_ci return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); 14269750e409Sopenharmony_ci} 14279750e409Sopenharmony_ci 14289750e409Sopenharmony_ci#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) 14299750e409Sopenharmony_ci 14309750e409Sopenharmony_cistatic unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) 14319750e409Sopenharmony_ci{ 14329750e409Sopenharmony_ci static const size_t default_buffer_size = 256; 14339750e409Sopenharmony_ci printbuffer buffer[1]; 14349750e409Sopenharmony_ci unsigned char *printed = NULL; 14359750e409Sopenharmony_ci 14369750e409Sopenharmony_ci memset(buffer, 0, sizeof(buffer)); 14379750e409Sopenharmony_ci 14389750e409Sopenharmony_ci /* create buffer */ 14399750e409Sopenharmony_ci buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); 14409750e409Sopenharmony_ci buffer->length = default_buffer_size; 14419750e409Sopenharmony_ci buffer->format = format; 14429750e409Sopenharmony_ci buffer->hooks = *hooks; 14439750e409Sopenharmony_ci if (buffer->buffer == NULL) 14449750e409Sopenharmony_ci { 14459750e409Sopenharmony_ci goto fail; 14469750e409Sopenharmony_ci } 14479750e409Sopenharmony_ci 14489750e409Sopenharmony_ci /* print the value */ 14499750e409Sopenharmony_ci if (!print_value(item, buffer)) 14509750e409Sopenharmony_ci { 14519750e409Sopenharmony_ci goto fail; 14529750e409Sopenharmony_ci } 14539750e409Sopenharmony_ci update_offset(buffer); 14549750e409Sopenharmony_ci 14559750e409Sopenharmony_ci /* check if reallocate is available */ 14569750e409Sopenharmony_ci if (hooks->reallocate != NULL) 14579750e409Sopenharmony_ci { 14589750e409Sopenharmony_ci printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); 14599750e409Sopenharmony_ci if (printed == NULL) { 14609750e409Sopenharmony_ci goto fail; 14619750e409Sopenharmony_ci } 14629750e409Sopenharmony_ci buffer->buffer = NULL; 14639750e409Sopenharmony_ci } 14649750e409Sopenharmony_ci else /* otherwise copy the JSON over to a new buffer */ 14659750e409Sopenharmony_ci { 14669750e409Sopenharmony_ci printed = (unsigned char*) hooks->allocate(buffer->offset + 1); 14679750e409Sopenharmony_ci if (printed == NULL) 14689750e409Sopenharmony_ci { 14699750e409Sopenharmony_ci goto fail; 14709750e409Sopenharmony_ci } 14719750e409Sopenharmony_ci memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); 14729750e409Sopenharmony_ci printed[buffer->offset] = '\0'; /* just to be sure */ 14739750e409Sopenharmony_ci 14749750e409Sopenharmony_ci /* free the buffer */ 14759750e409Sopenharmony_ci hooks->deallocate(buffer->buffer); 14769750e409Sopenharmony_ci } 14779750e409Sopenharmony_ci 14789750e409Sopenharmony_ci return printed; 14799750e409Sopenharmony_ci 14809750e409Sopenharmony_cifail: 14819750e409Sopenharmony_ci if (buffer->buffer != NULL) 14829750e409Sopenharmony_ci { 14839750e409Sopenharmony_ci hooks->deallocate(buffer->buffer); 14849750e409Sopenharmony_ci } 14859750e409Sopenharmony_ci 14869750e409Sopenharmony_ci if (printed != NULL) 14879750e409Sopenharmony_ci { 14889750e409Sopenharmony_ci hooks->deallocate(printed); 14899750e409Sopenharmony_ci } 14909750e409Sopenharmony_ci 14919750e409Sopenharmony_ci return NULL; 14929750e409Sopenharmony_ci} 14939750e409Sopenharmony_ci 14949750e409Sopenharmony_ci/* Render a cJSON item/entity/structure to text. */ 14959750e409Sopenharmony_ciCJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) 14969750e409Sopenharmony_ci{ 14979750e409Sopenharmony_ci return (char*)print(item, true, &global_hooks); 14989750e409Sopenharmony_ci} 14999750e409Sopenharmony_ci 15009750e409Sopenharmony_ciCJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) 15019750e409Sopenharmony_ci{ 15029750e409Sopenharmony_ci return (char*)print(item, false, &global_hooks); 15039750e409Sopenharmony_ci} 15049750e409Sopenharmony_ci 15059750e409Sopenharmony_ciCJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) 15069750e409Sopenharmony_ci{ 15079750e409Sopenharmony_ci printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; 15089750e409Sopenharmony_ci 15099750e409Sopenharmony_ci if (prebuffer < 0) 15109750e409Sopenharmony_ci { 15119750e409Sopenharmony_ci return NULL; 15129750e409Sopenharmony_ci } 15139750e409Sopenharmony_ci 15149750e409Sopenharmony_ci p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); 15159750e409Sopenharmony_ci if (!p.buffer) 15169750e409Sopenharmony_ci { 15179750e409Sopenharmony_ci return NULL; 15189750e409Sopenharmony_ci } 15199750e409Sopenharmony_ci 15209750e409Sopenharmony_ci p.length = (size_t)prebuffer; 15219750e409Sopenharmony_ci p.offset = 0; 15229750e409Sopenharmony_ci p.noalloc = false; 15239750e409Sopenharmony_ci p.format = fmt; 15249750e409Sopenharmony_ci p.hooks = global_hooks; 15259750e409Sopenharmony_ci 15269750e409Sopenharmony_ci if (!print_value(item, &p)) 15279750e409Sopenharmony_ci { 15289750e409Sopenharmony_ci global_hooks.deallocate(p.buffer); 15299750e409Sopenharmony_ci return NULL; 15309750e409Sopenharmony_ci } 15319750e409Sopenharmony_ci 15329750e409Sopenharmony_ci return (char*)p.buffer; 15339750e409Sopenharmony_ci} 15349750e409Sopenharmony_ci 15359750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) 15369750e409Sopenharmony_ci{ 15379750e409Sopenharmony_ci printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; 15389750e409Sopenharmony_ci 15399750e409Sopenharmony_ci if ((length < 0) || (buffer == NULL)) 15409750e409Sopenharmony_ci { 15419750e409Sopenharmony_ci return false; 15429750e409Sopenharmony_ci } 15439750e409Sopenharmony_ci 15449750e409Sopenharmony_ci p.buffer = (unsigned char*)buffer; 15459750e409Sopenharmony_ci p.length = (size_t)length; 15469750e409Sopenharmony_ci p.offset = 0; 15479750e409Sopenharmony_ci p.noalloc = true; 15489750e409Sopenharmony_ci p.format = format; 15499750e409Sopenharmony_ci p.hooks = global_hooks; 15509750e409Sopenharmony_ci 15519750e409Sopenharmony_ci return print_value(item, &p); 15529750e409Sopenharmony_ci} 15539750e409Sopenharmony_ci 15549750e409Sopenharmony_ci/* Parser core - when encountering text, process appropriately. */ 15559750e409Sopenharmony_cistatic cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) 15569750e409Sopenharmony_ci{ 15579750e409Sopenharmony_ci if ((input_buffer == NULL) || (input_buffer->content == NULL)) 15589750e409Sopenharmony_ci { 15599750e409Sopenharmony_ci return false; /* no input */ 15609750e409Sopenharmony_ci } 15619750e409Sopenharmony_ci 15629750e409Sopenharmony_ci /* parse the different types of values */ 15639750e409Sopenharmony_ci /* null */ 15649750e409Sopenharmony_ci if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) 15659750e409Sopenharmony_ci { 15669750e409Sopenharmony_ci item->type = cJSON_NULL; 15679750e409Sopenharmony_ci input_buffer->offset += 4; 15689750e409Sopenharmony_ci return true; 15699750e409Sopenharmony_ci } 15709750e409Sopenharmony_ci /* false */ 15719750e409Sopenharmony_ci if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) 15729750e409Sopenharmony_ci { 15739750e409Sopenharmony_ci item->type = cJSON_False; 15749750e409Sopenharmony_ci input_buffer->offset += 5; 15759750e409Sopenharmony_ci return true; 15769750e409Sopenharmony_ci } 15779750e409Sopenharmony_ci /* true */ 15789750e409Sopenharmony_ci if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) 15799750e409Sopenharmony_ci { 15809750e409Sopenharmony_ci item->type = cJSON_True; 15819750e409Sopenharmony_ci item->valueint = 1; 15829750e409Sopenharmony_ci input_buffer->offset += 4; 15839750e409Sopenharmony_ci return true; 15849750e409Sopenharmony_ci } 15859750e409Sopenharmony_ci /* string */ 15869750e409Sopenharmony_ci if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) 15879750e409Sopenharmony_ci { 15889750e409Sopenharmony_ci return parse_string(item, input_buffer); 15899750e409Sopenharmony_ci } 15909750e409Sopenharmony_ci /* number */ 15919750e409Sopenharmony_ci 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')))) 15929750e409Sopenharmony_ci { 15939750e409Sopenharmony_ci return parse_number(item, input_buffer); 15949750e409Sopenharmony_ci } 15959750e409Sopenharmony_ci /* array */ 15969750e409Sopenharmony_ci if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) 15979750e409Sopenharmony_ci { 15989750e409Sopenharmony_ci return parse_array(item, input_buffer); 15999750e409Sopenharmony_ci } 16009750e409Sopenharmony_ci /* object */ 16019750e409Sopenharmony_ci if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) 16029750e409Sopenharmony_ci { 16039750e409Sopenharmony_ci return parse_object(item, input_buffer); 16049750e409Sopenharmony_ci } 16059750e409Sopenharmony_ci 16069750e409Sopenharmony_ci return false; 16079750e409Sopenharmony_ci} 16089750e409Sopenharmony_ci 16099750e409Sopenharmony_ci/* Render a value to text. */ 16109750e409Sopenharmony_cistatic cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) 16119750e409Sopenharmony_ci{ 16129750e409Sopenharmony_ci unsigned char *output = NULL; 16139750e409Sopenharmony_ci 16149750e409Sopenharmony_ci if ((item == NULL) || (output_buffer == NULL)) 16159750e409Sopenharmony_ci { 16169750e409Sopenharmony_ci return false; 16179750e409Sopenharmony_ci } 16189750e409Sopenharmony_ci 16199750e409Sopenharmony_ci switch ((item->type) & 0xFF) 16209750e409Sopenharmony_ci { 16219750e409Sopenharmony_ci case cJSON_NULL: 16229750e409Sopenharmony_ci output = ensure(output_buffer, 5); 16239750e409Sopenharmony_ci if (output == NULL) 16249750e409Sopenharmony_ci { 16259750e409Sopenharmony_ci return false; 16269750e409Sopenharmony_ci } 16279750e409Sopenharmony_ci strcpy((char*)output, "null"); 16289750e409Sopenharmony_ci return true; 16299750e409Sopenharmony_ci 16309750e409Sopenharmony_ci case cJSON_False: 16319750e409Sopenharmony_ci output = ensure(output_buffer, 6); 16329750e409Sopenharmony_ci if (output == NULL) 16339750e409Sopenharmony_ci { 16349750e409Sopenharmony_ci return false; 16359750e409Sopenharmony_ci } 16369750e409Sopenharmony_ci strcpy((char*)output, "false"); 16379750e409Sopenharmony_ci return true; 16389750e409Sopenharmony_ci 16399750e409Sopenharmony_ci case cJSON_True: 16409750e409Sopenharmony_ci output = ensure(output_buffer, 5); 16419750e409Sopenharmony_ci if (output == NULL) 16429750e409Sopenharmony_ci { 16439750e409Sopenharmony_ci return false; 16449750e409Sopenharmony_ci } 16459750e409Sopenharmony_ci strcpy((char*)output, "true"); 16469750e409Sopenharmony_ci return true; 16479750e409Sopenharmony_ci 16489750e409Sopenharmony_ci case cJSON_Number: 16499750e409Sopenharmony_ci return print_number(item, output_buffer); 16509750e409Sopenharmony_ci 16519750e409Sopenharmony_ci case cJSON_Raw: 16529750e409Sopenharmony_ci { 16539750e409Sopenharmony_ci size_t raw_length = 0; 16549750e409Sopenharmony_ci if (item->valuestring == NULL) 16559750e409Sopenharmony_ci { 16569750e409Sopenharmony_ci return false; 16579750e409Sopenharmony_ci } 16589750e409Sopenharmony_ci 16599750e409Sopenharmony_ci raw_length = strlen(item->valuestring) + sizeof(""); 16609750e409Sopenharmony_ci output = ensure(output_buffer, raw_length); 16619750e409Sopenharmony_ci if (output == NULL) 16629750e409Sopenharmony_ci { 16639750e409Sopenharmony_ci return false; 16649750e409Sopenharmony_ci } 16659750e409Sopenharmony_ci memcpy(output, item->valuestring, raw_length); 16669750e409Sopenharmony_ci return true; 16679750e409Sopenharmony_ci } 16689750e409Sopenharmony_ci 16699750e409Sopenharmony_ci case cJSON_String: 16709750e409Sopenharmony_ci return print_string(item, output_buffer); 16719750e409Sopenharmony_ci 16729750e409Sopenharmony_ci case cJSON_Array: 16739750e409Sopenharmony_ci return print_array(item, output_buffer); 16749750e409Sopenharmony_ci 16759750e409Sopenharmony_ci case cJSON_Object: 16769750e409Sopenharmony_ci return print_object(item, output_buffer); 16779750e409Sopenharmony_ci 16789750e409Sopenharmony_ci default: 16799750e409Sopenharmony_ci return false; 16809750e409Sopenharmony_ci } 16819750e409Sopenharmony_ci} 16829750e409Sopenharmony_ci 16839750e409Sopenharmony_ci/* Build an array from input text. */ 16849750e409Sopenharmony_cistatic cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) 16859750e409Sopenharmony_ci{ 16869750e409Sopenharmony_ci cJSON *head = NULL; /* head of the linked list */ 16879750e409Sopenharmony_ci cJSON *current_item = NULL; 16889750e409Sopenharmony_ci 16899750e409Sopenharmony_ci if (input_buffer->depth >= CJSON_NESTING_LIMIT) 16909750e409Sopenharmony_ci { 16919750e409Sopenharmony_ci return false; /* to deeply nested */ 16929750e409Sopenharmony_ci } 16939750e409Sopenharmony_ci input_buffer->depth++; 16949750e409Sopenharmony_ci 16959750e409Sopenharmony_ci if (buffer_at_offset(input_buffer)[0] != '[') 16969750e409Sopenharmony_ci { 16979750e409Sopenharmony_ci /* not an array */ 16989750e409Sopenharmony_ci goto fail; 16999750e409Sopenharmony_ci } 17009750e409Sopenharmony_ci 17019750e409Sopenharmony_ci input_buffer->offset++; 17029750e409Sopenharmony_ci buffer_skip_whitespace(input_buffer); 17039750e409Sopenharmony_ci if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) 17049750e409Sopenharmony_ci { 17059750e409Sopenharmony_ci /* empty array */ 17069750e409Sopenharmony_ci goto success; 17079750e409Sopenharmony_ci } 17089750e409Sopenharmony_ci 17099750e409Sopenharmony_ci /* check if we skipped to the end of the buffer */ 17109750e409Sopenharmony_ci if (cannot_access_at_index(input_buffer, 0)) 17119750e409Sopenharmony_ci { 17129750e409Sopenharmony_ci input_buffer->offset--; 17139750e409Sopenharmony_ci goto fail; 17149750e409Sopenharmony_ci } 17159750e409Sopenharmony_ci 17169750e409Sopenharmony_ci /* step back to character in front of the first element */ 17179750e409Sopenharmony_ci input_buffer->offset--; 17189750e409Sopenharmony_ci /* loop through the comma separated array elements */ 17199750e409Sopenharmony_ci do 17209750e409Sopenharmony_ci { 17219750e409Sopenharmony_ci /* allocate next item */ 17229750e409Sopenharmony_ci cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); 17239750e409Sopenharmony_ci if (new_item == NULL) 17249750e409Sopenharmony_ci { 17259750e409Sopenharmony_ci goto fail; /* allocation failure */ 17269750e409Sopenharmony_ci } 17279750e409Sopenharmony_ci 17289750e409Sopenharmony_ci /* attach next item to list */ 17299750e409Sopenharmony_ci if (head == NULL) 17309750e409Sopenharmony_ci { 17319750e409Sopenharmony_ci /* start the linked list */ 17329750e409Sopenharmony_ci current_item = head = new_item; 17339750e409Sopenharmony_ci } 17349750e409Sopenharmony_ci else 17359750e409Sopenharmony_ci { 17369750e409Sopenharmony_ci /* add to the end and advance */ 17379750e409Sopenharmony_ci current_item->next = new_item; 17389750e409Sopenharmony_ci new_item->prev = current_item; 17399750e409Sopenharmony_ci current_item = new_item; 17409750e409Sopenharmony_ci } 17419750e409Sopenharmony_ci 17429750e409Sopenharmony_ci /* parse next value */ 17439750e409Sopenharmony_ci input_buffer->offset++; 17449750e409Sopenharmony_ci buffer_skip_whitespace(input_buffer); 17459750e409Sopenharmony_ci if (!parse_value(current_item, input_buffer)) 17469750e409Sopenharmony_ci { 17479750e409Sopenharmony_ci goto fail; /* failed to parse value */ 17489750e409Sopenharmony_ci } 17499750e409Sopenharmony_ci buffer_skip_whitespace(input_buffer); 17509750e409Sopenharmony_ci } 17519750e409Sopenharmony_ci while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); 17529750e409Sopenharmony_ci 17539750e409Sopenharmony_ci if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') 17549750e409Sopenharmony_ci { 17559750e409Sopenharmony_ci goto fail; /* expected end of array */ 17569750e409Sopenharmony_ci } 17579750e409Sopenharmony_ci 17589750e409Sopenharmony_cisuccess: 17599750e409Sopenharmony_ci input_buffer->depth--; 17609750e409Sopenharmony_ci 17619750e409Sopenharmony_ci if (head != NULL) { 17629750e409Sopenharmony_ci head->prev = current_item; 17639750e409Sopenharmony_ci } 17649750e409Sopenharmony_ci 17659750e409Sopenharmony_ci item->type = cJSON_Array; 17669750e409Sopenharmony_ci item->child = head; 17679750e409Sopenharmony_ci 17689750e409Sopenharmony_ci input_buffer->offset++; 17699750e409Sopenharmony_ci 17709750e409Sopenharmony_ci return true; 17719750e409Sopenharmony_ci 17729750e409Sopenharmony_cifail: 17739750e409Sopenharmony_ci if (head != NULL) 17749750e409Sopenharmony_ci { 17759750e409Sopenharmony_ci cJSON_Delete(head); 17769750e409Sopenharmony_ci } 17779750e409Sopenharmony_ci 17789750e409Sopenharmony_ci return false; 17799750e409Sopenharmony_ci} 17809750e409Sopenharmony_ci 17819750e409Sopenharmony_ci/* Render an array to text */ 17829750e409Sopenharmony_cistatic cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) 17839750e409Sopenharmony_ci{ 17849750e409Sopenharmony_ci unsigned char *output_pointer = NULL; 17859750e409Sopenharmony_ci size_t length = 0; 17869750e409Sopenharmony_ci cJSON *current_element = item->child; 17879750e409Sopenharmony_ci 17889750e409Sopenharmony_ci if (output_buffer == NULL) 17899750e409Sopenharmony_ci { 17909750e409Sopenharmony_ci return false; 17919750e409Sopenharmony_ci } 17929750e409Sopenharmony_ci 17939750e409Sopenharmony_ci /* Compose the output array. */ 17949750e409Sopenharmony_ci /* opening square bracket */ 17959750e409Sopenharmony_ci output_pointer = ensure(output_buffer, 1); 17969750e409Sopenharmony_ci if (output_pointer == NULL) 17979750e409Sopenharmony_ci { 17989750e409Sopenharmony_ci return false; 17999750e409Sopenharmony_ci } 18009750e409Sopenharmony_ci 18019750e409Sopenharmony_ci *output_pointer = '['; 18029750e409Sopenharmony_ci output_buffer->offset++; 18039750e409Sopenharmony_ci output_buffer->depth++; 18049750e409Sopenharmony_ci 18059750e409Sopenharmony_ci while (current_element != NULL) 18069750e409Sopenharmony_ci { 18079750e409Sopenharmony_ci if (!print_value(current_element, output_buffer)) 18089750e409Sopenharmony_ci { 18099750e409Sopenharmony_ci return false; 18109750e409Sopenharmony_ci } 18119750e409Sopenharmony_ci update_offset(output_buffer); 18129750e409Sopenharmony_ci if (current_element->next) 18139750e409Sopenharmony_ci { 18149750e409Sopenharmony_ci length = (size_t) (output_buffer->format ? 2 : 1); 18159750e409Sopenharmony_ci output_pointer = ensure(output_buffer, length + 1); 18169750e409Sopenharmony_ci if (output_pointer == NULL) 18179750e409Sopenharmony_ci { 18189750e409Sopenharmony_ci return false; 18199750e409Sopenharmony_ci } 18209750e409Sopenharmony_ci *output_pointer++ = ','; 18219750e409Sopenharmony_ci if(output_buffer->format) 18229750e409Sopenharmony_ci { 18239750e409Sopenharmony_ci *output_pointer++ = ' '; 18249750e409Sopenharmony_ci } 18259750e409Sopenharmony_ci *output_pointer = '\0'; 18269750e409Sopenharmony_ci output_buffer->offset += length; 18279750e409Sopenharmony_ci } 18289750e409Sopenharmony_ci current_element = current_element->next; 18299750e409Sopenharmony_ci } 18309750e409Sopenharmony_ci 18319750e409Sopenharmony_ci output_pointer = ensure(output_buffer, 2); 18329750e409Sopenharmony_ci if (output_pointer == NULL) 18339750e409Sopenharmony_ci { 18349750e409Sopenharmony_ci return false; 18359750e409Sopenharmony_ci } 18369750e409Sopenharmony_ci *output_pointer++ = ']'; 18379750e409Sopenharmony_ci *output_pointer = '\0'; 18389750e409Sopenharmony_ci output_buffer->depth--; 18399750e409Sopenharmony_ci 18409750e409Sopenharmony_ci return true; 18419750e409Sopenharmony_ci} 18429750e409Sopenharmony_ci 18439750e409Sopenharmony_ci/* Build an object from the text. */ 18449750e409Sopenharmony_cistatic cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) 18459750e409Sopenharmony_ci{ 18469750e409Sopenharmony_ci cJSON *head = NULL; /* linked list head */ 18479750e409Sopenharmony_ci cJSON *current_item = NULL; 18489750e409Sopenharmony_ci 18499750e409Sopenharmony_ci if (input_buffer->depth >= CJSON_NESTING_LIMIT) 18509750e409Sopenharmony_ci { 18519750e409Sopenharmony_ci return false; /* to deeply nested */ 18529750e409Sopenharmony_ci } 18539750e409Sopenharmony_ci input_buffer->depth++; 18549750e409Sopenharmony_ci 18559750e409Sopenharmony_ci if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) 18569750e409Sopenharmony_ci { 18579750e409Sopenharmony_ci goto fail; /* not an object */ 18589750e409Sopenharmony_ci } 18599750e409Sopenharmony_ci 18609750e409Sopenharmony_ci input_buffer->offset++; 18619750e409Sopenharmony_ci buffer_skip_whitespace(input_buffer); 18629750e409Sopenharmony_ci if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) 18639750e409Sopenharmony_ci { 18649750e409Sopenharmony_ci goto success; /* empty object */ 18659750e409Sopenharmony_ci } 18669750e409Sopenharmony_ci 18679750e409Sopenharmony_ci /* check if we skipped to the end of the buffer */ 18689750e409Sopenharmony_ci if (cannot_access_at_index(input_buffer, 0)) 18699750e409Sopenharmony_ci { 18709750e409Sopenharmony_ci input_buffer->offset--; 18719750e409Sopenharmony_ci goto fail; 18729750e409Sopenharmony_ci } 18739750e409Sopenharmony_ci 18749750e409Sopenharmony_ci /* step back to character in front of the first element */ 18759750e409Sopenharmony_ci input_buffer->offset--; 18769750e409Sopenharmony_ci /* loop through the comma separated array elements */ 18779750e409Sopenharmony_ci do 18789750e409Sopenharmony_ci { 18799750e409Sopenharmony_ci /* allocate next item */ 18809750e409Sopenharmony_ci cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); 18819750e409Sopenharmony_ci if (new_item == NULL) 18829750e409Sopenharmony_ci { 18839750e409Sopenharmony_ci goto fail; /* allocation failure */ 18849750e409Sopenharmony_ci } 18859750e409Sopenharmony_ci 18869750e409Sopenharmony_ci /* attach next item to list */ 18879750e409Sopenharmony_ci if (head == NULL) 18889750e409Sopenharmony_ci { 18899750e409Sopenharmony_ci /* start the linked list */ 18909750e409Sopenharmony_ci current_item = head = new_item; 18919750e409Sopenharmony_ci } 18929750e409Sopenharmony_ci else 18939750e409Sopenharmony_ci { 18949750e409Sopenharmony_ci /* add to the end and advance */ 18959750e409Sopenharmony_ci current_item->next = new_item; 18969750e409Sopenharmony_ci new_item->prev = current_item; 18979750e409Sopenharmony_ci current_item = new_item; 18989750e409Sopenharmony_ci } 18999750e409Sopenharmony_ci 19009750e409Sopenharmony_ci if (cannot_access_at_index(input_buffer, 1)) 19019750e409Sopenharmony_ci { 19029750e409Sopenharmony_ci goto fail; /* nothing comes after the comma */ 19039750e409Sopenharmony_ci } 19049750e409Sopenharmony_ci 19059750e409Sopenharmony_ci /* parse the name of the child */ 19069750e409Sopenharmony_ci input_buffer->offset++; 19079750e409Sopenharmony_ci buffer_skip_whitespace(input_buffer); 19089750e409Sopenharmony_ci if (!parse_string(current_item, input_buffer)) 19099750e409Sopenharmony_ci { 19109750e409Sopenharmony_ci goto fail; /* failed to parse name */ 19119750e409Sopenharmony_ci } 19129750e409Sopenharmony_ci buffer_skip_whitespace(input_buffer); 19139750e409Sopenharmony_ci 19149750e409Sopenharmony_ci /* swap valuestring and string, because we parsed the name */ 19159750e409Sopenharmony_ci current_item->string = current_item->valuestring; 19169750e409Sopenharmony_ci current_item->valuestring = NULL; 19179750e409Sopenharmony_ci 19189750e409Sopenharmony_ci if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) 19199750e409Sopenharmony_ci { 19209750e409Sopenharmony_ci goto fail; /* invalid object */ 19219750e409Sopenharmony_ci } 19229750e409Sopenharmony_ci 19239750e409Sopenharmony_ci /* parse the value */ 19249750e409Sopenharmony_ci input_buffer->offset++; 19259750e409Sopenharmony_ci buffer_skip_whitespace(input_buffer); 19269750e409Sopenharmony_ci if (!parse_value(current_item, input_buffer)) 19279750e409Sopenharmony_ci { 19289750e409Sopenharmony_ci goto fail; /* failed to parse value */ 19299750e409Sopenharmony_ci } 19309750e409Sopenharmony_ci buffer_skip_whitespace(input_buffer); 19319750e409Sopenharmony_ci } 19329750e409Sopenharmony_ci while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); 19339750e409Sopenharmony_ci 19349750e409Sopenharmony_ci if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) 19359750e409Sopenharmony_ci { 19369750e409Sopenharmony_ci goto fail; /* expected end of object */ 19379750e409Sopenharmony_ci } 19389750e409Sopenharmony_ci 19399750e409Sopenharmony_cisuccess: 19409750e409Sopenharmony_ci input_buffer->depth--; 19419750e409Sopenharmony_ci 19429750e409Sopenharmony_ci if (head != NULL) { 19439750e409Sopenharmony_ci head->prev = current_item; 19449750e409Sopenharmony_ci } 19459750e409Sopenharmony_ci 19469750e409Sopenharmony_ci item->type = cJSON_Object; 19479750e409Sopenharmony_ci item->child = head; 19489750e409Sopenharmony_ci 19499750e409Sopenharmony_ci input_buffer->offset++; 19509750e409Sopenharmony_ci return true; 19519750e409Sopenharmony_ci 19529750e409Sopenharmony_cifail: 19539750e409Sopenharmony_ci if (head != NULL) 19549750e409Sopenharmony_ci { 19559750e409Sopenharmony_ci cJSON_Delete(head); 19569750e409Sopenharmony_ci } 19579750e409Sopenharmony_ci 19589750e409Sopenharmony_ci return false; 19599750e409Sopenharmony_ci} 19609750e409Sopenharmony_ci 19619750e409Sopenharmony_ci/* Render an object to text. */ 19629750e409Sopenharmony_cistatic cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) 19639750e409Sopenharmony_ci{ 19649750e409Sopenharmony_ci unsigned char *output_pointer = NULL; 19659750e409Sopenharmony_ci size_t length = 0; 19669750e409Sopenharmony_ci cJSON *current_item = item->child; 19679750e409Sopenharmony_ci 19689750e409Sopenharmony_ci if (output_buffer == NULL) 19699750e409Sopenharmony_ci { 19709750e409Sopenharmony_ci return false; 19719750e409Sopenharmony_ci } 19729750e409Sopenharmony_ci 19739750e409Sopenharmony_ci /* Compose the output: */ 19749750e409Sopenharmony_ci length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ 19759750e409Sopenharmony_ci output_pointer = ensure(output_buffer, length + 1); 19769750e409Sopenharmony_ci if (output_pointer == NULL) 19779750e409Sopenharmony_ci { 19789750e409Sopenharmony_ci return false; 19799750e409Sopenharmony_ci } 19809750e409Sopenharmony_ci 19819750e409Sopenharmony_ci *output_pointer++ = '{'; 19829750e409Sopenharmony_ci output_buffer->depth++; 19839750e409Sopenharmony_ci if (output_buffer->format) 19849750e409Sopenharmony_ci { 19859750e409Sopenharmony_ci *output_pointer++ = '\n'; 19869750e409Sopenharmony_ci } 19879750e409Sopenharmony_ci output_buffer->offset += length; 19889750e409Sopenharmony_ci 19899750e409Sopenharmony_ci while (current_item) 19909750e409Sopenharmony_ci { 19919750e409Sopenharmony_ci if (output_buffer->format) 19929750e409Sopenharmony_ci { 19939750e409Sopenharmony_ci size_t i; 19949750e409Sopenharmony_ci output_pointer = ensure(output_buffer, output_buffer->depth); 19959750e409Sopenharmony_ci if (output_pointer == NULL) 19969750e409Sopenharmony_ci { 19979750e409Sopenharmony_ci return false; 19989750e409Sopenharmony_ci } 19999750e409Sopenharmony_ci for (i = 0; i < output_buffer->depth; i++) 20009750e409Sopenharmony_ci { 20019750e409Sopenharmony_ci *output_pointer++ = '\t'; 20029750e409Sopenharmony_ci } 20039750e409Sopenharmony_ci output_buffer->offset += output_buffer->depth; 20049750e409Sopenharmony_ci } 20059750e409Sopenharmony_ci 20069750e409Sopenharmony_ci /* print key */ 20079750e409Sopenharmony_ci if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) 20089750e409Sopenharmony_ci { 20099750e409Sopenharmony_ci return false; 20109750e409Sopenharmony_ci } 20119750e409Sopenharmony_ci update_offset(output_buffer); 20129750e409Sopenharmony_ci 20139750e409Sopenharmony_ci length = (size_t) (output_buffer->format ? 2 : 1); 20149750e409Sopenharmony_ci output_pointer = ensure(output_buffer, length); 20159750e409Sopenharmony_ci if (output_pointer == NULL) 20169750e409Sopenharmony_ci { 20179750e409Sopenharmony_ci return false; 20189750e409Sopenharmony_ci } 20199750e409Sopenharmony_ci *output_pointer++ = ':'; 20209750e409Sopenharmony_ci if (output_buffer->format) 20219750e409Sopenharmony_ci { 20229750e409Sopenharmony_ci *output_pointer++ = '\t'; 20239750e409Sopenharmony_ci } 20249750e409Sopenharmony_ci output_buffer->offset += length; 20259750e409Sopenharmony_ci 20269750e409Sopenharmony_ci /* print value */ 20279750e409Sopenharmony_ci if (!print_value(current_item, output_buffer)) 20289750e409Sopenharmony_ci { 20299750e409Sopenharmony_ci return false; 20309750e409Sopenharmony_ci } 20319750e409Sopenharmony_ci update_offset(output_buffer); 20329750e409Sopenharmony_ci 20339750e409Sopenharmony_ci /* print comma if not last */ 20349750e409Sopenharmony_ci length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); 20359750e409Sopenharmony_ci output_pointer = ensure(output_buffer, length + 1); 20369750e409Sopenharmony_ci if (output_pointer == NULL) 20379750e409Sopenharmony_ci { 20389750e409Sopenharmony_ci return false; 20399750e409Sopenharmony_ci } 20409750e409Sopenharmony_ci if (current_item->next) 20419750e409Sopenharmony_ci { 20429750e409Sopenharmony_ci *output_pointer++ = ','; 20439750e409Sopenharmony_ci } 20449750e409Sopenharmony_ci 20459750e409Sopenharmony_ci if (output_buffer->format) 20469750e409Sopenharmony_ci { 20479750e409Sopenharmony_ci *output_pointer++ = '\n'; 20489750e409Sopenharmony_ci } 20499750e409Sopenharmony_ci *output_pointer = '\0'; 20509750e409Sopenharmony_ci output_buffer->offset += length; 20519750e409Sopenharmony_ci 20529750e409Sopenharmony_ci current_item = current_item->next; 20539750e409Sopenharmony_ci } 20549750e409Sopenharmony_ci 20559750e409Sopenharmony_ci output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); 20569750e409Sopenharmony_ci if (output_pointer == NULL) 20579750e409Sopenharmony_ci { 20589750e409Sopenharmony_ci return false; 20599750e409Sopenharmony_ci } 20609750e409Sopenharmony_ci if (output_buffer->format) 20619750e409Sopenharmony_ci { 20629750e409Sopenharmony_ci size_t i; 20639750e409Sopenharmony_ci for (i = 0; i < (output_buffer->depth - 1); i++) 20649750e409Sopenharmony_ci { 20659750e409Sopenharmony_ci *output_pointer++ = '\t'; 20669750e409Sopenharmony_ci } 20679750e409Sopenharmony_ci } 20689750e409Sopenharmony_ci *output_pointer++ = '}'; 20699750e409Sopenharmony_ci *output_pointer = '\0'; 20709750e409Sopenharmony_ci output_buffer->depth--; 20719750e409Sopenharmony_ci 20729750e409Sopenharmony_ci return true; 20739750e409Sopenharmony_ci} 20749750e409Sopenharmony_ci 20759750e409Sopenharmony_ci/* Get Array size/item / object item. */ 20769750e409Sopenharmony_ciCJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) 20779750e409Sopenharmony_ci{ 20789750e409Sopenharmony_ci cJSON *child = NULL; 20799750e409Sopenharmony_ci size_t size = 0; 20809750e409Sopenharmony_ci 20819750e409Sopenharmony_ci if (array == NULL) 20829750e409Sopenharmony_ci { 20839750e409Sopenharmony_ci return 0; 20849750e409Sopenharmony_ci } 20859750e409Sopenharmony_ci 20869750e409Sopenharmony_ci child = array->child; 20879750e409Sopenharmony_ci 20889750e409Sopenharmony_ci while(child != NULL) 20899750e409Sopenharmony_ci { 20909750e409Sopenharmony_ci size++; 20919750e409Sopenharmony_ci child = child->next; 20929750e409Sopenharmony_ci } 20939750e409Sopenharmony_ci 20949750e409Sopenharmony_ci /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ 20959750e409Sopenharmony_ci 20969750e409Sopenharmony_ci return (int)size; 20979750e409Sopenharmony_ci} 20989750e409Sopenharmony_ci 20999750e409Sopenharmony_cistatic cJSON* get_array_item(const cJSON *array, size_t index) 21009750e409Sopenharmony_ci{ 21019750e409Sopenharmony_ci cJSON *current_child = NULL; 21029750e409Sopenharmony_ci 21039750e409Sopenharmony_ci if (array == NULL) 21049750e409Sopenharmony_ci { 21059750e409Sopenharmony_ci return NULL; 21069750e409Sopenharmony_ci } 21079750e409Sopenharmony_ci 21089750e409Sopenharmony_ci current_child = array->child; 21099750e409Sopenharmony_ci while ((current_child != NULL) && (index > 0)) 21109750e409Sopenharmony_ci { 21119750e409Sopenharmony_ci index--; 21129750e409Sopenharmony_ci current_child = current_child->next; 21139750e409Sopenharmony_ci } 21149750e409Sopenharmony_ci 21159750e409Sopenharmony_ci return current_child; 21169750e409Sopenharmony_ci} 21179750e409Sopenharmony_ci 21189750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) 21199750e409Sopenharmony_ci{ 21209750e409Sopenharmony_ci if (index < 0) 21219750e409Sopenharmony_ci { 21229750e409Sopenharmony_ci return NULL; 21239750e409Sopenharmony_ci } 21249750e409Sopenharmony_ci 21259750e409Sopenharmony_ci return get_array_item(array, (size_t)index); 21269750e409Sopenharmony_ci} 21279750e409Sopenharmony_ci 21289750e409Sopenharmony_cistatic cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) 21299750e409Sopenharmony_ci{ 21309750e409Sopenharmony_ci cJSON *current_element = NULL; 21319750e409Sopenharmony_ci 21329750e409Sopenharmony_ci if ((object == NULL) || (name == NULL)) 21339750e409Sopenharmony_ci { 21349750e409Sopenharmony_ci return NULL; 21359750e409Sopenharmony_ci } 21369750e409Sopenharmony_ci 21379750e409Sopenharmony_ci current_element = object->child; 21389750e409Sopenharmony_ci if (case_sensitive) 21399750e409Sopenharmony_ci { 21409750e409Sopenharmony_ci while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) 21419750e409Sopenharmony_ci { 21429750e409Sopenharmony_ci current_element = current_element->next; 21439750e409Sopenharmony_ci } 21449750e409Sopenharmony_ci } 21459750e409Sopenharmony_ci else 21469750e409Sopenharmony_ci { 21479750e409Sopenharmony_ci while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) 21489750e409Sopenharmony_ci { 21499750e409Sopenharmony_ci current_element = current_element->next; 21509750e409Sopenharmony_ci } 21519750e409Sopenharmony_ci } 21529750e409Sopenharmony_ci 21539750e409Sopenharmony_ci if ((current_element == NULL) || (current_element->string == NULL)) { 21549750e409Sopenharmony_ci return NULL; 21559750e409Sopenharmony_ci } 21569750e409Sopenharmony_ci 21579750e409Sopenharmony_ci return current_element; 21589750e409Sopenharmony_ci} 21599750e409Sopenharmony_ci 21609750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) 21619750e409Sopenharmony_ci{ 21629750e409Sopenharmony_ci return get_object_item(object, string, false); 21639750e409Sopenharmony_ci} 21649750e409Sopenharmony_ci 21659750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) 21669750e409Sopenharmony_ci{ 21679750e409Sopenharmony_ci return get_object_item(object, string, true); 21689750e409Sopenharmony_ci} 21699750e409Sopenharmony_ci 21709750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) 21719750e409Sopenharmony_ci{ 21729750e409Sopenharmony_ci return cJSON_GetObjectItem(object, string) ? 1 : 0; 21739750e409Sopenharmony_ci} 21749750e409Sopenharmony_ci 21759750e409Sopenharmony_ci/* Utility for array list handling. */ 21769750e409Sopenharmony_cistatic void suffix_object(cJSON *prev, cJSON *item) 21779750e409Sopenharmony_ci{ 21789750e409Sopenharmony_ci prev->next = item; 21799750e409Sopenharmony_ci item->prev = prev; 21809750e409Sopenharmony_ci} 21819750e409Sopenharmony_ci 21829750e409Sopenharmony_ci/* Utility for handling references. */ 21839750e409Sopenharmony_cistatic cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) 21849750e409Sopenharmony_ci{ 21859750e409Sopenharmony_ci cJSON *reference = NULL; 21869750e409Sopenharmony_ci if (item == NULL) 21879750e409Sopenharmony_ci { 21889750e409Sopenharmony_ci return NULL; 21899750e409Sopenharmony_ci } 21909750e409Sopenharmony_ci 21919750e409Sopenharmony_ci reference = cJSON_New_Item(hooks); 21929750e409Sopenharmony_ci if (reference == NULL) 21939750e409Sopenharmony_ci { 21949750e409Sopenharmony_ci return NULL; 21959750e409Sopenharmony_ci } 21969750e409Sopenharmony_ci 21979750e409Sopenharmony_ci memcpy(reference, item, sizeof(cJSON)); 21989750e409Sopenharmony_ci reference->string = NULL; 21999750e409Sopenharmony_ci reference->type |= cJSON_IsReference; 22009750e409Sopenharmony_ci reference->next = reference->prev = NULL; 22019750e409Sopenharmony_ci return reference; 22029750e409Sopenharmony_ci} 22039750e409Sopenharmony_ci 22049750e409Sopenharmony_cistatic cJSON_bool add_item_to_array(cJSON *array, cJSON *item) 22059750e409Sopenharmony_ci{ 22069750e409Sopenharmony_ci cJSON *child = NULL; 22079750e409Sopenharmony_ci 22089750e409Sopenharmony_ci if ((item == NULL) || (array == NULL) || (array == item)) 22099750e409Sopenharmony_ci { 22109750e409Sopenharmony_ci return false; 22119750e409Sopenharmony_ci } 22129750e409Sopenharmony_ci 22139750e409Sopenharmony_ci child = array->child; 22149750e409Sopenharmony_ci /* 22159750e409Sopenharmony_ci * To find the last item in array quickly, we use prev in array 22169750e409Sopenharmony_ci */ 22179750e409Sopenharmony_ci if (child == NULL) 22189750e409Sopenharmony_ci { 22199750e409Sopenharmony_ci /* list is empty, start new one */ 22209750e409Sopenharmony_ci array->child = item; 22219750e409Sopenharmony_ci item->prev = item; 22229750e409Sopenharmony_ci item->next = NULL; 22239750e409Sopenharmony_ci } 22249750e409Sopenharmony_ci else 22259750e409Sopenharmony_ci { 22269750e409Sopenharmony_ci /* append to the end */ 22279750e409Sopenharmony_ci if (child->prev) 22289750e409Sopenharmony_ci { 22299750e409Sopenharmony_ci suffix_object(child->prev, item); 22309750e409Sopenharmony_ci array->child->prev = item; 22319750e409Sopenharmony_ci } 22329750e409Sopenharmony_ci } 22339750e409Sopenharmony_ci 22349750e409Sopenharmony_ci return true; 22359750e409Sopenharmony_ci} 22369750e409Sopenharmony_ci 22379750e409Sopenharmony_ci/* Add item to array/object. */ 22389750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) 22399750e409Sopenharmony_ci{ 22409750e409Sopenharmony_ci return add_item_to_array(array, item); 22419750e409Sopenharmony_ci} 22429750e409Sopenharmony_ci 22439750e409Sopenharmony_ci#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) 22449750e409Sopenharmony_ci #pragma GCC diagnostic push 22459750e409Sopenharmony_ci#endif 22469750e409Sopenharmony_ci#ifdef __GNUC__ 22479750e409Sopenharmony_ci#pragma GCC diagnostic ignored "-Wcast-qual" 22489750e409Sopenharmony_ci#endif 22499750e409Sopenharmony_ci/* helper function to cast away const */ 22509750e409Sopenharmony_cistatic void* cast_away_const(const void* string) 22519750e409Sopenharmony_ci{ 22529750e409Sopenharmony_ci return (void*)string; 22539750e409Sopenharmony_ci} 22549750e409Sopenharmony_ci#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) 22559750e409Sopenharmony_ci #pragma GCC diagnostic pop 22569750e409Sopenharmony_ci#endif 22579750e409Sopenharmony_ci 22589750e409Sopenharmony_ci 22599750e409Sopenharmony_cistatic 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) 22609750e409Sopenharmony_ci{ 22619750e409Sopenharmony_ci char *new_key = NULL; 22629750e409Sopenharmony_ci int new_type = cJSON_Invalid; 22639750e409Sopenharmony_ci 22649750e409Sopenharmony_ci if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) 22659750e409Sopenharmony_ci { 22669750e409Sopenharmony_ci return false; 22679750e409Sopenharmony_ci } 22689750e409Sopenharmony_ci 22699750e409Sopenharmony_ci if (constant_key) 22709750e409Sopenharmony_ci { 22719750e409Sopenharmony_ci new_key = (char*)cast_away_const(string); 22729750e409Sopenharmony_ci new_type = item->type | cJSON_StringIsConst; 22739750e409Sopenharmony_ci } 22749750e409Sopenharmony_ci else 22759750e409Sopenharmony_ci { 22769750e409Sopenharmony_ci new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); 22779750e409Sopenharmony_ci if (new_key == NULL) 22789750e409Sopenharmony_ci { 22799750e409Sopenharmony_ci return false; 22809750e409Sopenharmony_ci } 22819750e409Sopenharmony_ci 22829750e409Sopenharmony_ci new_type = item->type & ~cJSON_StringIsConst; 22839750e409Sopenharmony_ci } 22849750e409Sopenharmony_ci 22859750e409Sopenharmony_ci if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) 22869750e409Sopenharmony_ci { 22879750e409Sopenharmony_ci hooks->deallocate(item->string); 22889750e409Sopenharmony_ci } 22899750e409Sopenharmony_ci 22909750e409Sopenharmony_ci item->string = new_key; 22919750e409Sopenharmony_ci item->type = new_type; 22929750e409Sopenharmony_ci 22939750e409Sopenharmony_ci return add_item_to_array(object, item); 22949750e409Sopenharmony_ci} 22959750e409Sopenharmony_ci 22969750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) 22979750e409Sopenharmony_ci{ 22989750e409Sopenharmony_ci return add_item_to_object(object, string, item, &global_hooks, false); 22999750e409Sopenharmony_ci} 23009750e409Sopenharmony_ci 23019750e409Sopenharmony_ci/* Add an item to an object with constant string as key */ 23029750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) 23039750e409Sopenharmony_ci{ 23049750e409Sopenharmony_ci return add_item_to_object(object, string, item, &global_hooks, true); 23059750e409Sopenharmony_ci} 23069750e409Sopenharmony_ci 23079750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) 23089750e409Sopenharmony_ci{ 23099750e409Sopenharmony_ci if (array == NULL) 23109750e409Sopenharmony_ci { 23119750e409Sopenharmony_ci return false; 23129750e409Sopenharmony_ci } 23139750e409Sopenharmony_ci 23149750e409Sopenharmony_ci return add_item_to_array(array, create_reference(item, &global_hooks)); 23159750e409Sopenharmony_ci} 23169750e409Sopenharmony_ci 23179750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) 23189750e409Sopenharmony_ci{ 23199750e409Sopenharmony_ci if ((object == NULL) || (string == NULL)) 23209750e409Sopenharmony_ci { 23219750e409Sopenharmony_ci return false; 23229750e409Sopenharmony_ci } 23239750e409Sopenharmony_ci 23249750e409Sopenharmony_ci return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); 23259750e409Sopenharmony_ci} 23269750e409Sopenharmony_ci 23279750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) 23289750e409Sopenharmony_ci{ 23299750e409Sopenharmony_ci cJSON *null = cJSON_CreateNull(); 23309750e409Sopenharmony_ci if (add_item_to_object(object, name, null, &global_hooks, false)) 23319750e409Sopenharmony_ci { 23329750e409Sopenharmony_ci return null; 23339750e409Sopenharmony_ci } 23349750e409Sopenharmony_ci 23359750e409Sopenharmony_ci cJSON_Delete(null); 23369750e409Sopenharmony_ci return NULL; 23379750e409Sopenharmony_ci} 23389750e409Sopenharmony_ci 23399750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) 23409750e409Sopenharmony_ci{ 23419750e409Sopenharmony_ci cJSON *true_item = cJSON_CreateTrue(); 23429750e409Sopenharmony_ci if (add_item_to_object(object, name, true_item, &global_hooks, false)) 23439750e409Sopenharmony_ci { 23449750e409Sopenharmony_ci return true_item; 23459750e409Sopenharmony_ci } 23469750e409Sopenharmony_ci 23479750e409Sopenharmony_ci cJSON_Delete(true_item); 23489750e409Sopenharmony_ci return NULL; 23499750e409Sopenharmony_ci} 23509750e409Sopenharmony_ci 23519750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) 23529750e409Sopenharmony_ci{ 23539750e409Sopenharmony_ci cJSON *false_item = cJSON_CreateFalse(); 23549750e409Sopenharmony_ci if (add_item_to_object(object, name, false_item, &global_hooks, false)) 23559750e409Sopenharmony_ci { 23569750e409Sopenharmony_ci return false_item; 23579750e409Sopenharmony_ci } 23589750e409Sopenharmony_ci 23599750e409Sopenharmony_ci cJSON_Delete(false_item); 23609750e409Sopenharmony_ci return NULL; 23619750e409Sopenharmony_ci} 23629750e409Sopenharmony_ci 23639750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) 23649750e409Sopenharmony_ci{ 23659750e409Sopenharmony_ci cJSON *bool_item = cJSON_CreateBool(boolean); 23669750e409Sopenharmony_ci if (add_item_to_object(object, name, bool_item, &global_hooks, false)) 23679750e409Sopenharmony_ci { 23689750e409Sopenharmony_ci return bool_item; 23699750e409Sopenharmony_ci } 23709750e409Sopenharmony_ci 23719750e409Sopenharmony_ci cJSON_Delete(bool_item); 23729750e409Sopenharmony_ci return NULL; 23739750e409Sopenharmony_ci} 23749750e409Sopenharmony_ci 23759750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 23769750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddInt64NumberToObject(cJSON * const object, const char * const name, const long long integer) 23779750e409Sopenharmony_ci{ 23789750e409Sopenharmony_ci cJSON *int_item = cJSON_CreateInt64Number(integer); 23799750e409Sopenharmony_ci if (add_item_to_object(object, name, int_item, &global_hooks, false)) 23809750e409Sopenharmony_ci { 23819750e409Sopenharmony_ci return int_item; 23829750e409Sopenharmony_ci } 23839750e409Sopenharmony_ci 23849750e409Sopenharmony_ci cJSON_Delete(int_item); 23859750e409Sopenharmony_ci return NULL; 23869750e409Sopenharmony_ci} 23879750e409Sopenharmony_ci#endif /* __CJSON_USE_INT64 */ 23889750e409Sopenharmony_ci 23899750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) 23909750e409Sopenharmony_ci{ 23919750e409Sopenharmony_ci cJSON *number_item = cJSON_CreateNumber(number); 23929750e409Sopenharmony_ci if (add_item_to_object(object, name, number_item, &global_hooks, false)) 23939750e409Sopenharmony_ci { 23949750e409Sopenharmony_ci return number_item; 23959750e409Sopenharmony_ci } 23969750e409Sopenharmony_ci 23979750e409Sopenharmony_ci cJSON_Delete(number_item); 23989750e409Sopenharmony_ci return NULL; 23999750e409Sopenharmony_ci} 24009750e409Sopenharmony_ci 24019750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) 24029750e409Sopenharmony_ci{ 24039750e409Sopenharmony_ci cJSON *string_item = cJSON_CreateString(string); 24049750e409Sopenharmony_ci if (add_item_to_object(object, name, string_item, &global_hooks, false)) 24059750e409Sopenharmony_ci { 24069750e409Sopenharmony_ci return string_item; 24079750e409Sopenharmony_ci } 24089750e409Sopenharmony_ci 24099750e409Sopenharmony_ci cJSON_Delete(string_item); 24109750e409Sopenharmony_ci return NULL; 24119750e409Sopenharmony_ci} 24129750e409Sopenharmony_ci 24139750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) 24149750e409Sopenharmony_ci{ 24159750e409Sopenharmony_ci cJSON *raw_item = cJSON_CreateRaw(raw); 24169750e409Sopenharmony_ci if (add_item_to_object(object, name, raw_item, &global_hooks, false)) 24179750e409Sopenharmony_ci { 24189750e409Sopenharmony_ci return raw_item; 24199750e409Sopenharmony_ci } 24209750e409Sopenharmony_ci 24219750e409Sopenharmony_ci cJSON_Delete(raw_item); 24229750e409Sopenharmony_ci return NULL; 24239750e409Sopenharmony_ci} 24249750e409Sopenharmony_ci 24259750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) 24269750e409Sopenharmony_ci{ 24279750e409Sopenharmony_ci cJSON *object_item = cJSON_CreateObject(); 24289750e409Sopenharmony_ci if (add_item_to_object(object, name, object_item, &global_hooks, false)) 24299750e409Sopenharmony_ci { 24309750e409Sopenharmony_ci return object_item; 24319750e409Sopenharmony_ci } 24329750e409Sopenharmony_ci 24339750e409Sopenharmony_ci cJSON_Delete(object_item); 24349750e409Sopenharmony_ci return NULL; 24359750e409Sopenharmony_ci} 24369750e409Sopenharmony_ci 24379750e409Sopenharmony_ciCJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) 24389750e409Sopenharmony_ci{ 24399750e409Sopenharmony_ci cJSON *array = cJSON_CreateArray(); 24409750e409Sopenharmony_ci if (add_item_to_object(object, name, array, &global_hooks, false)) 24419750e409Sopenharmony_ci { 24429750e409Sopenharmony_ci return array; 24439750e409Sopenharmony_ci } 24449750e409Sopenharmony_ci 24459750e409Sopenharmony_ci cJSON_Delete(array); 24469750e409Sopenharmony_ci return NULL; 24479750e409Sopenharmony_ci} 24489750e409Sopenharmony_ci 24499750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) 24509750e409Sopenharmony_ci{ 24519750e409Sopenharmony_ci if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL)) 24529750e409Sopenharmony_ci { 24539750e409Sopenharmony_ci return NULL; 24549750e409Sopenharmony_ci } 24559750e409Sopenharmony_ci 24569750e409Sopenharmony_ci if (item != parent->child) 24579750e409Sopenharmony_ci { 24589750e409Sopenharmony_ci /* not the first element */ 24599750e409Sopenharmony_ci item->prev->next = item->next; 24609750e409Sopenharmony_ci } 24619750e409Sopenharmony_ci if (item->next != NULL) 24629750e409Sopenharmony_ci { 24639750e409Sopenharmony_ci /* not the last element */ 24649750e409Sopenharmony_ci item->next->prev = item->prev; 24659750e409Sopenharmony_ci } 24669750e409Sopenharmony_ci 24679750e409Sopenharmony_ci if (item == parent->child) 24689750e409Sopenharmony_ci { 24699750e409Sopenharmony_ci /* first element */ 24709750e409Sopenharmony_ci parent->child = item->next; 24719750e409Sopenharmony_ci } 24729750e409Sopenharmony_ci else if (item->next == NULL) 24739750e409Sopenharmony_ci { 24749750e409Sopenharmony_ci /* last element */ 24759750e409Sopenharmony_ci parent->child->prev = item->prev; 24769750e409Sopenharmony_ci } 24779750e409Sopenharmony_ci 24789750e409Sopenharmony_ci /* make sure the detached item doesn't point anywhere anymore */ 24799750e409Sopenharmony_ci item->prev = NULL; 24809750e409Sopenharmony_ci item->next = NULL; 24819750e409Sopenharmony_ci 24829750e409Sopenharmony_ci return item; 24839750e409Sopenharmony_ci} 24849750e409Sopenharmony_ci 24859750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) 24869750e409Sopenharmony_ci{ 24879750e409Sopenharmony_ci if (which < 0) 24889750e409Sopenharmony_ci { 24899750e409Sopenharmony_ci return NULL; 24909750e409Sopenharmony_ci } 24919750e409Sopenharmony_ci 24929750e409Sopenharmony_ci return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); 24939750e409Sopenharmony_ci} 24949750e409Sopenharmony_ci 24959750e409Sopenharmony_ciCJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) 24969750e409Sopenharmony_ci{ 24979750e409Sopenharmony_ci cJSON_Delete(cJSON_DetachItemFromArray(array, which)); 24989750e409Sopenharmony_ci} 24999750e409Sopenharmony_ci 25009750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) 25019750e409Sopenharmony_ci{ 25029750e409Sopenharmony_ci cJSON *to_detach = cJSON_GetObjectItem(object, string); 25039750e409Sopenharmony_ci 25049750e409Sopenharmony_ci return cJSON_DetachItemViaPointer(object, to_detach); 25059750e409Sopenharmony_ci} 25069750e409Sopenharmony_ci 25079750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) 25089750e409Sopenharmony_ci{ 25099750e409Sopenharmony_ci cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); 25109750e409Sopenharmony_ci 25119750e409Sopenharmony_ci return cJSON_DetachItemViaPointer(object, to_detach); 25129750e409Sopenharmony_ci} 25139750e409Sopenharmony_ci 25149750e409Sopenharmony_ciCJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) 25159750e409Sopenharmony_ci{ 25169750e409Sopenharmony_ci cJSON_Delete(cJSON_DetachItemFromObject(object, string)); 25179750e409Sopenharmony_ci} 25189750e409Sopenharmony_ci 25199750e409Sopenharmony_ciCJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) 25209750e409Sopenharmony_ci{ 25219750e409Sopenharmony_ci cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); 25229750e409Sopenharmony_ci} 25239750e409Sopenharmony_ci 25249750e409Sopenharmony_ci/* Replace array/object items with new ones. */ 25259750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) 25269750e409Sopenharmony_ci{ 25279750e409Sopenharmony_ci cJSON *after_inserted = NULL; 25289750e409Sopenharmony_ci 25299750e409Sopenharmony_ci if (which < 0 || newitem == NULL) 25309750e409Sopenharmony_ci { 25319750e409Sopenharmony_ci return false; 25329750e409Sopenharmony_ci } 25339750e409Sopenharmony_ci 25349750e409Sopenharmony_ci after_inserted = get_array_item(array, (size_t)which); 25359750e409Sopenharmony_ci if (after_inserted == NULL) 25369750e409Sopenharmony_ci { 25379750e409Sopenharmony_ci return add_item_to_array(array, newitem); 25389750e409Sopenharmony_ci } 25399750e409Sopenharmony_ci 25409750e409Sopenharmony_ci if (after_inserted != array->child && after_inserted->prev == NULL) { 25419750e409Sopenharmony_ci /* return false if after_inserted is a corrupted array item */ 25429750e409Sopenharmony_ci return false; 25439750e409Sopenharmony_ci } 25449750e409Sopenharmony_ci 25459750e409Sopenharmony_ci newitem->next = after_inserted; 25469750e409Sopenharmony_ci newitem->prev = after_inserted->prev; 25479750e409Sopenharmony_ci after_inserted->prev = newitem; 25489750e409Sopenharmony_ci if (after_inserted == array->child) 25499750e409Sopenharmony_ci { 25509750e409Sopenharmony_ci array->child = newitem; 25519750e409Sopenharmony_ci } 25529750e409Sopenharmony_ci else 25539750e409Sopenharmony_ci { 25549750e409Sopenharmony_ci newitem->prev->next = newitem; 25559750e409Sopenharmony_ci } 25569750e409Sopenharmony_ci return true; 25579750e409Sopenharmony_ci} 25589750e409Sopenharmony_ci 25599750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) 25609750e409Sopenharmony_ci{ 25619750e409Sopenharmony_ci if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL)) 25629750e409Sopenharmony_ci { 25639750e409Sopenharmony_ci return false; 25649750e409Sopenharmony_ci } 25659750e409Sopenharmony_ci 25669750e409Sopenharmony_ci if (replacement == item) 25679750e409Sopenharmony_ci { 25689750e409Sopenharmony_ci return true; 25699750e409Sopenharmony_ci } 25709750e409Sopenharmony_ci 25719750e409Sopenharmony_ci replacement->next = item->next; 25729750e409Sopenharmony_ci replacement->prev = item->prev; 25739750e409Sopenharmony_ci 25749750e409Sopenharmony_ci if (replacement->next != NULL) 25759750e409Sopenharmony_ci { 25769750e409Sopenharmony_ci replacement->next->prev = replacement; 25779750e409Sopenharmony_ci } 25789750e409Sopenharmony_ci if (parent->child == item) 25799750e409Sopenharmony_ci { 25809750e409Sopenharmony_ci if (parent->child->prev == parent->child) 25819750e409Sopenharmony_ci { 25829750e409Sopenharmony_ci replacement->prev = replacement; 25839750e409Sopenharmony_ci } 25849750e409Sopenharmony_ci parent->child = replacement; 25859750e409Sopenharmony_ci } 25869750e409Sopenharmony_ci else 25879750e409Sopenharmony_ci { /* 25889750e409Sopenharmony_ci * To find the last item in array quickly, we use prev in array. 25899750e409Sopenharmony_ci * We can't modify the last item's next pointer where this item was the parent's child 25909750e409Sopenharmony_ci */ 25919750e409Sopenharmony_ci if (replacement->prev != NULL) 25929750e409Sopenharmony_ci { 25939750e409Sopenharmony_ci replacement->prev->next = replacement; 25949750e409Sopenharmony_ci } 25959750e409Sopenharmony_ci if (replacement->next == NULL) 25969750e409Sopenharmony_ci { 25979750e409Sopenharmony_ci parent->child->prev = replacement; 25989750e409Sopenharmony_ci } 25999750e409Sopenharmony_ci } 26009750e409Sopenharmony_ci 26019750e409Sopenharmony_ci item->next = NULL; 26029750e409Sopenharmony_ci item->prev = NULL; 26039750e409Sopenharmony_ci cJSON_Delete(item); 26049750e409Sopenharmony_ci 26059750e409Sopenharmony_ci return true; 26069750e409Sopenharmony_ci} 26079750e409Sopenharmony_ci 26089750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) 26099750e409Sopenharmony_ci{ 26109750e409Sopenharmony_ci if (which < 0) 26119750e409Sopenharmony_ci { 26129750e409Sopenharmony_ci return false; 26139750e409Sopenharmony_ci } 26149750e409Sopenharmony_ci 26159750e409Sopenharmony_ci return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); 26169750e409Sopenharmony_ci} 26179750e409Sopenharmony_ci 26189750e409Sopenharmony_cistatic cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) 26199750e409Sopenharmony_ci{ 26209750e409Sopenharmony_ci if ((replacement == NULL) || (string == NULL)) 26219750e409Sopenharmony_ci { 26229750e409Sopenharmony_ci return false; 26239750e409Sopenharmony_ci } 26249750e409Sopenharmony_ci 26259750e409Sopenharmony_ci /* replace the name in the replacement */ 26269750e409Sopenharmony_ci if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) 26279750e409Sopenharmony_ci { 26289750e409Sopenharmony_ci cJSON_free(replacement->string); 26299750e409Sopenharmony_ci } 26309750e409Sopenharmony_ci replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); 26319750e409Sopenharmony_ci if (replacement->string == NULL) 26329750e409Sopenharmony_ci { 26339750e409Sopenharmony_ci return false; 26349750e409Sopenharmony_ci } 26359750e409Sopenharmony_ci 26369750e409Sopenharmony_ci replacement->type &= ~cJSON_StringIsConst; 26379750e409Sopenharmony_ci 26389750e409Sopenharmony_ci return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); 26399750e409Sopenharmony_ci} 26409750e409Sopenharmony_ci 26419750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) 26429750e409Sopenharmony_ci{ 26439750e409Sopenharmony_ci return replace_item_in_object(object, string, newitem, false); 26449750e409Sopenharmony_ci} 26459750e409Sopenharmony_ci 26469750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) 26479750e409Sopenharmony_ci{ 26489750e409Sopenharmony_ci return replace_item_in_object(object, string, newitem, true); 26499750e409Sopenharmony_ci} 26509750e409Sopenharmony_ci 26519750e409Sopenharmony_ci/* Create basic types: */ 26529750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) 26539750e409Sopenharmony_ci{ 26549750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 26559750e409Sopenharmony_ci if(item) 26569750e409Sopenharmony_ci { 26579750e409Sopenharmony_ci item->type = cJSON_NULL; 26589750e409Sopenharmony_ci } 26599750e409Sopenharmony_ci 26609750e409Sopenharmony_ci return item; 26619750e409Sopenharmony_ci} 26629750e409Sopenharmony_ci 26639750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) 26649750e409Sopenharmony_ci{ 26659750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 26669750e409Sopenharmony_ci if(item) 26679750e409Sopenharmony_ci { 26689750e409Sopenharmony_ci item->type = cJSON_True; 26699750e409Sopenharmony_ci } 26709750e409Sopenharmony_ci 26719750e409Sopenharmony_ci return item; 26729750e409Sopenharmony_ci} 26739750e409Sopenharmony_ci 26749750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) 26759750e409Sopenharmony_ci{ 26769750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 26779750e409Sopenharmony_ci if(item) 26789750e409Sopenharmony_ci { 26799750e409Sopenharmony_ci item->type = cJSON_False; 26809750e409Sopenharmony_ci } 26819750e409Sopenharmony_ci 26829750e409Sopenharmony_ci return item; 26839750e409Sopenharmony_ci} 26849750e409Sopenharmony_ci 26859750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) 26869750e409Sopenharmony_ci{ 26879750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 26889750e409Sopenharmony_ci if(item) 26899750e409Sopenharmony_ci { 26909750e409Sopenharmony_ci item->type = boolean ? cJSON_True : cJSON_False; 26919750e409Sopenharmony_ci } 26929750e409Sopenharmony_ci 26939750e409Sopenharmony_ci return item; 26949750e409Sopenharmony_ci} 26959750e409Sopenharmony_ci 26969750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 26979750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateInt64Number(long long integer) 26989750e409Sopenharmony_ci{ 26999750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 27009750e409Sopenharmony_ci if(item) 27019750e409Sopenharmony_ci { 27029750e409Sopenharmony_ci item->type = cJSON_Number | cJSON_IsInt64; 27039750e409Sopenharmony_ci item->valueint = integer; 27049750e409Sopenharmony_ci item->valuedouble = (double)integer; 27059750e409Sopenharmony_ci } 27069750e409Sopenharmony_ci 27079750e409Sopenharmony_ci return item; 27089750e409Sopenharmony_ci} 27099750e409Sopenharmony_ci#endif /* __CJSON_USE_INT64 */ 27109750e409Sopenharmony_ci 27119750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 27129750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) 27139750e409Sopenharmony_ci{ 27149750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 27159750e409Sopenharmony_ci if(item) 27169750e409Sopenharmony_ci { 27179750e409Sopenharmony_ci item->type = cJSON_Number; 27189750e409Sopenharmony_ci item->valuedouble = num; 27199750e409Sopenharmony_ci 27209750e409Sopenharmony_ci /* use saturation in case of overflow */ 27219750e409Sopenharmony_ci /* note that double max(DBL_MAX) is bigger than long long max(LLONG_MAX) */ 27229750e409Sopenharmony_ci if (num >= (double)LLONG_MAX) 27239750e409Sopenharmony_ci { 27249750e409Sopenharmony_ci item->valueint = LLONG_MAX; 27259750e409Sopenharmony_ci } 27269750e409Sopenharmony_ci else if (num <= (double)LLONG_MIN) 27279750e409Sopenharmony_ci { 27289750e409Sopenharmony_ci item->valueint = LLONG_MIN; 27299750e409Sopenharmony_ci } 27309750e409Sopenharmony_ci else 27319750e409Sopenharmony_ci { 27329750e409Sopenharmony_ci item->valueint = (long long)num; 27339750e409Sopenharmony_ci } 27349750e409Sopenharmony_ci } 27359750e409Sopenharmony_ci 27369750e409Sopenharmony_ci return item; 27379750e409Sopenharmony_ci} 27389750e409Sopenharmony_ci#else 27399750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) 27409750e409Sopenharmony_ci{ 27419750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 27429750e409Sopenharmony_ci if(item) 27439750e409Sopenharmony_ci { 27449750e409Sopenharmony_ci item->type = cJSON_Number; 27459750e409Sopenharmony_ci item->valuedouble = num; 27469750e409Sopenharmony_ci 27479750e409Sopenharmony_ci /* use saturation in case of overflow */ 27489750e409Sopenharmony_ci if (num >= INT_MAX) 27499750e409Sopenharmony_ci { 27509750e409Sopenharmony_ci item->valueint = INT_MAX; 27519750e409Sopenharmony_ci } 27529750e409Sopenharmony_ci else if (num <= (double)INT_MIN) 27539750e409Sopenharmony_ci { 27549750e409Sopenharmony_ci item->valueint = INT_MIN; 27559750e409Sopenharmony_ci } 27569750e409Sopenharmony_ci else 27579750e409Sopenharmony_ci { 27589750e409Sopenharmony_ci item->valueint = (int)num; 27599750e409Sopenharmony_ci } 27609750e409Sopenharmony_ci } 27619750e409Sopenharmony_ci 27629750e409Sopenharmony_ci return item; 27639750e409Sopenharmony_ci} 27649750e409Sopenharmony_ci#endif /* __CJSON_USE_INT64 */ 27659750e409Sopenharmony_ci 27669750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) 27679750e409Sopenharmony_ci{ 27689750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 27699750e409Sopenharmony_ci if(item) 27709750e409Sopenharmony_ci { 27719750e409Sopenharmony_ci item->type = cJSON_String; 27729750e409Sopenharmony_ci item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); 27739750e409Sopenharmony_ci if(!item->valuestring) 27749750e409Sopenharmony_ci { 27759750e409Sopenharmony_ci cJSON_Delete(item); 27769750e409Sopenharmony_ci return NULL; 27779750e409Sopenharmony_ci } 27789750e409Sopenharmony_ci } 27799750e409Sopenharmony_ci 27809750e409Sopenharmony_ci return item; 27819750e409Sopenharmony_ci} 27829750e409Sopenharmony_ci 27839750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) 27849750e409Sopenharmony_ci{ 27859750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 27869750e409Sopenharmony_ci if (item != NULL) 27879750e409Sopenharmony_ci { 27889750e409Sopenharmony_ci item->type = cJSON_String | cJSON_IsReference; 27899750e409Sopenharmony_ci item->valuestring = (char*)cast_away_const(string); 27909750e409Sopenharmony_ci } 27919750e409Sopenharmony_ci 27929750e409Sopenharmony_ci return item; 27939750e409Sopenharmony_ci} 27949750e409Sopenharmony_ci 27959750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) 27969750e409Sopenharmony_ci{ 27979750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 27989750e409Sopenharmony_ci if (item != NULL) { 27999750e409Sopenharmony_ci item->type = cJSON_Object | cJSON_IsReference; 28009750e409Sopenharmony_ci item->child = (cJSON*)cast_away_const(child); 28019750e409Sopenharmony_ci } 28029750e409Sopenharmony_ci 28039750e409Sopenharmony_ci return item; 28049750e409Sopenharmony_ci} 28059750e409Sopenharmony_ci 28069750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { 28079750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 28089750e409Sopenharmony_ci if (item != NULL) { 28099750e409Sopenharmony_ci item->type = cJSON_Array | cJSON_IsReference; 28109750e409Sopenharmony_ci item->child = (cJSON*)cast_away_const(child); 28119750e409Sopenharmony_ci } 28129750e409Sopenharmony_ci 28139750e409Sopenharmony_ci return item; 28149750e409Sopenharmony_ci} 28159750e409Sopenharmony_ci 28169750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) 28179750e409Sopenharmony_ci{ 28189750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 28199750e409Sopenharmony_ci if(item) 28209750e409Sopenharmony_ci { 28219750e409Sopenharmony_ci item->type = cJSON_Raw; 28229750e409Sopenharmony_ci item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); 28239750e409Sopenharmony_ci if(!item->valuestring) 28249750e409Sopenharmony_ci { 28259750e409Sopenharmony_ci cJSON_Delete(item); 28269750e409Sopenharmony_ci return NULL; 28279750e409Sopenharmony_ci } 28289750e409Sopenharmony_ci } 28299750e409Sopenharmony_ci 28309750e409Sopenharmony_ci return item; 28319750e409Sopenharmony_ci} 28329750e409Sopenharmony_ci 28339750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) 28349750e409Sopenharmony_ci{ 28359750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 28369750e409Sopenharmony_ci if(item) 28379750e409Sopenharmony_ci { 28389750e409Sopenharmony_ci item->type=cJSON_Array; 28399750e409Sopenharmony_ci } 28409750e409Sopenharmony_ci 28419750e409Sopenharmony_ci return item; 28429750e409Sopenharmony_ci} 28439750e409Sopenharmony_ci 28449750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) 28459750e409Sopenharmony_ci{ 28469750e409Sopenharmony_ci cJSON *item = cJSON_New_Item(&global_hooks); 28479750e409Sopenharmony_ci if (item) 28489750e409Sopenharmony_ci { 28499750e409Sopenharmony_ci item->type = cJSON_Object; 28509750e409Sopenharmony_ci } 28519750e409Sopenharmony_ci 28529750e409Sopenharmony_ci return item; 28539750e409Sopenharmony_ci} 28549750e409Sopenharmony_ci 28559750e409Sopenharmony_ci/* Create Arrays: */ 28569750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) 28579750e409Sopenharmony_ci{ 28589750e409Sopenharmony_ci size_t i = 0; 28599750e409Sopenharmony_ci cJSON *n = NULL; 28609750e409Sopenharmony_ci cJSON *p = NULL; 28619750e409Sopenharmony_ci cJSON *a = NULL; 28629750e409Sopenharmony_ci 28639750e409Sopenharmony_ci if ((count < 0) || (numbers == NULL)) 28649750e409Sopenharmony_ci { 28659750e409Sopenharmony_ci return NULL; 28669750e409Sopenharmony_ci } 28679750e409Sopenharmony_ci 28689750e409Sopenharmony_ci a = cJSON_CreateArray(); 28699750e409Sopenharmony_ci 28709750e409Sopenharmony_ci for(i = 0; a && (i < (size_t)count); i++) 28719750e409Sopenharmony_ci { 28729750e409Sopenharmony_ci n = cJSON_CreateNumber(numbers[i]); 28739750e409Sopenharmony_ci if (!n) 28749750e409Sopenharmony_ci { 28759750e409Sopenharmony_ci cJSON_Delete(a); 28769750e409Sopenharmony_ci return NULL; 28779750e409Sopenharmony_ci } 28789750e409Sopenharmony_ci if(!i) 28799750e409Sopenharmony_ci { 28809750e409Sopenharmony_ci a->child = n; 28819750e409Sopenharmony_ci } 28829750e409Sopenharmony_ci else 28839750e409Sopenharmony_ci { 28849750e409Sopenharmony_ci suffix_object(p, n); 28859750e409Sopenharmony_ci } 28869750e409Sopenharmony_ci p = n; 28879750e409Sopenharmony_ci } 28889750e409Sopenharmony_ci 28899750e409Sopenharmony_ci if (a && a->child) { 28909750e409Sopenharmony_ci a->child->prev = n; 28919750e409Sopenharmony_ci } 28929750e409Sopenharmony_ci 28939750e409Sopenharmony_ci return a; 28949750e409Sopenharmony_ci} 28959750e409Sopenharmony_ci 28969750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) 28979750e409Sopenharmony_ci{ 28989750e409Sopenharmony_ci size_t i = 0; 28999750e409Sopenharmony_ci cJSON *n = NULL; 29009750e409Sopenharmony_ci cJSON *p = NULL; 29019750e409Sopenharmony_ci cJSON *a = NULL; 29029750e409Sopenharmony_ci 29039750e409Sopenharmony_ci if ((count < 0) || (numbers == NULL)) 29049750e409Sopenharmony_ci { 29059750e409Sopenharmony_ci return NULL; 29069750e409Sopenharmony_ci } 29079750e409Sopenharmony_ci 29089750e409Sopenharmony_ci a = cJSON_CreateArray(); 29099750e409Sopenharmony_ci 29109750e409Sopenharmony_ci for(i = 0; a && (i < (size_t)count); i++) 29119750e409Sopenharmony_ci { 29129750e409Sopenharmony_ci n = cJSON_CreateNumber((double)numbers[i]); 29139750e409Sopenharmony_ci if(!n) 29149750e409Sopenharmony_ci { 29159750e409Sopenharmony_ci cJSON_Delete(a); 29169750e409Sopenharmony_ci return NULL; 29179750e409Sopenharmony_ci } 29189750e409Sopenharmony_ci if(!i) 29199750e409Sopenharmony_ci { 29209750e409Sopenharmony_ci a->child = n; 29219750e409Sopenharmony_ci } 29229750e409Sopenharmony_ci else 29239750e409Sopenharmony_ci { 29249750e409Sopenharmony_ci suffix_object(p, n); 29259750e409Sopenharmony_ci } 29269750e409Sopenharmony_ci p = n; 29279750e409Sopenharmony_ci } 29289750e409Sopenharmony_ci 29299750e409Sopenharmony_ci if (a && a->child) { 29309750e409Sopenharmony_ci a->child->prev = n; 29319750e409Sopenharmony_ci } 29329750e409Sopenharmony_ci 29339750e409Sopenharmony_ci return a; 29349750e409Sopenharmony_ci} 29359750e409Sopenharmony_ci 29369750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) 29379750e409Sopenharmony_ci{ 29389750e409Sopenharmony_ci size_t i = 0; 29399750e409Sopenharmony_ci cJSON *n = NULL; 29409750e409Sopenharmony_ci cJSON *p = NULL; 29419750e409Sopenharmony_ci cJSON *a = NULL; 29429750e409Sopenharmony_ci 29439750e409Sopenharmony_ci if ((count < 0) || (numbers == NULL)) 29449750e409Sopenharmony_ci { 29459750e409Sopenharmony_ci return NULL; 29469750e409Sopenharmony_ci } 29479750e409Sopenharmony_ci 29489750e409Sopenharmony_ci a = cJSON_CreateArray(); 29499750e409Sopenharmony_ci 29509750e409Sopenharmony_ci for(i = 0; a && (i < (size_t)count); i++) 29519750e409Sopenharmony_ci { 29529750e409Sopenharmony_ci n = cJSON_CreateNumber(numbers[i]); 29539750e409Sopenharmony_ci if(!n) 29549750e409Sopenharmony_ci { 29559750e409Sopenharmony_ci cJSON_Delete(a); 29569750e409Sopenharmony_ci return NULL; 29579750e409Sopenharmony_ci } 29589750e409Sopenharmony_ci if(!i) 29599750e409Sopenharmony_ci { 29609750e409Sopenharmony_ci a->child = n; 29619750e409Sopenharmony_ci } 29629750e409Sopenharmony_ci else 29639750e409Sopenharmony_ci { 29649750e409Sopenharmony_ci suffix_object(p, n); 29659750e409Sopenharmony_ci } 29669750e409Sopenharmony_ci p = n; 29679750e409Sopenharmony_ci } 29689750e409Sopenharmony_ci 29699750e409Sopenharmony_ci if (a && a->child) { 29709750e409Sopenharmony_ci a->child->prev = n; 29719750e409Sopenharmony_ci } 29729750e409Sopenharmony_ci 29739750e409Sopenharmony_ci return a; 29749750e409Sopenharmony_ci} 29759750e409Sopenharmony_ci 29769750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) 29779750e409Sopenharmony_ci{ 29789750e409Sopenharmony_ci size_t i = 0; 29799750e409Sopenharmony_ci cJSON *n = NULL; 29809750e409Sopenharmony_ci cJSON *p = NULL; 29819750e409Sopenharmony_ci cJSON *a = NULL; 29829750e409Sopenharmony_ci 29839750e409Sopenharmony_ci if ((count < 0) || (strings == NULL)) 29849750e409Sopenharmony_ci { 29859750e409Sopenharmony_ci return NULL; 29869750e409Sopenharmony_ci } 29879750e409Sopenharmony_ci 29889750e409Sopenharmony_ci a = cJSON_CreateArray(); 29899750e409Sopenharmony_ci 29909750e409Sopenharmony_ci for (i = 0; a && (i < (size_t)count); i++) 29919750e409Sopenharmony_ci { 29929750e409Sopenharmony_ci n = cJSON_CreateString(strings[i]); 29939750e409Sopenharmony_ci if(!n) 29949750e409Sopenharmony_ci { 29959750e409Sopenharmony_ci cJSON_Delete(a); 29969750e409Sopenharmony_ci return NULL; 29979750e409Sopenharmony_ci } 29989750e409Sopenharmony_ci if(!i) 29999750e409Sopenharmony_ci { 30009750e409Sopenharmony_ci a->child = n; 30019750e409Sopenharmony_ci } 30029750e409Sopenharmony_ci else 30039750e409Sopenharmony_ci { 30049750e409Sopenharmony_ci suffix_object(p,n); 30059750e409Sopenharmony_ci } 30069750e409Sopenharmony_ci p = n; 30079750e409Sopenharmony_ci } 30089750e409Sopenharmony_ci 30099750e409Sopenharmony_ci if (a && a->child) { 30109750e409Sopenharmony_ci a->child->prev = n; 30119750e409Sopenharmony_ci } 30129750e409Sopenharmony_ci 30139750e409Sopenharmony_ci return a; 30149750e409Sopenharmony_ci} 30159750e409Sopenharmony_ci 30169750e409Sopenharmony_ci/* Duplication */ 30179750e409Sopenharmony_ciCJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) 30189750e409Sopenharmony_ci{ 30199750e409Sopenharmony_ci cJSON *newitem = NULL; 30209750e409Sopenharmony_ci cJSON *child = NULL; 30219750e409Sopenharmony_ci cJSON *next = NULL; 30229750e409Sopenharmony_ci cJSON *newchild = NULL; 30239750e409Sopenharmony_ci 30249750e409Sopenharmony_ci /* Bail on bad ptr */ 30259750e409Sopenharmony_ci if (!item) 30269750e409Sopenharmony_ci { 30279750e409Sopenharmony_ci goto fail; 30289750e409Sopenharmony_ci } 30299750e409Sopenharmony_ci /* Create new item */ 30309750e409Sopenharmony_ci newitem = cJSON_New_Item(&global_hooks); 30319750e409Sopenharmony_ci if (!newitem) 30329750e409Sopenharmony_ci { 30339750e409Sopenharmony_ci goto fail; 30349750e409Sopenharmony_ci } 30359750e409Sopenharmony_ci /* Copy over all vars */ 30369750e409Sopenharmony_ci newitem->type = item->type & (~cJSON_IsReference); 30379750e409Sopenharmony_ci newitem->valueint = item->valueint; 30389750e409Sopenharmony_ci newitem->valuedouble = item->valuedouble; 30399750e409Sopenharmony_ci if (item->valuestring) 30409750e409Sopenharmony_ci { 30419750e409Sopenharmony_ci newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); 30429750e409Sopenharmony_ci if (!newitem->valuestring) 30439750e409Sopenharmony_ci { 30449750e409Sopenharmony_ci goto fail; 30459750e409Sopenharmony_ci } 30469750e409Sopenharmony_ci } 30479750e409Sopenharmony_ci if (item->string) 30489750e409Sopenharmony_ci { 30499750e409Sopenharmony_ci newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); 30509750e409Sopenharmony_ci if (!newitem->string) 30519750e409Sopenharmony_ci { 30529750e409Sopenharmony_ci goto fail; 30539750e409Sopenharmony_ci } 30549750e409Sopenharmony_ci } 30559750e409Sopenharmony_ci /* If non-recursive, then we're done! */ 30569750e409Sopenharmony_ci if (!recurse) 30579750e409Sopenharmony_ci { 30589750e409Sopenharmony_ci return newitem; 30599750e409Sopenharmony_ci } 30609750e409Sopenharmony_ci /* Walk the ->next chain for the child. */ 30619750e409Sopenharmony_ci child = item->child; 30629750e409Sopenharmony_ci while (child != NULL) 30639750e409Sopenharmony_ci { 30649750e409Sopenharmony_ci newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ 30659750e409Sopenharmony_ci if (!newchild) 30669750e409Sopenharmony_ci { 30679750e409Sopenharmony_ci goto fail; 30689750e409Sopenharmony_ci } 30699750e409Sopenharmony_ci if (next != NULL) 30709750e409Sopenharmony_ci { 30719750e409Sopenharmony_ci /* If newitem->child already set, then crosswire ->prev and ->next and move on */ 30729750e409Sopenharmony_ci next->next = newchild; 30739750e409Sopenharmony_ci newchild->prev = next; 30749750e409Sopenharmony_ci next = newchild; 30759750e409Sopenharmony_ci } 30769750e409Sopenharmony_ci else 30779750e409Sopenharmony_ci { 30789750e409Sopenharmony_ci /* Set newitem->child and move to it */ 30799750e409Sopenharmony_ci newitem->child = newchild; 30809750e409Sopenharmony_ci next = newchild; 30819750e409Sopenharmony_ci } 30829750e409Sopenharmony_ci child = child->next; 30839750e409Sopenharmony_ci } 30849750e409Sopenharmony_ci if (newitem && newitem->child) 30859750e409Sopenharmony_ci { 30869750e409Sopenharmony_ci newitem->child->prev = newchild; 30879750e409Sopenharmony_ci } 30889750e409Sopenharmony_ci 30899750e409Sopenharmony_ci return newitem; 30909750e409Sopenharmony_ci 30919750e409Sopenharmony_cifail: 30929750e409Sopenharmony_ci if (newitem != NULL) 30939750e409Sopenharmony_ci { 30949750e409Sopenharmony_ci cJSON_Delete(newitem); 30959750e409Sopenharmony_ci } 30969750e409Sopenharmony_ci 30979750e409Sopenharmony_ci return NULL; 30989750e409Sopenharmony_ci} 30999750e409Sopenharmony_ci 31009750e409Sopenharmony_cistatic void skip_oneline_comment(char **input) 31019750e409Sopenharmony_ci{ 31029750e409Sopenharmony_ci *input += static_strlen("//"); 31039750e409Sopenharmony_ci 31049750e409Sopenharmony_ci for (; (*input)[0] != '\0'; ++(*input)) 31059750e409Sopenharmony_ci { 31069750e409Sopenharmony_ci if ((*input)[0] == '\n') { 31079750e409Sopenharmony_ci *input += static_strlen("\n"); 31089750e409Sopenharmony_ci return; 31099750e409Sopenharmony_ci } 31109750e409Sopenharmony_ci } 31119750e409Sopenharmony_ci} 31129750e409Sopenharmony_ci 31139750e409Sopenharmony_cistatic void skip_multiline_comment(char **input) 31149750e409Sopenharmony_ci{ 31159750e409Sopenharmony_ci *input += static_strlen("/*"); 31169750e409Sopenharmony_ci 31179750e409Sopenharmony_ci for (; (*input)[0] != '\0'; ++(*input)) 31189750e409Sopenharmony_ci { 31199750e409Sopenharmony_ci if (((*input)[0] == '*') && ((*input)[1] == '/')) 31209750e409Sopenharmony_ci { 31219750e409Sopenharmony_ci *input += static_strlen("*/"); 31229750e409Sopenharmony_ci return; 31239750e409Sopenharmony_ci } 31249750e409Sopenharmony_ci } 31259750e409Sopenharmony_ci} 31269750e409Sopenharmony_ci 31279750e409Sopenharmony_cistatic void minify_string(char **input, char **output) { 31289750e409Sopenharmony_ci (*output)[0] = (*input)[0]; 31299750e409Sopenharmony_ci *input += static_strlen("\""); 31309750e409Sopenharmony_ci *output += static_strlen("\""); 31319750e409Sopenharmony_ci 31329750e409Sopenharmony_ci 31339750e409Sopenharmony_ci for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { 31349750e409Sopenharmony_ci (*output)[0] = (*input)[0]; 31359750e409Sopenharmony_ci 31369750e409Sopenharmony_ci if ((*input)[0] == '\"') { 31379750e409Sopenharmony_ci (*output)[0] = '\"'; 31389750e409Sopenharmony_ci *input += static_strlen("\""); 31399750e409Sopenharmony_ci *output += static_strlen("\""); 31409750e409Sopenharmony_ci return; 31419750e409Sopenharmony_ci } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { 31429750e409Sopenharmony_ci (*output)[1] = (*input)[1]; 31439750e409Sopenharmony_ci *input += static_strlen("\""); 31449750e409Sopenharmony_ci *output += static_strlen("\""); 31459750e409Sopenharmony_ci } 31469750e409Sopenharmony_ci } 31479750e409Sopenharmony_ci} 31489750e409Sopenharmony_ci 31499750e409Sopenharmony_ciCJSON_PUBLIC(void) cJSON_Minify(char *json) 31509750e409Sopenharmony_ci{ 31519750e409Sopenharmony_ci char *into = json; 31529750e409Sopenharmony_ci 31539750e409Sopenharmony_ci if (json == NULL) 31549750e409Sopenharmony_ci { 31559750e409Sopenharmony_ci return; 31569750e409Sopenharmony_ci } 31579750e409Sopenharmony_ci 31589750e409Sopenharmony_ci while (json[0] != '\0') 31599750e409Sopenharmony_ci { 31609750e409Sopenharmony_ci switch (json[0]) 31619750e409Sopenharmony_ci { 31629750e409Sopenharmony_ci case ' ': 31639750e409Sopenharmony_ci case '\t': 31649750e409Sopenharmony_ci case '\r': 31659750e409Sopenharmony_ci case '\n': 31669750e409Sopenharmony_ci json++; 31679750e409Sopenharmony_ci break; 31689750e409Sopenharmony_ci 31699750e409Sopenharmony_ci case '/': 31709750e409Sopenharmony_ci if (json[1] == '/') 31719750e409Sopenharmony_ci { 31729750e409Sopenharmony_ci skip_oneline_comment(&json); 31739750e409Sopenharmony_ci } 31749750e409Sopenharmony_ci else if (json[1] == '*') 31759750e409Sopenharmony_ci { 31769750e409Sopenharmony_ci skip_multiline_comment(&json); 31779750e409Sopenharmony_ci } else { 31789750e409Sopenharmony_ci json++; 31799750e409Sopenharmony_ci } 31809750e409Sopenharmony_ci break; 31819750e409Sopenharmony_ci 31829750e409Sopenharmony_ci case '\"': 31839750e409Sopenharmony_ci minify_string(&json, (char**)&into); 31849750e409Sopenharmony_ci break; 31859750e409Sopenharmony_ci 31869750e409Sopenharmony_ci default: 31879750e409Sopenharmony_ci into[0] = json[0]; 31889750e409Sopenharmony_ci json++; 31899750e409Sopenharmony_ci into++; 31909750e409Sopenharmony_ci } 31919750e409Sopenharmony_ci } 31929750e409Sopenharmony_ci 31939750e409Sopenharmony_ci /* and null-terminate. */ 31949750e409Sopenharmony_ci *into = '\0'; 31959750e409Sopenharmony_ci} 31969750e409Sopenharmony_ci 31979750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) 31989750e409Sopenharmony_ci{ 31999750e409Sopenharmony_ci if (item == NULL) 32009750e409Sopenharmony_ci { 32019750e409Sopenharmony_ci return false; 32029750e409Sopenharmony_ci } 32039750e409Sopenharmony_ci 32049750e409Sopenharmony_ci return (item->type & 0xFF) == cJSON_Invalid; 32059750e409Sopenharmony_ci} 32069750e409Sopenharmony_ci 32079750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) 32089750e409Sopenharmony_ci{ 32099750e409Sopenharmony_ci if (item == NULL) 32109750e409Sopenharmony_ci { 32119750e409Sopenharmony_ci return false; 32129750e409Sopenharmony_ci } 32139750e409Sopenharmony_ci 32149750e409Sopenharmony_ci return (item->type & 0xFF) == cJSON_False; 32159750e409Sopenharmony_ci} 32169750e409Sopenharmony_ci 32179750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) 32189750e409Sopenharmony_ci{ 32199750e409Sopenharmony_ci if (item == NULL) 32209750e409Sopenharmony_ci { 32219750e409Sopenharmony_ci return false; 32229750e409Sopenharmony_ci } 32239750e409Sopenharmony_ci 32249750e409Sopenharmony_ci return (item->type & 0xff) == cJSON_True; 32259750e409Sopenharmony_ci} 32269750e409Sopenharmony_ci 32279750e409Sopenharmony_ci 32289750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) 32299750e409Sopenharmony_ci{ 32309750e409Sopenharmony_ci if (item == NULL) 32319750e409Sopenharmony_ci { 32329750e409Sopenharmony_ci return false; 32339750e409Sopenharmony_ci } 32349750e409Sopenharmony_ci 32359750e409Sopenharmony_ci return (item->type & (cJSON_True | cJSON_False)) != 0; 32369750e409Sopenharmony_ci} 32379750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) 32389750e409Sopenharmony_ci{ 32399750e409Sopenharmony_ci if (item == NULL) 32409750e409Sopenharmony_ci { 32419750e409Sopenharmony_ci return false; 32429750e409Sopenharmony_ci } 32439750e409Sopenharmony_ci 32449750e409Sopenharmony_ci return (item->type & 0xFF) == cJSON_NULL; 32459750e409Sopenharmony_ci} 32469750e409Sopenharmony_ci 32479750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 32489750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsInt64Number(const cJSON * const item) 32499750e409Sopenharmony_ci{ 32509750e409Sopenharmony_ci if (item == NULL) 32519750e409Sopenharmony_ci { 32529750e409Sopenharmony_ci return false; 32539750e409Sopenharmony_ci } 32549750e409Sopenharmony_ci 32559750e409Sopenharmony_ci return cJSON_IsNumber(item) && (item->type & cJSON_IsInt64); 32569750e409Sopenharmony_ci} 32579750e409Sopenharmony_ci#endif /* __CJSON_USE_INT64 */ 32589750e409Sopenharmony_ci 32599750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) 32609750e409Sopenharmony_ci{ 32619750e409Sopenharmony_ci if (item == NULL) 32629750e409Sopenharmony_ci { 32639750e409Sopenharmony_ci return false; 32649750e409Sopenharmony_ci } 32659750e409Sopenharmony_ci 32669750e409Sopenharmony_ci return (item->type & 0xFF) == cJSON_Number; 32679750e409Sopenharmony_ci} 32689750e409Sopenharmony_ci 32699750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) 32709750e409Sopenharmony_ci{ 32719750e409Sopenharmony_ci if (item == NULL) 32729750e409Sopenharmony_ci { 32739750e409Sopenharmony_ci return false; 32749750e409Sopenharmony_ci } 32759750e409Sopenharmony_ci 32769750e409Sopenharmony_ci return (item->type & 0xFF) == cJSON_String; 32779750e409Sopenharmony_ci} 32789750e409Sopenharmony_ci 32799750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) 32809750e409Sopenharmony_ci{ 32819750e409Sopenharmony_ci if (item == NULL) 32829750e409Sopenharmony_ci { 32839750e409Sopenharmony_ci return false; 32849750e409Sopenharmony_ci } 32859750e409Sopenharmony_ci 32869750e409Sopenharmony_ci return (item->type & 0xFF) == cJSON_Array; 32879750e409Sopenharmony_ci} 32889750e409Sopenharmony_ci 32899750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) 32909750e409Sopenharmony_ci{ 32919750e409Sopenharmony_ci if (item == NULL) 32929750e409Sopenharmony_ci { 32939750e409Sopenharmony_ci return false; 32949750e409Sopenharmony_ci } 32959750e409Sopenharmony_ci 32969750e409Sopenharmony_ci return (item->type & 0xFF) == cJSON_Object; 32979750e409Sopenharmony_ci} 32989750e409Sopenharmony_ci 32999750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) 33009750e409Sopenharmony_ci{ 33019750e409Sopenharmony_ci if (item == NULL) 33029750e409Sopenharmony_ci { 33039750e409Sopenharmony_ci return false; 33049750e409Sopenharmony_ci } 33059750e409Sopenharmony_ci 33069750e409Sopenharmony_ci return (item->type & 0xFF) == cJSON_Raw; 33079750e409Sopenharmony_ci} 33089750e409Sopenharmony_ci 33099750e409Sopenharmony_ciCJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) 33109750e409Sopenharmony_ci{ 33119750e409Sopenharmony_ci if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) 33129750e409Sopenharmony_ci { 33139750e409Sopenharmony_ci return false; 33149750e409Sopenharmony_ci } 33159750e409Sopenharmony_ci 33169750e409Sopenharmony_ci /* check if type is valid */ 33179750e409Sopenharmony_ci switch (a->type & 0xFF) 33189750e409Sopenharmony_ci { 33199750e409Sopenharmony_ci case cJSON_False: 33209750e409Sopenharmony_ci case cJSON_True: 33219750e409Sopenharmony_ci case cJSON_NULL: 33229750e409Sopenharmony_ci case cJSON_Number: 33239750e409Sopenharmony_ci case cJSON_String: 33249750e409Sopenharmony_ci case cJSON_Raw: 33259750e409Sopenharmony_ci case cJSON_Array: 33269750e409Sopenharmony_ci case cJSON_Object: 33279750e409Sopenharmony_ci break; 33289750e409Sopenharmony_ci 33299750e409Sopenharmony_ci default: 33309750e409Sopenharmony_ci return false; 33319750e409Sopenharmony_ci } 33329750e409Sopenharmony_ci 33339750e409Sopenharmony_ci /* identical objects are equal */ 33349750e409Sopenharmony_ci if (a == b) 33359750e409Sopenharmony_ci { 33369750e409Sopenharmony_ci return true; 33379750e409Sopenharmony_ci } 33389750e409Sopenharmony_ci 33399750e409Sopenharmony_ci switch (a->type & 0xFF) 33409750e409Sopenharmony_ci { 33419750e409Sopenharmony_ci /* in these cases and equal type is enough */ 33429750e409Sopenharmony_ci case cJSON_False: 33439750e409Sopenharmony_ci case cJSON_True: 33449750e409Sopenharmony_ci case cJSON_NULL: 33459750e409Sopenharmony_ci return true; 33469750e409Sopenharmony_ci 33479750e409Sopenharmony_ci#ifdef __CJSON_USE_INT64 33489750e409Sopenharmony_ci case cJSON_Number: 33499750e409Sopenharmony_ci if (!compare_double(a->valuedouble, b->valuedouble)) 33509750e409Sopenharmony_ci { 33519750e409Sopenharmony_ci return false; 33529750e409Sopenharmony_ci } 33539750e409Sopenharmony_ci 33549750e409Sopenharmony_ci if ((a->type & cJSON_IsInt64) != (b->type & cJSON_IsInt64)) 33559750e409Sopenharmony_ci { 33569750e409Sopenharmony_ci /* cJSON_IsInt64 should also be considered */ 33579750e409Sopenharmony_ci return false; 33589750e409Sopenharmony_ci } 33599750e409Sopenharmony_ci 33609750e409Sopenharmony_ci if ((a->type & cJSON_IsInt64) && (b->type & cJSON_IsInt64)) 33619750e409Sopenharmony_ci { 33629750e409Sopenharmony_ci /* compare valueint if both of them are int64 */ 33639750e409Sopenharmony_ci return a->valueint == b->valueint; 33649750e409Sopenharmony_ci } 33659750e409Sopenharmony_ci 33669750e409Sopenharmony_ci return true; 33679750e409Sopenharmony_ci#else 33689750e409Sopenharmony_ci case cJSON_Number: 33699750e409Sopenharmony_ci if (compare_double(a->valuedouble, b->valuedouble)) 33709750e409Sopenharmony_ci { 33719750e409Sopenharmony_ci return true; 33729750e409Sopenharmony_ci } 33739750e409Sopenharmony_ci return false; 33749750e409Sopenharmony_ci#endif /* __CJSON_USE_INT64 */ 33759750e409Sopenharmony_ci 33769750e409Sopenharmony_ci case cJSON_String: 33779750e409Sopenharmony_ci case cJSON_Raw: 33789750e409Sopenharmony_ci if ((a->valuestring == NULL) || (b->valuestring == NULL)) 33799750e409Sopenharmony_ci { 33809750e409Sopenharmony_ci return false; 33819750e409Sopenharmony_ci } 33829750e409Sopenharmony_ci if (strcmp(a->valuestring, b->valuestring) == 0) 33839750e409Sopenharmony_ci { 33849750e409Sopenharmony_ci return true; 33859750e409Sopenharmony_ci } 33869750e409Sopenharmony_ci 33879750e409Sopenharmony_ci return false; 33889750e409Sopenharmony_ci 33899750e409Sopenharmony_ci case cJSON_Array: 33909750e409Sopenharmony_ci { 33919750e409Sopenharmony_ci cJSON *a_element = a->child; 33929750e409Sopenharmony_ci cJSON *b_element = b->child; 33939750e409Sopenharmony_ci 33949750e409Sopenharmony_ci for (; (a_element != NULL) && (b_element != NULL);) 33959750e409Sopenharmony_ci { 33969750e409Sopenharmony_ci if (!cJSON_Compare(a_element, b_element, case_sensitive)) 33979750e409Sopenharmony_ci { 33989750e409Sopenharmony_ci return false; 33999750e409Sopenharmony_ci } 34009750e409Sopenharmony_ci 34019750e409Sopenharmony_ci a_element = a_element->next; 34029750e409Sopenharmony_ci b_element = b_element->next; 34039750e409Sopenharmony_ci } 34049750e409Sopenharmony_ci 34059750e409Sopenharmony_ci /* one of the arrays is longer than the other */ 34069750e409Sopenharmony_ci if (a_element != b_element) { 34079750e409Sopenharmony_ci return false; 34089750e409Sopenharmony_ci } 34099750e409Sopenharmony_ci 34109750e409Sopenharmony_ci return true; 34119750e409Sopenharmony_ci } 34129750e409Sopenharmony_ci 34139750e409Sopenharmony_ci case cJSON_Object: 34149750e409Sopenharmony_ci { 34159750e409Sopenharmony_ci cJSON *a_element = NULL; 34169750e409Sopenharmony_ci cJSON *b_element = NULL; 34179750e409Sopenharmony_ci cJSON_ArrayForEach(a_element, a) 34189750e409Sopenharmony_ci { 34199750e409Sopenharmony_ci /* TODO This has O(n^2) runtime, which is horrible! */ 34209750e409Sopenharmony_ci b_element = get_object_item(b, a_element->string, case_sensitive); 34219750e409Sopenharmony_ci if (b_element == NULL) 34229750e409Sopenharmony_ci { 34239750e409Sopenharmony_ci return false; 34249750e409Sopenharmony_ci } 34259750e409Sopenharmony_ci 34269750e409Sopenharmony_ci if (!cJSON_Compare(a_element, b_element, case_sensitive)) 34279750e409Sopenharmony_ci { 34289750e409Sopenharmony_ci return false; 34299750e409Sopenharmony_ci } 34309750e409Sopenharmony_ci } 34319750e409Sopenharmony_ci 34329750e409Sopenharmony_ci /* doing this twice, once on a and b to prevent true comparison if a subset of b 34339750e409Sopenharmony_ci * TODO: Do this the proper way, this is just a fix for now */ 34349750e409Sopenharmony_ci cJSON_ArrayForEach(b_element, b) 34359750e409Sopenharmony_ci { 34369750e409Sopenharmony_ci a_element = get_object_item(a, b_element->string, case_sensitive); 34379750e409Sopenharmony_ci if (a_element == NULL) 34389750e409Sopenharmony_ci { 34399750e409Sopenharmony_ci return false; 34409750e409Sopenharmony_ci } 34419750e409Sopenharmony_ci 34429750e409Sopenharmony_ci if (!cJSON_Compare(b_element, a_element, case_sensitive)) 34439750e409Sopenharmony_ci { 34449750e409Sopenharmony_ci return false; 34459750e409Sopenharmony_ci } 34469750e409Sopenharmony_ci } 34479750e409Sopenharmony_ci 34489750e409Sopenharmony_ci return true; 34499750e409Sopenharmony_ci } 34509750e409Sopenharmony_ci 34519750e409Sopenharmony_ci default: 34529750e409Sopenharmony_ci return false; 34539750e409Sopenharmony_ci } 34549750e409Sopenharmony_ci} 34559750e409Sopenharmony_ci 34569750e409Sopenharmony_ciCJSON_PUBLIC(void *) cJSON_malloc(size_t size) 34579750e409Sopenharmony_ci{ 34589750e409Sopenharmony_ci return global_hooks.allocate(size); 34599750e409Sopenharmony_ci} 34609750e409Sopenharmony_ci 34619750e409Sopenharmony_ciCJSON_PUBLIC(void) cJSON_free(void *object) 34629750e409Sopenharmony_ci{ 34639750e409Sopenharmony_ci global_hooks.deallocate(object); 34649750e409Sopenharmony_ci} 3465