提交 3045fef9 编写于 作者: W wuxn9999 提交者: Jinliang Li

Upgrade cJSON from version 1.6.0 to 1.7.15 (#1391)

* Upgrade cJSON from version 1.7.8 to 1.7.15.
Signed-off-by: N福明 <wuxiangnan.wxn@alibaba-inc.com>

* Upgrade cJSON from version 1.7.12 to 1.7.15.
Signed-off-by: N福明 <wuxiangnan.wxn@alibaba-inc.com>
上级 cd80b188
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <ctype.h> #include <ctype.h>
#include <float.h>
#ifdef ENABLE_LOCALES #ifdef ENABLE_LOCALES
#include <locale.h> #include <locale.h>
...@@ -68,6 +69,22 @@ ...@@ -68,6 +69,22 @@
#endif #endif
#define false ((cJSON_bool)0) #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 { typedef struct {
const unsigned char *json; const unsigned char *json;
size_t position; size_t position;
...@@ -79,16 +96,28 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) ...@@ -79,16 +96,28 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
return (const char*) (global_error.json + global_error.position); return (const char*) (global_error.json + global_error.position);
} }
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) { CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
if (!cJSON_IsString(item)) { {
if (!cJSON_IsString(item))
{
return NULL; return NULL;
} }
return item->valuestring; 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 */ /* 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 != 12) #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. #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif #endif
...@@ -132,7 +161,7 @@ typedef struct internal_hooks ...@@ -132,7 +161,7 @@ typedef struct internal_hooks
} internal_hooks; } internal_hooks;
#if defined(_MSC_VER) #if defined(_MSC_VER)
/* work around MSVC error C2322: '...' address of dillimport '...' is not static */ /* work around MSVC error C2322: '...' address of dllimport '...' is not static */
static void * CJSON_CDECL internal_malloc(size_t size) static void * CJSON_CDECL internal_malloc(size_t size)
{ {
return malloc(size); return malloc(size);
...@@ -368,6 +397,33 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) ...@@ -368,6 +397,33 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
return object->valuedouble = 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 typedef struct
{ {
unsigned char *buffer; unsigned char *buffer;
...@@ -455,10 +511,8 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) ...@@ -455,10 +511,8 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
return NULL; return NULL;
} }
if (newbuffer)
{ memcpy(newbuffer, p->buffer, p->offset + 1);
memcpy(newbuffer, p->buffer, p->offset + 1);
}
p->hooks.deallocate(p->buffer); p->hooks.deallocate(p->buffer);
} }
p->length = newsize; p->length = newsize;
...@@ -480,6 +534,13 @@ static void update_offset(printbuffer * const buffer) ...@@ -480,6 +534,13 @@ static void update_offset(printbuffer * const buffer)
buffer->offset += strlen((const char*)buffer_pointer); 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. */ /* Render the number nicely from the given item into a string. */
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
{ {
...@@ -487,9 +548,9 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out ...@@ -487,9 +548,9 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
double d = item->valuedouble; double d = item->valuedouble;
int length = 0; int length = 0;
size_t i = 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(); unsigned char decimal_point = get_decimal_point();
double test; double test = 0.0;
if (output_buffer == NULL) if (output_buffer == NULL)
{ {
...@@ -497,7 +558,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out ...@@ -497,7 +558,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
} }
/* This checks for NaN and Infinity */ /* This checks for NaN and Infinity */
if ((d * 0) != 0) if (isnan(d) || isinf(d))
{ {
length = sprintf((char*)number_buffer, "null"); length = sprintf((char*)number_buffer, "null");
} }
...@@ -507,7 +568,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out ...@@ -507,7 +568,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
length = sprintf((char*)number_buffer, "%1.15g", d); length = sprintf((char*)number_buffer, "%1.15g", d);
/* Check whether the original double can be recovered */ /* 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 */ /* If not, print with 17 decimal places of precision */
length = sprintf((char*)number_buffer, "%1.17g", d); length = sprintf((char*)number_buffer, "%1.17g", d);
...@@ -977,6 +1038,11 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) ...@@ -977,6 +1038,11 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
return NULL; return NULL;
} }
if (cannot_access_at_index(buffer, 0))
{
return buffer;
}
while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
{ {
buffer->offset++; buffer->offset++;
...@@ -1006,8 +1072,23 @@ static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) ...@@ -1006,8 +1072,23 @@ static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
return 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) 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 } }; parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
cJSON *item = NULL; cJSON *item = NULL;
...@@ -1016,13 +1097,13 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return ...@@ -1016,13 +1097,13 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
global_error.json = NULL; global_error.json = NULL;
global_error.position = 0; global_error.position = 0;
if (value == NULL) if (value == NULL || 0 == buffer_length)
{ {
goto fail; goto fail;
} }
buffer.content = (const unsigned char*)value; buffer.content = (const unsigned char*)value;
buffer.length = strlen((const char*)value) + sizeof(""); buffer.length = buffer_length;
buffer.offset = 0; buffer.offset = 0;
buffer.hooks = global_hooks; buffer.hooks = global_hooks;
...@@ -1092,7 +1173,12 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) ...@@ -1092,7 +1173,12 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
return cJSON_ParseWithOpts(value, 0, 0); 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) static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
{ {
...@@ -1199,20 +1285,20 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON ...@@ -1199,20 +1285,20 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
return (char*)p.buffer; 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 } }; printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
if ((len < 0) || (buf == NULL)) if ((length < 0) || (buffer == NULL))
{ {
return false; return false;
} }
p.buffer = (unsigned char*)buf; p.buffer = (unsigned char*)buffer;
p.length = (size_t)len; p.length = (size_t)length;
p.offset = 0; p.offset = 0;
p.noalloc = true; p.noalloc = true;
p.format = fmt; p.format = format;
p.hooks = global_hooks; p.hooks = global_hooks;
return print_value(item, &p); return print_value(item, &p);
...@@ -1425,6 +1511,10 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf ...@@ -1425,6 +1511,10 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
success: success:
input_buffer->depth--; input_buffer->depth--;
if (head != NULL) {
head->prev = current_item;
}
item->type = cJSON_Array; item->type = cJSON_Array;
item->child = head; item->child = head;
...@@ -1597,6 +1687,10 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu ...@@ -1597,6 +1687,10 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
success: success:
input_buffer->depth--; input_buffer->depth--;
if (head != NULL) {
head->prev = current_item;
}
item->type = cJSON_Object; item->type = cJSON_Object;
item->child = head; item->child = head;
...@@ -1859,35 +1953,39 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) ...@@ -1859,35 +1953,39 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{ {
cJSON *child = NULL; cJSON *child = NULL;
if ((item == NULL) || (array == NULL)) if ((item == NULL) || (array == NULL) || (array == item))
{ {
return false; return false;
} }
child = array->child; child = array->child;
/*
* To find the last item in array quickly, we use prev in array
*/
if (child == NULL) if (child == NULL)
{ {
/* list is empty, start new one */ /* list is empty, start new one */
array->child = item; array->child = item;
item->prev = item;
item->next = NULL;
} }
else else
{ {
/* append to the end */ /* 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; return true;
} }
/* Add item to array/object. */ /* 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)))) #if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
...@@ -1911,7 +2009,7 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st ...@@ -1911,7 +2009,7 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st
char *new_key = NULL; char *new_key = NULL;
int new_type = cJSON_Invalid; int new_type = cJSON_Invalid;
if ((object == NULL) || (string == NULL) || (item == NULL)) if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
{ {
return false; return false;
} }
...@@ -1943,35 +2041,35 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st ...@@ -1943,35 +2041,35 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st
return add_item_to_array(object, item); 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 */ /* 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) 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)) 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) CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
...@@ -2089,7 +2187,7 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it ...@@ -2089,7 +2187,7 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it
return NULL; return NULL;
} }
if (item->prev != NULL) if (item != parent->child)
{ {
/* not the first element */ /* not the first element */
item->prev->next = item->next; item->prev->next = item->next;
...@@ -2105,6 +2203,12 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it ...@@ -2105,6 +2203,12 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it
/* first element */ /* first element */
parent->child = item->next; 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 */ /* make sure the detached item doesn't point anywhere anymore */
item->prev = NULL; item->prev = NULL;
item->next = NULL; item->next = NULL;
...@@ -2152,20 +2256,19 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const ...@@ -2152,20 +2256,19 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const
} }
/* Replace array/object items with new ones. */ /* 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; cJSON *after_inserted = NULL;
if (which < 0) if (which < 0)
{ {
return; return false;
} }
after_inserted = get_array_item(array, (size_t)which); after_inserted = get_array_item(array, (size_t)which);
if (after_inserted == NULL) if (after_inserted == NULL)
{ {
add_item_to_array(array, newitem); return add_item_to_array(array, newitem);
return;
} }
newitem->next = after_inserted; newitem->next = after_inserted;
...@@ -2179,6 +2282,7 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit ...@@ -2179,6 +2282,7 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit
{ {
newitem->prev->next = newitem; newitem->prev->next = newitem;
} }
return true;
} }
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
...@@ -2200,14 +2304,28 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON ...@@ -2200,14 +2304,28 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
{ {
replacement->next->prev = replacement; replacement->next->prev = replacement;
} }
if (replacement->prev != NULL)
{
replacement->prev->next = replacement;
}
if (parent->child == item) if (parent->child == item)
{ {
if (parent->child->prev == parent->child)
{
replacement->prev = replacement;
}
parent->child = 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 (replacement->next == NULL)
{
parent->child->prev = replacement;
}
}
item->next = NULL; item->next = NULL;
item->prev = NULL; item->prev = NULL;
...@@ -2216,14 +2334,14 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON ...@@ -2216,14 +2334,14 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
return true; 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) 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) static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
...@@ -2241,19 +2359,17 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO ...@@ -2241,19 +2359,17 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO
replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
replacement->type &= ~cJSON_StringIsConst; replacement->type &= ~cJSON_StringIsConst;
cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
return true;
} }
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: */ /* Create basic types: */
...@@ -2290,12 +2406,12 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) ...@@ -2290,12 +2406,12 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
return item; 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); cJSON *item = cJSON_New_Item(&global_hooks);
if(item) if(item)
{ {
item->type = b ? cJSON_True : cJSON_False; item->type = boolean ? cJSON_True : cJSON_False;
} }
return item; return item;
...@@ -2430,6 +2546,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) ...@@ -2430,6 +2546,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
} }
a = cJSON_CreateArray(); 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]); n = cJSON_CreateNumber(numbers[i]);
...@@ -2449,6 +2566,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) ...@@ -2449,6 +2566,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
p = n; p = n;
} }
if (a && a->child) {
a->child->prev = n;
}
return a; return a;
} }
...@@ -2485,6 +2606,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) ...@@ -2485,6 +2606,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
p = n; p = n;
} }
if (a && a->child) {
a->child->prev = n;
}
return a; return a;
} }
...@@ -2502,7 +2627,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) ...@@ -2502,7 +2627,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
a = cJSON_CreateArray(); 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]); n = cJSON_CreateNumber(numbers[i]);
if(!n) if(!n)
...@@ -2521,10 +2646,14 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) ...@@ -2521,10 +2646,14 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
p = n; p = n;
} }
if (a && a->child) {
a->child->prev = n;
}
return a; 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; size_t i = 0;
cJSON *n = NULL; cJSON *n = NULL;
...@@ -2557,6 +2686,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count) ...@@ -2557,6 +2686,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
p = n; p = n;
} }
if (a && a->child) {
a->child->prev = n;
}
return a; return a;
} }
...@@ -2628,6 +2761,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) ...@@ -2628,6 +2761,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
} }
child = child->next; child = child->next;
} }
if (newitem && newitem->child)
{
newitem->child->prev = newchild;
}
return newitem; return newitem;
...@@ -2839,7 +2976,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) ...@@ -2839,7 +2976,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) 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; return false;
} }
...@@ -2876,7 +3013,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons ...@@ -2876,7 +3013,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
return true; return true;
case cJSON_Number: case cJSON_Number:
if (a->valuedouble == b->valuedouble) if (compare_double(a->valuedouble, b->valuedouble))
{ {
return true; return true;
} }
......
...@@ -81,7 +81,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ ...@@ -81,7 +81,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
/* project version */ /* project version */
#define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7 #define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 12 #define CJSON_VERSION_PATCH 15
#include <stddef.h> #include <stddef.h>
...@@ -146,9 +146,11 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); ...@@ -146,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. */ /* 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. */ /* 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_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. */ /* 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(). */ /* 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_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. */ /* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
...@@ -160,7 +162,7 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON ...@@ -160,7 +162,7 @@ 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 */ /* 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); CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */ /* 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). */ /* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
...@@ -173,8 +175,9 @@ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *st ...@@ -173,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. */ /* 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); CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check if the item is a string and return its valuestring */ /* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); 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 */ /* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
...@@ -203,29 +206,30 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); ...@@ -203,29 +206,30 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so /* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */ * it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); 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 */ * they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(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_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *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_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. */ /* Append item to the specified array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *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);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. /* 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 * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */ * 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. */ /* 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(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
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);
/* 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_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
...@@ -235,22 +239,24 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) ...@@ -235,22 +239,24 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */ /* 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(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(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
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);
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);
/* Duplicate a cJSON item */ /* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); 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 /* 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. * 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. */ * 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. /* 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) */ * 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); 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); CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time. /* Helper functions for creating and adding items to an object at the same time.
...@@ -270,6 +276,8 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c ...@@ -270,6 +276,8 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c
/* helper for the cJSON_SetNumberValue macro */ /* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (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);
/* Macro for iterating over an array or object */ /* 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) #define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
......
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
#include <math.h>
#include <float.h>
#include <math.h>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning (pop) #pragma warning (pop)
...@@ -105,6 +108,14 @@ static int compare_strings(const unsigned char *string1, const unsigned char *st ...@@ -105,6 +108,14 @@ static int compare_strings(const unsigned char *string1, const unsigned char *st
return tolower(*string1) - tolower(*string2); return tolower(*string1) - tolower(*string2);
} }
/* 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);
}
/* Compare the next path element of two JSON pointers, two NULL pointers are considered unequal: */ /* Compare the next path element of two JSON pointers, two NULL pointers are considered unequal: */
static cJSON_bool compare_pointers(const unsigned char *name, const unsigned char *pointer, const cJSON_bool case_sensitive) static cJSON_bool compare_pointers(const unsigned char *name, const unsigned char *pointer, const cJSON_bool case_sensitive)
{ {
...@@ -165,13 +176,14 @@ static void encode_string_as_pointer(unsigned char *destination, const unsigned ...@@ -165,13 +176,14 @@ static void encode_string_as_pointer(unsigned char *destination, const unsigned
{ {
if (source[0] == '/') if (source[0] == '/')
{ {
destination[0] = '~';
destination[1] = '1'; destination[1] = '1';
destination++; destination++;
} }
else if (source[0] == '~') else if (source[0] == '~')
{ {
destination[0] = '~'; destination[0] = '~';
destination[1] = '1'; destination[1] = '0';
destination++; destination++;
} }
else else
...@@ -216,6 +228,7 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje ...@@ -216,6 +228,7 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje
if (child_index > ULONG_MAX) if (child_index > ULONG_MAX)
{ {
cJSON_free(target_pointer); cJSON_free(target_pointer);
cJSON_free(full_pointer);
return NULL; return NULL;
} }
sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* /<array_index><path> */ sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* /<array_index><path> */
...@@ -390,7 +403,7 @@ static cJSON *detach_item_from_array(cJSON *array, size_t which) ...@@ -390,7 +403,7 @@ static cJSON *detach_item_from_array(cJSON *array, size_t which)
/* item doesn't exist */ /* item doesn't exist */
return NULL; return NULL;
} }
if (c->prev) if (c != array->child)
{ {
/* not the first element */ /* not the first element */
c->prev->next = c->next; c->prev->next = c->next;
...@@ -399,10 +412,14 @@ static cJSON *detach_item_from_array(cJSON *array, size_t which) ...@@ -399,10 +412,14 @@ static cJSON *detach_item_from_array(cJSON *array, size_t which)
{ {
c->next->prev = c->prev; c->next->prev = c->prev;
} }
if (c==array->child) if (c == array->child)
{ {
array->child = c->next; array->child = c->next;
} }
else if (c->next == NULL)
{
array->child->prev = c->prev;
}
/* make sure the detached item doesn't point anywhere anymore */ /* make sure the detached item doesn't point anywhere anymore */
c->prev = c->next = NULL; c->prev = c->next = NULL;
...@@ -595,7 +612,7 @@ static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensiti ...@@ -595,7 +612,7 @@ static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensiti
{ {
case cJSON_Number: case cJSON_Number:
/* numeric mismatch. */ /* numeric mismatch. */
if ((a->valueint != b->valueint) || (a->valuedouble != b->valuedouble)) if ((a->valueint != b->valueint) || (!compare_double(a->valuedouble, b->valuedouble)))
{ {
return false; return false;
} }
...@@ -943,7 +960,9 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_ ...@@ -943,7 +960,9 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_
/* split pointer in parent and child */ /* split pointer in parent and child */
parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring); parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring);
child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); if (parent_pointer) {
child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/');
}
if (child_pointer != NULL) if (child_pointer != NULL)
{ {
child_pointer[0] = '\0'; child_pointer[0] = '\0';
...@@ -1135,7 +1154,7 @@ static void create_patches(cJSON * const patches, const unsigned char * const pa ...@@ -1135,7 +1154,7 @@ static void create_patches(cJSON * const patches, const unsigned char * const pa
switch (from->type & 0xFF) switch (from->type & 0xFF)
{ {
case cJSON_Number: case cJSON_Number:
if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble)) if ((from->valueint != to->valueint) || !compare_double(from->valuedouble, to->valuedouble))
{ {
compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); compose_patch(patches, (const unsigned char*)"replace", path, NULL, to);
} }
...@@ -1389,6 +1408,10 @@ static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const c ...@@ -1389,6 +1408,10 @@ static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const c
from_child = from->child; from_child = from->child;
to_child = to->child; to_child = to->child;
patch = cJSON_CreateObject(); patch = cJSON_CreateObject();
if (patch == NULL)
{
return NULL;
}
while (from_child || to_child) while (from_child || to_child)
{ {
int diff; int diff;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册