Upgrade cJSON version to v1.7.16 (#2404)

This commit is contained in:
Cengizhan Pasaoglu 2023-07-31 13:14:50 +03:00 committed by GitHub
parent b1fa27e91d
commit 45a4e774de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 423 additions and 220 deletions

View File

@ -22,7 +22,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
| third party components | version number | latest release | vendor pages | CVE details | | third party components | version number | latest release | vendor pages | CVE details |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| cjson | 1.7.10 | 1.7.14 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html | | cjson | 1.7.16 | 1.7.16 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html |
| contiki-ng (er-coap) | unspecified | 3.0 | https://github.com/contiki-os/contiki | https://www.cvedetails.com/vendor/16528/Contiki-os.html | | contiki-ng (er-coap) | unspecified | 3.0 | https://github.com/contiki-os/contiki | https://www.cvedetails.com/vendor/16528/Contiki-os.html |
| freebsd libm | unspecified | 13.0 | https://www.freebsd.org/ | https://www.cvedetails.com/vendor/6/Freebsd.html | | freebsd libm | unspecified | 13.0 | https://www.freebsd.org/ | https://www.cvedetails.com/vendor/6/Freebsd.html |
| LVGL | 6.0.1 | 7.11.0 | https://lvgl.io/ | | | LVGL | 6.0.1 | 7.11.0 | https://lvgl.io/ | |

View File

@ -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>
@ -58,9 +59,33 @@
#include "cJSON.h" #include "cJSON.h"
/* define our own boolean type */ /* define our own boolean type */
#ifdef true
#undef true
#endif
#define true ((cJSON_bool)1) #define true ((cJSON_bool)1)
#ifdef false
#undef false
#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;
@ -72,7 +97,7 @@ 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;
@ -81,18 +106,27 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item)
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 /* This is a safeguard to prevent copy-pasters from using incompatible C and
* header files */ * header files */
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) \ #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) \
|| (CJSON_VERSION_PATCH != 10) || (CJSON_VERSION_PATCH != 16)
#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
CJSON_PUBLIC(const char *) cJSON_Version(void) CJSON_PUBLIC(const char *) cJSON_Version(void)
{ {
static char version[15]; static char version[15];
snprintf(version, sizeof(version), "%i.%i.%i", CJSON_VERSION_MAJOR, sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR,
CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); CJSON_VERSION_PATCH);
return version; return version;
} }
@ -127,8 +161,8 @@ typedef struct internal_hooks {
} internal_hooks; } internal_hooks;
#if defined(_MSC_VER) #if defined(_MSC_VER)
/* work around MSVC error C2322: '...' address of dillimport '...' /* work around MSVC error C2322: '...' address of dllimport '...' is not static
is not static */ */
static void *CJSON_CDECL static void *CJSON_CDECL
internal_malloc(size_t size) internal_malloc(size_t size)
{ {
@ -150,13 +184,11 @@ internal_realloc(void *pointer, size_t size)
#define internal_realloc realloc #define internal_realloc realloc
#endif #endif
/* clang-format off */ /* strlen of character literals resolved at compile time */
static internal_hooks global_hooks = { #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
internal_malloc,
internal_free, static internal_hooks global_hooks = { internal_malloc, internal_free,
internal_realloc internal_realloc };
};
/* clang-format on */
static unsigned char * static unsigned char *
cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks)
@ -271,8 +303,8 @@ typedef struct {
/* get a pointer to the buffer at the position */ /* get a pointer to the buffer at the position */
#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
/* Parse the input text to generate a number, and populate the result /* Parse the input text to generate a number, and populate the result into item.
into item. */ */
static cJSON_bool static cJSON_bool
parse_number(cJSON *const item, parse_buffer *const input_buffer) parse_number(cJSON *const item, parse_buffer *const input_buffer)
{ {
@ -287,9 +319,8 @@ parse_number(cJSON *const item, parse_buffer *const input_buffer)
} }
/* copy the number into a temporary buffer and replace '.' with the decimal /* copy the number into a temporary buffer and replace '.' with the decimal
* point of the current locale (for strtod) * point of the current locale (for strtod) This also takes care of '\0' not
* This also takes care of '\0' not necessarily being available for marking * necessarily being available for marking the end of the input */
* the end of the input */
for (i = 0; (i < (sizeof(number_c_string) - 1)) for (i = 0; (i < (sizeof(number_c_string) - 1))
&& can_access_at_index(input_buffer, i); && can_access_at_index(input_buffer, i);
i++) { i++) {
@ -363,6 +394,32 @@ 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;
size_t length; size_t length;
@ -438,9 +495,8 @@ 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;
@ -463,6 +519,14 @@ 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 static cJSON_bool
print_number(const cJSON *const item, printbuffer *const output_buffer) print_number(const cJSON *const item, printbuffer *const output_buffer)
@ -471,35 +535,37 @@ print_number(const cJSON *const item, printbuffer *const output_buffer)
double d = item->valuedouble; double d = item->valuedouble;
int length = 0; int length = 0;
size_t i = 0; size_t i = 0;
unsigned char unsigned char number_buffer[26] = {
number_buffer[26]; /* temporary buffer to print the number into */ 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) {
return false; return false;
} }
/* This checks for NaN and Infinity */ /* This checks for NaN and Infinity */
if ((d * 0) != 0) { if (isnan(d) || isinf(d)) {
length = snprintf((char *)number_buffer, sizeof(number_buffer), "null"); length = sprintf((char *)number_buffer, "null");
}
else if (d == (double)item->valueint) {
length = sprintf((char *)number_buffer, "%d", item->valueint);
} }
else { else {
/* Try 15 decimal places of precision to avoid nonsignificant nonzero /* Try 15 decimal places of precision to avoid nonsignificant nonzero
* digits */ * digits */
length = length = sprintf((char *)number_buffer, "%1.15g", d);
snprintf((char *)number_buffer, sizeof(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) if ((sscanf((char *)number_buffer, "%lg", &test) != 1)
|| ((double)test != d)) { || !compare_double((double)test, d)) {
/* If not, print with 17 decimal places of precision */ /* If not, print with 17 decimal places of precision */
length = snprintf((char *)number_buffer, sizeof(number_buffer), length = sprintf((char *)number_buffer, "%1.17g", d);
"%1.17g", d);
} }
} }
/* snprintf failed or buffer overrun occured */ /* sprintf failed or buffer overrun occurred */
if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
return false; return false;
} }
@ -709,8 +775,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer)
if (((size_t)(input_end - input_buffer->content) if (((size_t)(input_end - input_buffer->content)
>= input_buffer->length) >= input_buffer->length)
|| (*input_end != '\"')) { || (*input_end != '\"')) {
goto fail; goto fail; /* string ended unexpectedly */
/* string ended unexpectedly */
} }
/* This is at most how much we need for the output */ /* This is at most how much we need for the output */
@ -719,8 +784,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer)
output = (unsigned char *)input_buffer->hooks.allocate(allocation_length output = (unsigned char *)input_buffer->hooks.allocate(allocation_length
+ sizeof("")); + sizeof(""));
if (output == NULL) { if (output == NULL) {
goto fail; goto fail; /* allocation failure */
/* allocation failure */
} }
} }
@ -805,7 +869,7 @@ print_string_ptr(const unsigned char *const input,
printbuffer *const output_buffer) printbuffer *const output_buffer)
{ {
const unsigned char *input_pointer = NULL; const unsigned char *input_pointer = NULL;
unsigned char *output = NULL, *output_end; unsigned char *output = NULL;
unsigned char *output_pointer = NULL; unsigned char *output_pointer = NULL;
size_t output_length = 0; size_t output_length = 0;
/* numbers of additional characters needed for escaping */ /* numbers of additional characters needed for escaping */
@ -853,7 +917,6 @@ print_string_ptr(const unsigned char *const input,
if (output == NULL) { if (output == NULL) {
return false; return false;
} }
output_end = output + output_length + sizeof("\"\"");
/* no characters have to be escaped */ /* no characters have to be escaped */
if (escape_characters == 0) { if (escape_characters == 0) {
@ -902,9 +965,7 @@ print_string_ptr(const unsigned char *const input,
break; break;
default: default:
/* escape and print as unicode codepoint */ /* escape and print as unicode codepoint */
snprintf((char *)output_pointer, sprintf((char *)output_pointer, "u%04x", *input_pointer);
output_end - output_pointer, "u%04x",
*input_pointer);
output_pointer += 4; output_pointer += 4;
break; break;
} }
@ -945,6 +1006,10 @@ 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) while (can_access_at_index(buffer, 0)
&& (buffer_at_offset(buffer)[0] <= 32)) { && (buffer_at_offset(buffer)[0] <= 32)) {
buffer->offset++; buffer->offset++;
@ -975,10 +1040,28 @@ skip_utf8_bom(parse_buffer *const buffer)
return buffer; return buffer;
} }
/* Parse an object - create a new root, and populate. */
CJSON_PUBLIC(cJSON *) CJSON_PUBLIC(cJSON *)
cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_ParseWithOpts(const char *value, const char **return_parse_end,
cJSON_bool require_null_terminated) 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;
@ -987,12 +1070,12 @@ cJSON_ParseWithOpts(const char *value, const char **return_parse_end,
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;
@ -1056,7 +1139,13 @@ 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 * static unsigned char *
print(const cJSON *const item, cJSON_bool format, print(const cJSON *const item, cJSON_bool format,
@ -1113,6 +1202,10 @@ fail:
hooks->deallocate(buffer->buffer); hooks->deallocate(buffer->buffer);
} }
if (printed != NULL) {
hooks->deallocate(printed);
}
return NULL; return NULL;
} }
@ -1156,20 +1249,20 @@ cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
} }
CJSON_PUBLIC(cJSON_bool) CJSON_PUBLIC(cJSON_bool)
cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length,
const cJSON_bool fmt) 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);
@ -1341,8 +1434,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer)
/* allocate next item */ /* allocate next item */
cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
if (new_item == NULL) { if (new_item == NULL) {
goto fail; goto fail; /* allocation failure */
/* allocation failure */
} }
/* attach next item to list */ /* attach next item to list */
@ -1361,8 +1453,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer)
input_buffer->offset++; input_buffer->offset++;
buffer_skip_whitespace(input_buffer); buffer_skip_whitespace(input_buffer);
if (!parse_value(current_item, input_buffer)) { if (!parse_value(current_item, input_buffer)) {
goto fail; goto fail; /* failed to parse value */
/* failed to parse value */
} }
buffer_skip_whitespace(input_buffer); buffer_skip_whitespace(input_buffer);
} while (can_access_at_index(input_buffer, 0) } while (can_access_at_index(input_buffer, 0)
@ -1370,13 +1461,16 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer)
if (cannot_access_at_index(input_buffer, 0) if (cannot_access_at_index(input_buffer, 0)
|| buffer_at_offset(input_buffer)[0] != ']') { || buffer_at_offset(input_buffer)[0] != ']') {
goto fail; goto fail; /* expected end of array */
/* expected end of array */
} }
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;
@ -1461,16 +1555,14 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer)
if (cannot_access_at_index(input_buffer, 0) if (cannot_access_at_index(input_buffer, 0)
|| (buffer_at_offset(input_buffer)[0] != '{')) { || (buffer_at_offset(input_buffer)[0] != '{')) {
goto fail; goto fail; /* not an object */
/* not an object */
} }
input_buffer->offset++; input_buffer->offset++;
buffer_skip_whitespace(input_buffer); buffer_skip_whitespace(input_buffer);
if (can_access_at_index(input_buffer, 0) if (can_access_at_index(input_buffer, 0)
&& (buffer_at_offset(input_buffer)[0] == '}')) { && (buffer_at_offset(input_buffer)[0] == '}')) {
goto success; goto success; /* empty object */
/* empty object */
} }
/* check if we skipped to the end of the buffer */ /* check if we skipped to the end of the buffer */
@ -1486,8 +1578,7 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer)
/* allocate next item */ /* allocate next item */
cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
if (new_item == NULL) { if (new_item == NULL) {
goto fail; goto fail; /* allocation failure */
/* allocation failure */
} }
/* attach next item to list */ /* attach next item to list */
@ -1506,8 +1597,7 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer)
input_buffer->offset++; input_buffer->offset++;
buffer_skip_whitespace(input_buffer); buffer_skip_whitespace(input_buffer);
if (!parse_string(current_item, input_buffer)) { if (!parse_string(current_item, input_buffer)) {
goto fail; goto fail; /* failed to parse name */
/* faile to parse name */
} }
buffer_skip_whitespace(input_buffer); buffer_skip_whitespace(input_buffer);
@ -1517,16 +1607,14 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer)
if (cannot_access_at_index(input_buffer, 0) if (cannot_access_at_index(input_buffer, 0)
|| (buffer_at_offset(input_buffer)[0] != ':')) { || (buffer_at_offset(input_buffer)[0] != ':')) {
goto fail; goto fail; /* invalid object */
/* invalid object */
} }
/* parse the value */ /* parse the value */
input_buffer->offset++; input_buffer->offset++;
buffer_skip_whitespace(input_buffer); buffer_skip_whitespace(input_buffer);
if (!parse_value(current_item, input_buffer)) { if (!parse_value(current_item, input_buffer)) {
goto fail; goto fail; /* failed to parse value */
/* failed to parse value */
} }
buffer_skip_whitespace(input_buffer); buffer_skip_whitespace(input_buffer);
} while (can_access_at_index(input_buffer, 0) } while (can_access_at_index(input_buffer, 0)
@ -1534,13 +1622,16 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer)
if (cannot_access_at_index(input_buffer, 0) if (cannot_access_at_index(input_buffer, 0)
|| (buffer_at_offset(input_buffer)[0] != '}')) { || (buffer_at_offset(input_buffer)[0] != '}')) {
goto fail; goto fail; /* expected end of object */
/* expected end of object */
} }
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;
@ -1792,22 +1883,26 @@ 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;
@ -1847,7 +1942,8 @@ add_item_to_object(cJSON *const object, const char *const string,
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;
} }
@ -2028,7 +2124,7 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item)
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;
} }
@ -2041,6 +2137,11 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item)
/* 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;
@ -2121,7 +2222,8 @@ CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item,
cJSON *replacement) cJSON *replacement)
{ {
if ((parent == NULL) || (replacement == NULL) || (item == NULL)) { if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL)
|| (item == NULL)) {
return false; return false;
} }
@ -2135,11 +2237,23 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item,
if (replacement->next != NULL) { if (replacement->next != NULL) {
replacement->next->prev = replacement; 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) { if (replacement->prev != NULL) {
replacement->prev->next = replacement; replacement->prev->next = replacement;
} }
if (parent->child == item) { if (replacement->next == NULL) {
parent->child = replacement; parent->child->prev = replacement;
}
} }
item->next = NULL; item->next = NULL;
@ -2149,15 +2263,15 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item,
return true; return true;
} }
CJSON_PUBLIC(void) CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) 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), return cJSON_ReplaceItemViaPointer(
newitem); array, get_array_item(array, (size_t)which), newitem);
} }
static cJSON_bool static cJSON_bool
@ -2175,25 +2289,27 @@ replace_item_in_object(cJSON *object, const char *string, cJSON *replacement,
} }
replacement->string = replacement->string =
(char *)cJSON_strdup((const unsigned char *)string, &global_hooks); (char *)cJSON_strdup((const unsigned char *)string, &global_hooks);
if (replacement->string == NULL) {
return false;
}
replacement->type &= ~cJSON_StringIsConst; replacement->type &= ~cJSON_StringIsConst;
cJSON_ReplaceItemViaPointer( return cJSON_ReplaceItemViaPointer(
object, get_object_item(object, string, case_sensitive), replacement); object, get_object_item(object, string, case_sensitive), replacement);
return true;
} }
CJSON_PUBLIC(void) CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) 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_PUBLIC(cJSON_bool)
cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string,
cJSON *newitem) 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: */
@ -2227,11 +2343,11 @@ 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;
@ -2357,6 +2473,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]);
if (!n) { if (!n) {
@ -2372,6 +2489,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;
} }
@ -2403,6 +2524,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;
} }
@ -2434,10 +2559,15 @@ 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;
@ -2465,6 +2595,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;
} }
@ -2532,6 +2666,9 @@ 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;
@ -2543,55 +2680,93 @@ fail:
return NULL; 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) CJSON_PUBLIC(void) cJSON_Minify(char *json)
{ {
unsigned char *into = (unsigned char *)json; char *into = json;
if (json == NULL) { if (json == NULL) {
return; return;
} }
while (*json) { while (json[0] != '\0') {
if (*json == ' ') { switch (json[0]) {
case ' ':
case '\t':
case '\r':
case '\n':
json++; json++;
break;
case '/':
if (json[1] == '/') {
skip_oneline_comment(&json);
} }
else if (*json == '\t') { else if (json[1] == '*') {
/* Whitespace characters. */ skip_multiline_comment(&json);
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 { else {
/* All other characters. */ json++;
*into++ = (unsigned char)*json++; }
break;
case '\"':
minify_string(&json, (char **)&into);
break;
default:
into[0] = json[0];
json++;
into++;
} }
} }
@ -2692,8 +2867,7 @@ CJSON_PUBLIC(cJSON_bool)
cJSON_Compare(const cJSON *const a, const cJSON *const b, cJSON_Compare(const cJSON *const a, const cJSON *const b,
const cJSON_bool case_sensitive) const cJSON_bool case_sensitive)
{ {
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) {
|| cJSON_IsInvalid(a)) {
return false; return false;
} }
@ -2726,7 +2900,7 @@ cJSON_Compare(const cJSON *const a, const cJSON *const b,
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;
} }
return false; return false;

View File

@ -35,30 +35,34 @@ extern "C" {
#ifdef __WINDOWS__ #ifdef __WINDOWS__
/** /* When compiling for windows, we specify a specific calling convention to avoid
* 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
* issues where we are being called from a project with a different default convention. For windows you have 3 define options:
* calling convention. For windows you have 3 define options:
* CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever
* dllexport symbols dllexport symbols CJSON_EXPORT_SYMBOLS - Define this on library build when you
* CJSON_EXPORT_SYMBOLS - Define this on library build when you want to want to dllexport symbols (default) CJSON_IMPORT_SYMBOLS - Define this if you
* dllexport symbols (default) want to dllimport symbol
* CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
* For *nix builds that support visibility attribute, you can define similar
* For *nix builds that support visibility attribute, you can define similar behavior by
* behavior by setting default visibility to hidden by adding
* -fvisibility=hidden (for gcc) setting default visibility to hidden by adding
* or -fvisibility=hidden (for gcc)
* -xldscope=hidden (for sun cc) or
* to CFLAGS, then using the CJSON_API_VISIBILITY flag to "export" the same -xldscope=hidden (for sun cc)
* symbols the way CJSON_EXPORT_SYMBOLS does 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_CDECL __cdecl
#define CJSON_STDCALL __stdcall #define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and /* export symbols by default, this is necessary for copy pasting the C and
header file */ * header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) \ #if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) \
&& !defined(CJSON_EXPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS #define CJSON_EXPORT_SYMBOLS
@ -86,7 +90,7 @@ extern "C" {
/* 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 10 #define CJSON_VERSION_PATCH 16
#include <stddef.h> #include <stddef.h>
@ -107,11 +111,11 @@ extern "C" {
/* The cJSON structure: */ /* The cJSON structure: */
typedef struct cJSON { typedef struct cJSON {
/* next/prev allow you to walk array/object chains. Alternatively, use /* next/prev allow you to walk array/object chains. Alternatively, use
GetArraySize/GetArrayItem/GetObjectItem */ * GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next; struct cJSON *next;
struct cJSON *prev; struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of /* An array or object item will have a child pointer pointing to a chain of
the items in the array/object. */ * the items in the array/object. */
struct cJSON *child; struct cJSON *child;
/* The type of the item, as above. */ /* The type of the item, as above. */
@ -125,7 +129,7 @@ typedef struct cJSON {
double valuedouble; double valuedouble;
/* The item's name string, if this item is the child of, or is in the list /* The item's name string, if this item is the child of, or is in the list
of subitems of an object. */ * of subitems of an object. */
char *string; char *string;
} cJSON; } cJSON;
@ -140,7 +144,7 @@ typedef struct cJSON_Hooks {
typedef int cJSON_bool; typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse
them. This is to prevent stack overflows. */ * them. This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT #ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000 #define CJSON_NESTING_LIMIT 1000
#endif #endif
@ -159,6 +163,8 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks);
/* 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 /* ParseWithOpts allows you to require (and check) that the JSON is null
* terminated, and to retrieve the pointer to the final byte parsed. */ * terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then /* If you supply a ptr in return_parse_end and parsing fails, then
@ -167,6 +173,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) CJSON_PUBLIC(cJSON *)
cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_ParseWithOpts(const char *value, const char **return_parse_end,
cJSON_bool require_null_terminated); 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);
@ -185,7 +195,7 @@ CJSON_PUBLIC(cJSON_bool)
cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length,
const cJSON_bool format); 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);
@ -205,8 +215,9 @@ cJSON_HasObjectItem(const cJSON *object, const char *string);
* when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ * 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);
@ -233,18 +244,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); 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(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
@ -264,7 +278,7 @@ cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) CJSON_PUBLIC(cJSON_bool)
cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); 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_PUBLIC(cJSON *)
cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item); 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);
@ -286,32 +300,35 @@ cJSON_InsertItemInArray(
CJSON_PUBLIC(cJSON_bool) CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item,
cJSON *replacement); cJSON *replacement);
CJSON_PUBLIC(void) CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(void) CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
CJSON_PUBLIC(void) CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string,
cJSON *newitem); 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 /* 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 * 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 * children connected to the item. The item->next and ->prev pointers are always
zero on return from Duplicate. */ * zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or /* Recursively compare two cJSON items for equality. If either a or b is NULL or
* invalid, they will be considered unequal. * invalid, they will be considered unequal. case_sensitive determines if object
* case_sensitive determines if object keys are treated case sensitive (1) or * keys are treated case sensitive (1) or case insensitive (0) */
* case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) CJSON_PUBLIC(cJSON_bool)
cJSON_Compare(const cJSON *const a, const cJSON *const b, cJSON_Compare(const cJSON *const a, const cJSON *const b,
const cJSON_bool case_sensitive); 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.
They return the added item or NULL on failure. */ * They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON *) CJSON_PUBLIC(cJSON *)
cJSON_AddNullToObject(cJSON *const object, const char *const name); cJSON_AddNullToObject(cJSON *const object, const char *const name);
CJSON_PUBLIC(cJSON *) CJSON_PUBLIC(cJSON *)
@ -336,7 +353,7 @@ CJSON_PUBLIC(cJSON *)
cJSON_AddArrayToObject(cJSON *const object, const char *const name); cJSON_AddArrayToObject(cJSON *const object, const char *const name);
/* When assigning an integer value, it needs to be propagated to valuedouble /* When assigning an integer value, it needs to be propagated to valuedouble
too. */ * too. */
#define cJSON_SetIntValue(object, number) \ #define cJSON_SetIntValue(object, number) \
((object) ? (object)->valueint = (object)->valuedouble = (number) \ ((object) ? (object)->valueint = (object)->valuedouble = (number) \
: (number)) : (number))
@ -345,6 +362,18 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) \ #define cJSON_SetNumberValue(object, number) \
((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) \ ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) \
: (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 */ /* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) \ #define cJSON_ArrayForEach(element, array) \
@ -352,7 +381,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
element = element->next) element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with /* malloc/free objects using the malloc/free functions that have been set with
cJSON_InitHooks */ * cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size); CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object); CJSON_PUBLIC(void) cJSON_free(void *object);