Update the latest cJSON library, resolve calling cJSON_ Print returned a failed problem.

This commit is contained in:
Yangyuanxin
2022-11-13 10:44:14 -05:00
parent eaa1b9ee5e
commit 3aa583750a
2 changed files with 3423 additions and 3217 deletions

View File

@@ -28,10 +28,60 @@ extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 1
#define CJSON_VERSION_PATCH 15
#include <stddef.h>
@@ -74,55 +124,13 @@ typedef struct cJSON
typedef struct cJSON_Hooks
{
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type __stdcall
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall
#endif
#else /* !WIN32 */
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
@@ -138,9 +146,11 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
@@ -152,11 +162,11 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
@@ -165,8 +175,9 @@ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *st
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check if the item is a string and return its valuestring */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
@@ -195,29 +206,30 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/arrray that only references it's elements so
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items. */
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
@@ -227,22 +239,24 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
@@ -262,6 +276,15 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)

View File

@@ -22,8 +22,6 @@
/* cJSON */
/* JSON parser in C. */
#define _MSC_VER 1900
#undef _MSC_VER
/* disable warnings about old C89 functions in MSVC */
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
@@ -43,12 +41,9 @@
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "cJSON.h"
#include <tos_k.h>
#include <float.h>
#ifdef ENABLE_LOCALES
#include <locale.h>
@@ -61,12 +56,36 @@
#pragma GCC visibility pop
#endif
#include "cJSON.h"
#include <tos_k.h>
/* define our own boolean type */
#ifdef true
#undef true
#endif
#define true ((cJSON_bool)1)
#ifdef false
#undef false
#endif
#define false ((cJSON_bool)0)
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
#ifndef isinf
#define isinf(d) (isnan((d - d)) && !isnan(d))
#endif
#ifndef isnan
#define isnan(d) (d != d)
#endif
#ifndef NAN
#ifdef _WIN32
#define NAN sqrt(-1.0)
#else
#define NAN 0.0/0.0
#endif
#endif
typedef struct {
const unsigned char *json;
size_t position;
@@ -78,16 +97,28 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
return (const char*) (global_error.json + global_error.position);
}
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) {
if (!cJSON_IsString(item)) {
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
{
if (!cJSON_IsString(item))
{
return NULL;
}
return item->valuestring;
}
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
{
if (!cJSON_IsNumber(item))
{
return (double) NAN;
}
return item->valuedouble;
}
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 1)
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif
@@ -125,34 +156,37 @@ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned
typedef struct internal_hooks
{
void *(*allocate)(size_t size);
void (*deallocate)(void *pointer);
void *(*reallocate)(void *pointer, size_t size);
void *(CJSON_CDECL *allocate)(size_t size);
void (CJSON_CDECL *deallocate)(void *pointer);
void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
} internal_hooks;
#if defined(_MSC_VER)
/* work around MSVC error C2322: '...' address of dillimport '...' is not static */
static void *internal_malloc(size_t size)
/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
static void * CJSON_CDECL internal_malloc(size_t size)
{
//return malloc(size);
return tos_mmheap_alloc(size);
}
static void internal_free(void *pointer)
static void CJSON_CDECL internal_free(void *pointer)
{
//free(pointer);
tos_mmheap_free(pointer);
}
static void *internal_realloc(void *pointer, size_t size)
static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
{
//return realloc(pointer, size);
return tos_mmheap_realloc(pointer,size);
}
#else
#define internal_malloc tos_mmheap_alloc
#define internal_free tos_mmheap_free
#define internal_realloc tos_mmheap_realloc
#define internal_malloc tos_mmheap_alloc
#define internal_free tos_mmheap_free
#define internal_realloc tos_mmheap_realloc
#endif
/* strlen of character literals resolved at compile time */
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
@@ -333,7 +367,7 @@ loop_end:
{
item->valueint = INT_MAX;
}
else if (number <= INT_MIN)
else if (number <= (double)INT_MIN)
{
item->valueint = INT_MIN;
}
@@ -355,7 +389,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
{
object->valueint = INT_MAX;
}
else if (number <= INT_MIN)
else if (number <= (double)INT_MIN)
{
object->valueint = INT_MIN;
}
@@ -367,6 +401,33 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
return object->valuedouble = number;
}
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
{
char *copy = NULL;
/* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
{
return NULL;
}
if (strlen(valuestring) <= strlen(object->valuestring))
{
strcpy(object->valuestring, valuestring);
return object->valuestring;
}
copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
if (copy == NULL)
{
return NULL;
}
if (object->valuestring != NULL)
{
cJSON_free(object->valuestring);
}
object->valuestring = copy;
return copy;
}
typedef struct
{
unsigned char *buffer;
@@ -454,10 +515,8 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
return NULL;
}
if (newbuffer)
{
memcpy(newbuffer, p->buffer, p->offset + 1);
}
p->hooks.deallocate(p->buffer);
}
p->length = newsize;
@@ -479,6 +538,13 @@ static void update_offset(printbuffer * const buffer)
buffer->offset += strlen((const char*)buffer_pointer);
}
/* securely comparison of floating-point variables */
static cJSON_bool compare_double(double a, double b)
{
double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
return (fabs(a - b) <= maxVal * DBL_EPSILON);
}
/* Render the number nicely from the given item into a string. */
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
{
@@ -486,9 +552,9 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
double d = item->valuedouble;
int length = 0;
size_t i = 0;
unsigned char number_buffer[26]; /* temporary buffer to print the number into */
unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
unsigned char decimal_point = get_decimal_point();
double test;
double test = 0.0;
if (output_buffer == NULL)
{
@@ -496,24 +562,28 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
}
/* This checks for NaN and Infinity */
if ((d * 0) != 0)
if (isnan(d) || isinf(d))
{
length = sprintf((char*)number_buffer, "null");
}
else if(d == (double)item->valueint)
{
length = sprintf((char*)number_buffer, "%d", item->valueint);
}
else
{
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
length = sprintf((char*)number_buffer, "%1.15g", d);
/* Check whether the original double can be recovered */
if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d))
if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
{
/* If not, print with 17 decimal places of precision */
length = sprintf((char*)number_buffer, "%1.17g", d);
}
}
/* sprintf failed or buffer overrun occured */
/* sprintf failed or buffer overrun occurred */
if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
{
return false;
@@ -976,6 +1046,11 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
return NULL;
}
if (cannot_access_at_index(buffer, 0))
{
return buffer;
}
while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
{
buffer->offset++;
@@ -1005,8 +1080,23 @@ static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
return buffer;
}
/* Parse an object - create a new root, and populate. */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
{
size_t buffer_length;
if (NULL == value)
{
return NULL;
}
/* Adding null character size due to require_null_terminated. */
buffer_length = strlen(value) + sizeof("");
return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
}
/* Parse an object - create a new root, and populate. */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
{
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
cJSON *item = NULL;
@@ -1015,13 +1105,13 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
global_error.json = NULL;
global_error.position = 0;
if (value == NULL)
if (value == NULL || 0 == buffer_length)
{
goto fail;
}
buffer.content = (const unsigned char*)value;
buffer.length = strlen((const char*)value) + sizeof("");
buffer.length = buffer_length;
buffer.offset = 0;
buffer.hooks = global_hooks;
@@ -1091,7 +1181,12 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
return cJSON_ParseWithOpts(value, 0, 0);
}
#define cjson_min(a, b) ((a < b) ? a : b)
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
{
return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
}
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
{
@@ -1122,10 +1217,10 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
if (hooks->reallocate != NULL)
{
printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
buffer->buffer = NULL;
if (printed == NULL) {
goto fail;
}
buffer->buffer = NULL;
}
else /* otherwise copy the JSON over to a new buffer */
{
@@ -1198,20 +1293,20 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
return (char*)p.buffer;
}
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
{
printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
if ((len < 0) || (buf == NULL))
if ((length < 0) || (buffer == NULL))
{
return false;
}
p.buffer = (unsigned char*)buf;
p.length = (size_t)len;
p.buffer = (unsigned char*)buffer;
p.length = (size_t)length;
p.offset = 0;
p.noalloc = true;
p.format = fmt;
p.format = format;
p.hooks = global_hooks;
return print_value(item, &p);
@@ -1319,10 +1414,6 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp
size_t raw_length = 0;
if (item->valuestring == NULL)
{
if (!output_buffer->noalloc)
{
output_buffer->hooks.deallocate(output_buffer->buffer);
}
return false;
}
@@ -1428,6 +1519,10 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
success:
input_buffer->depth--;
if (head != NULL) {
head->prev = current_item;
}
item->type = cJSON_Array;
item->child = head;
@@ -1568,7 +1663,7 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
buffer_skip_whitespace(input_buffer);
if (!parse_string(current_item, input_buffer))
{
goto fail; /* faile to parse name */
goto fail; /* failed to parse name */
}
buffer_skip_whitespace(input_buffer);
@@ -1600,6 +1695,10 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
success:
input_buffer->depth--;
if (head != NULL) {
head->prev = current_item;
}
item->type = cJSON_Object;
item->child = head;
@@ -1688,7 +1787,7 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out
update_offset(output_buffer);
/* print comma if not last */
length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0));
length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
output_pointer = ensure(output_buffer, length + 1);
if (output_pointer == NULL)
{
@@ -1794,7 +1893,7 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
current_element = object->child;
if (case_sensitive)
{
while ((current_element != NULL) && (strcmp(name, current_element->string) != 0))
while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
{
current_element = current_element->next;
}
@@ -1807,6 +1906,10 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
}
}
if ((current_element == NULL) || (current_element->string == NULL)) {
return NULL;
}
return current_element;
}
@@ -1858,35 +1961,39 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{
cJSON *child = NULL;
if ((item == NULL) || (array == NULL))
if ((item == NULL) || (array == NULL) || (array == item))
{
return false;
}
child = array->child;
/*
* To find the last item in array quickly, we use prev in array
*/
if (child == NULL)
{
/* list is empty, start new one */
array->child = item;
item->prev = item;
item->next = NULL;
}
else
{
/* append to the end */
while (child->next)
if (child->prev)
{
child = child->next;
suffix_object(child->prev, item);
array->child->prev = item;
}
suffix_object(child, item);
}
return true;
}
/* Add item to array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
{
add_item_to_array(array, item);
return add_item_to_array(array, item);
}
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
@@ -1907,65 +2014,70 @@ static void* cast_away_const(const void* string)
static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
{
if ((object == NULL) || (string == NULL) || (item == NULL))
char *new_key = NULL;
int new_type = cJSON_Invalid;
if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
{
return false;
}
if (constant_key)
{
new_key = (char*)cast_away_const(string);
new_type = item->type | cJSON_StringIsConst;
}
else
{
new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
if (new_key == NULL)
{
return false;
}
new_type = item->type & ~cJSON_StringIsConst;
}
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
{
hooks->deallocate(item->string);
}
if (constant_key)
{
item->string = (char*)cast_away_const(string);
item->type |= cJSON_StringIsConst;
}
else
{
char *key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
if (key == NULL)
{
return false;
}
item->string = key;
item->type &= ~cJSON_StringIsConst;
}
item->string = new_key;
item->type = new_type;
return add_item_to_array(object, item);
}
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, false);
return add_item_to_object(object, string, item, &global_hooks, false);
}
/* Add an item to an object with constant string as key */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
{
add_item_to_object(object, string, item, &global_hooks, true);
return add_item_to_object(object, string, item, &global_hooks, true);
}
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
{
if (array == NULL)
{
return;
return false;
}
add_item_to_array(array, create_reference(item, &global_hooks));
return add_item_to_array(array, create_reference(item, &global_hooks));
}
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
{
if ((object == NULL) || (string == NULL))
{
return;
return false;
}
add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
}
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
@@ -2083,7 +2195,7 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it
return NULL;
}
if (item->prev != NULL)
if (item != parent->child)
{
/* not the first element */
item->prev->next = item->next;
@@ -2099,6 +2211,12 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it
/* first element */
parent->child = item->next;
}
else if (item->next == NULL)
{
/* last element */
parent->child->prev = item->prev;
}
/* make sure the detached item doesn't point anywhere anymore */
item->prev = NULL;
item->next = NULL;
@@ -2146,20 +2264,19 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const
}
/* Replace array/object items with new ones. */
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
{
cJSON *after_inserted = NULL;
if (which < 0)
{
return;
return false;
}
after_inserted = get_array_item(array, (size_t)which);
if (after_inserted == NULL)
{
add_item_to_array(array, newitem);
return;
return add_item_to_array(array, newitem);
}
newitem->next = after_inserted;
@@ -2173,6 +2290,7 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit
{
newitem->prev->next = newitem;
}
return true;
}
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
@@ -2194,13 +2312,27 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
{
replacement->next->prev = replacement;
}
if (parent->child == item)
{
if (parent->child->prev == parent->child)
{
replacement->prev = replacement;
}
parent->child = replacement;
}
else
{ /*
* To find the last item in array quickly, we use prev in array.
* We can't modify the last item's next pointer where this item was the parent's child
*/
if (replacement->prev != NULL)
{
replacement->prev->next = replacement;
}
if (parent->child == item)
if (replacement->next == NULL)
{
parent->child = replacement;
parent->child->prev = replacement;
}
}
item->next = NULL;
@@ -2210,14 +2342,14 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
return true;
}
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
{
if (which < 0)
{
return;
return false;
}
cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
}
static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
@@ -2233,21 +2365,24 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO
cJSON_free(replacement->string);
}
replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
if (replacement->string == NULL)
{
return false;
}
replacement->type &= ~cJSON_StringIsConst;
cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
return true;
return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
}
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
{
replace_item_in_object(object, string, newitem, false);
return replace_item_in_object(object, string, newitem, false);
}
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
{
replace_item_in_object(object, string, newitem, true);
return replace_item_in_object(object, string, newitem, true);
}
/* Create basic types: */
@@ -2284,12 +2419,12 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
return item;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
{
cJSON *item = cJSON_New_Item(&global_hooks);
if(item)
{
item->type = b ? cJSON_True : cJSON_False;
item->type = boolean ? cJSON_True : cJSON_False;
}
return item;
@@ -2308,7 +2443,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
{
item->valueint = INT_MAX;
}
else if (num <= INT_MIN)
else if (num <= (double)INT_MIN)
{
item->valueint = INT_MIN;
}
@@ -2424,6 +2559,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
}
a = cJSON_CreateArray();
for(i = 0; a && (i < (size_t)count); i++)
{
n = cJSON_CreateNumber(numbers[i]);
@@ -2443,6 +2579,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
@@ -2479,6 +2619,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
@@ -2496,7 +2640,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
a = cJSON_CreateArray();
for(i = 0;a && (i < (size_t)count); i++)
for(i = 0; a && (i < (size_t)count); i++)
{
n = cJSON_CreateNumber(numbers[i]);
if(!n)
@@ -2515,10 +2659,14 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
{
size_t i = 0;
cJSON *n = NULL;
@@ -2551,6 +2699,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
@@ -2622,6 +2774,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
}
child = child->next;
}
if (newitem && newitem->child)
{
newitem->child->prev = newchild;
}
return newitem;
@@ -2634,69 +2790,96 @@ fail:
return NULL;
}
static void skip_oneline_comment(char **input)
{
*input += static_strlen("//");
for (; (*input)[0] != '\0'; ++(*input))
{
if ((*input)[0] == '\n') {
*input += static_strlen("\n");
return;
}
}
}
static void skip_multiline_comment(char **input)
{
*input += static_strlen("/*");
for (; (*input)[0] != '\0'; ++(*input))
{
if (((*input)[0] == '*') && ((*input)[1] == '/'))
{
*input += static_strlen("*/");
return;
}
}
}
static void minify_string(char **input, char **output) {
(*output)[0] = (*input)[0];
*input += static_strlen("\"");
*output += static_strlen("\"");
for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
(*output)[0] = (*input)[0];
if ((*input)[0] == '\"') {
(*output)[0] = '\"';
*input += static_strlen("\"");
*output += static_strlen("\"");
return;
} else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
(*output)[1] = (*input)[1];
*input += static_strlen("\"");
*output += static_strlen("\"");
}
}
}
CJSON_PUBLIC(void) cJSON_Minify(char *json)
{
unsigned char *into = (unsigned char*)json;
char *into = json;
if (json == NULL)
{
return;
}
while (*json)
while (json[0] != '\0')
{
if (*json == ' ')
switch (json[0])
{
case ' ':
case '\t':
case '\r':
case '\n':
json++;
break;
case '/':
if (json[1] == '/')
{
skip_oneline_comment(&json);
}
else if (json[1] == '*')
{
skip_multiline_comment(&json);
} else {
json++;
}
else if (*json == '\t')
{
/* Whitespace characters. */
break;
case '\"':
minify_string(&json, (char**)&into);
break;
default:
into[0] = json[0];
json++;
}
else if (*json == '\r')
{
json++;
}
else if (*json=='\n')
{
json++;
}
else if ((*json == '/') && (json[1] == '/'))
{
/* double-slash comments, to end of line. */
while (*json && (*json != '\n'))
{
json++;
}
}
else if ((*json == '/') && (json[1] == '*'))
{
/* multiline comments. */
while (*json && !((*json == '*') && (json[1] == '/')))
{
json++;
}
json += 2;
}
else if (*json == '\"')
{
/* string literals, which are \" sensitive. */
*into++ = (unsigned char)*json++;
while (*json && (*json != '\"'))
{
if (*json == '\\')
{
*into++ = (unsigned char)*json++;
}
*into++ = (unsigned char)*json++;
}
*into++ = (unsigned char)*json++;
}
else
{
/* All other characters. */
*into++ = (unsigned char)*json++;
into++;
}
}
@@ -2806,7 +2989,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
{
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
{
return false;
}
@@ -2843,7 +3026,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
return true;
case cJSON_Number:
if (a->valuedouble == b->valuedouble)
if (compare_double(a->valuedouble, b->valuedouble))
{
return true;
}