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 |
| --- | --- | --- | --- | --- |
| 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 |
| 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/ | |

View File

@ -43,6 +43,7 @@
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <float.h>
#ifdef ENABLE_LOCALES
#include <locale.h>
@ -58,9 +59,33 @@
#include "cJSON.h"
/* define our own boolean type */
#ifdef true
#undef true
#endif
#define true ((cJSON_bool)1)
#ifdef false
#undef false
#endif
#define false ((cJSON_bool)0)
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has
* been defined in math.h */
#ifndef isinf
#define isinf(d) (isnan((d - d)) && !isnan(d))
#endif
#ifndef isnan
#define isnan(d) (d != d)
#endif
#ifndef NAN
#ifdef _WIN32
#define NAN sqrt(-1.0)
#else
#define NAN 0.0 / 0.0
#endif
#endif
typedef struct {
const unsigned char *json;
size_t position;
@ -72,7 +97,7 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
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)) {
return NULL;
@ -81,18 +106,27 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item)
return item->valuestring;
}
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item)
{
if (!cJSON_IsNumber(item)) {
return (double)NAN;
}
return item->valuedouble;
}
/* This is a safeguard to prevent copy-pasters from using incompatible C and
* header files */
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) \
|| (CJSON_VERSION_PATCH != 10)
|| (CJSON_VERSION_PATCH != 16)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif
CJSON_PUBLIC(const char *) cJSON_Version(void)
{
static char version[15];
snprintf(version, sizeof(version), "%i.%i.%i", CJSON_VERSION_MAJOR,
CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR,
CJSON_VERSION_PATCH);
return version;
}
@ -127,8 +161,8 @@ typedef struct internal_hooks {
} internal_hooks;
#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)
{
@ -150,13 +184,11 @@ internal_realloc(void *pointer, size_t size)
#define internal_realloc realloc
#endif
/* clang-format off */
static internal_hooks global_hooks = {
internal_malloc,
internal_free,
internal_realloc
};
/* clang-format on */
/* strlen of character literals resolved at compile time */
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
static internal_hooks global_hooks = { internal_malloc, internal_free,
internal_realloc };
static unsigned char *
cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks)
@ -271,8 +303,8 @@ typedef struct {
/* get a pointer to the buffer at the position */
#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
/* Parse the input text to generate a number, and populate the result
into item. */
/* Parse the input text to generate a number, and populate the result into item.
*/
static cJSON_bool
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
* point of the current locale (for strtod)
* This also takes care of '\0' not necessarily being available for marking
* the end of the input */
* point of the current locale (for strtod) This also takes care of '\0' not
* necessarily being available for marking the end of the input */
for (i = 0; (i < (sizeof(number_c_string) - 1))
&& can_access_at_index(input_buffer, i);
i++) {
@ -363,6 +394,32 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
return object->valuedouble = number;
}
CJSON_PUBLIC(char *)
cJSON_SetValuestring(cJSON *object, const char *valuestring)
{
char *copy = NULL;
/* if object's type is not cJSON_String or is cJSON_IsReference, it should
* not set valuestring */
if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) {
return NULL;
}
if (strlen(valuestring) <= strlen(object->valuestring)) {
strcpy(object->valuestring, valuestring);
return object->valuestring;
}
copy =
(char *)cJSON_strdup((const unsigned char *)valuestring, &global_hooks);
if (copy == NULL) {
return NULL;
}
if (object->valuestring != NULL) {
cJSON_free(object->valuestring);
}
object->valuestring = copy;
return copy;
}
typedef struct {
unsigned char *buffer;
size_t length;
@ -438,9 +495,8 @@ ensure(printbuffer *const p, size_t needed)
return NULL;
}
if (newbuffer) {
memcpy(newbuffer, p->buffer, p->offset + 1);
}
p->hooks.deallocate(p->buffer);
}
p->length = newsize;
@ -463,6 +519,14 @@ update_offset(printbuffer *const buffer)
buffer->offset += strlen((const char *)buffer_pointer);
}
/* securely comparison of floating-point variables */
static cJSON_bool
compare_double(double a, double b)
{
double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
return (fabs(a - b) <= maxVal * DBL_EPSILON);
}
/* Render the number nicely from the given item into a string. */
static cJSON_bool
print_number(const cJSON *const item, printbuffer *const output_buffer)
@ -471,35 +535,37 @@ print_number(const cJSON *const item, printbuffer *const output_buffer)
double d = item->valuedouble;
int length = 0;
size_t i = 0;
unsigned char
number_buffer[26]; /* temporary buffer to print the number into */
unsigned char number_buffer[26] = {
0
}; /* temporary buffer to print the number into */
unsigned char decimal_point = get_decimal_point();
double test;
double test = 0.0;
if (output_buffer == NULL) {
return false;
}
/* This checks for NaN and Infinity */
if ((d * 0) != 0) {
length = snprintf((char *)number_buffer, sizeof(number_buffer), "null");
if (isnan(d) || isinf(d)) {
length = sprintf((char *)number_buffer, "null");
}
else if (d == (double)item->valueint) {
length = sprintf((char *)number_buffer, "%d", item->valueint);
}
else {
/* Try 15 decimal places of precision to avoid nonsignificant nonzero
* digits */
length =
snprintf((char *)number_buffer, sizeof(number_buffer), "%1.15g", d);
length = sprintf((char *)number_buffer, "%1.15g", d);
/* Check whether the original double can be recovered */
if ((sscanf((char *)number_buffer, "%lg", &test) != 1)
|| ((double)test != d)) {
|| !compare_double((double)test, d)) {
/* If not, print with 17 decimal places of precision */
length = snprintf((char *)number_buffer, sizeof(number_buffer),
"%1.17g", d);
length = sprintf((char *)number_buffer, "%1.17g", d);
}
}
/* snprintf failed or buffer overrun occured */
/* sprintf failed or buffer overrun occurred */
if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) {
return false;
}
@ -709,8 +775,7 @@ parse_string(cJSON *const item, parse_buffer *const input_buffer)
if (((size_t)(input_end - input_buffer->content)
>= input_buffer->length)
|| (*input_end != '\"')) {
goto fail;
/* string ended unexpectedly */
goto fail; /* string ended unexpectedly */
}
/* 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
+ sizeof(""));
if (output == NULL) {
goto fail;
/* allocation failure */
goto fail; /* allocation failure */
}
}
@ -805,7 +869,7 @@ print_string_ptr(const unsigned char *const input,
printbuffer *const output_buffer)
{
const unsigned char *input_pointer = NULL;
unsigned char *output = NULL, *output_end;
unsigned char *output = NULL;
unsigned char *output_pointer = NULL;
size_t output_length = 0;
/* numbers of additional characters needed for escaping */
@ -853,7 +917,6 @@ print_string_ptr(const unsigned char *const input,
if (output == NULL) {
return false;
}
output_end = output + output_length + sizeof("\"\"");
/* no characters have to be escaped */
if (escape_characters == 0) {
@ -902,9 +965,7 @@ print_string_ptr(const unsigned char *const input,
break;
default:
/* escape and print as unicode codepoint */
snprintf((char *)output_pointer,
output_end - output_pointer, "u%04x",
*input_pointer);
sprintf((char *)output_pointer, "u%04x", *input_pointer);
output_pointer += 4;
break;
}
@ -945,6 +1006,10 @@ buffer_skip_whitespace(parse_buffer *const buffer)
return NULL;
}
if (cannot_access_at_index(buffer, 0)) {
return buffer;
}
while (can_access_at_index(buffer, 0)
&& (buffer_at_offset(buffer)[0] <= 32)) {
buffer->offset++;
@ -975,10 +1040,28 @@ skip_utf8_bom(parse_buffer *const buffer)
return buffer;
}
/* Parse an object - create a new root, and populate. */
CJSON_PUBLIC(cJSON *)
cJSON_ParseWithOpts(const char *value, const char **return_parse_end,
cJSON_bool require_null_terminated)
{
size_t buffer_length;
if (NULL == value) {
return NULL;
}
/* Adding null character size due to require_null_terminated. */
buffer_length = strlen(value) + sizeof("");
return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end,
require_null_terminated);
}
/* Parse an object - create a new root, and populate. */
CJSON_PUBLIC(cJSON *)
cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length,
const char **return_parse_end,
cJSON_bool require_null_terminated)
{
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
cJSON *item = NULL;
@ -987,12 +1070,12 @@ cJSON_ParseWithOpts(const char *value, const char **return_parse_end,
global_error.json = NULL;
global_error.position = 0;
if (value == NULL) {
if (value == NULL || 0 == buffer_length) {
goto fail;
}
buffer.content = (const unsigned char *)value;
buffer.length = strlen((const char *)value) + sizeof("");
buffer.length = buffer_length;
buffer.offset = 0;
buffer.hooks = global_hooks;
@ -1056,7 +1139,13 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
return cJSON_ParseWithOpts(value, 0, 0);
}
#define cjson_min(a, b) ((a < b) ? a : b)
CJSON_PUBLIC(cJSON *)
cJSON_ParseWithLength(const char *value, size_t buffer_length)
{
return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
}
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
static unsigned char *
print(const cJSON *const item, cJSON_bool format,
@ -1113,6 +1202,10 @@ fail:
hooks->deallocate(buffer->buffer);
}
if (printed != NULL) {
hooks->deallocate(printed);
}
return NULL;
}
@ -1156,20 +1249,20 @@ cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
}
CJSON_PUBLIC(cJSON_bool)
cJSON_PrintPreallocated(cJSON *item, char *buf, const int len,
const cJSON_bool fmt)
cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length,
const cJSON_bool format)
{
printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
if ((len < 0) || (buf == NULL)) {
if ((length < 0) || (buffer == NULL)) {
return false;
}
p.buffer = (unsigned char *)buf;
p.length = (size_t)len;
p.buffer = (unsigned char *)buffer;
p.length = (size_t)length;
p.offset = 0;
p.noalloc = true;
p.format = fmt;
p.format = format;
p.hooks = global_hooks;
return print_value(item, &p);
@ -1341,8 +1434,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer)
/* allocate next item */
cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
if (new_item == NULL) {
goto fail;
/* allocation failure */
goto fail; /* allocation failure */
}
/* attach next item to list */
@ -1361,8 +1453,7 @@ parse_array(cJSON *const item, parse_buffer *const input_buffer)
input_buffer->offset++;
buffer_skip_whitespace(input_buffer);
if (!parse_value(current_item, input_buffer)) {
goto fail;
/* failed to parse value */
goto fail; /* failed to parse value */
}
buffer_skip_whitespace(input_buffer);
} 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)
|| buffer_at_offset(input_buffer)[0] != ']') {
goto fail;
/* expected end of array */
goto fail; /* expected end of array */
}
success:
input_buffer->depth--;
if (head != NULL) {
head->prev = current_item;
}
item->type = cJSON_Array;
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)
|| (buffer_at_offset(input_buffer)[0] != '{')) {
goto fail;
/* not an object */
goto fail; /* not an object */
}
input_buffer->offset++;
buffer_skip_whitespace(input_buffer);
if (can_access_at_index(input_buffer, 0)
&& (buffer_at_offset(input_buffer)[0] == '}')) {
goto success;
/* empty object */
goto success; /* empty object */
}
/* 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 */
cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
if (new_item == NULL) {
goto fail;
/* allocation failure */
goto fail; /* allocation failure */
}
/* attach next item to list */
@ -1506,8 +1597,7 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer)
input_buffer->offset++;
buffer_skip_whitespace(input_buffer);
if (!parse_string(current_item, input_buffer)) {
goto fail;
/* faile to parse name */
goto fail; /* failed to parse name */
}
buffer_skip_whitespace(input_buffer);
@ -1517,16 +1607,14 @@ parse_object(cJSON *const item, parse_buffer *const input_buffer)
if (cannot_access_at_index(input_buffer, 0)
|| (buffer_at_offset(input_buffer)[0] != ':')) {
goto fail;
/* invalid object */
goto fail; /* invalid object */
}
/* parse the value */
input_buffer->offset++;
buffer_skip_whitespace(input_buffer);
if (!parse_value(current_item, input_buffer)) {
goto fail;
/* failed to parse value */
goto fail; /* failed to parse value */
}
buffer_skip_whitespace(input_buffer);
} 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)
|| (buffer_at_offset(input_buffer)[0] != '}')) {
goto fail;
/* expected end of object */
goto fail; /* expected end of object */
}
success:
input_buffer->depth--;
if (head != NULL) {
head->prev = current_item;
}
item->type = cJSON_Object;
item->child = head;
@ -1792,22 +1883,26 @@ add_item_to_array(cJSON *array, cJSON *item)
{
cJSON *child = NULL;
if ((item == NULL) || (array == NULL)) {
if ((item == NULL) || (array == NULL) || (array == item)) {
return false;
}
child = array->child;
/*
* To find the last item in array quickly, we use prev in array
*/
if (child == NULL) {
/* list is empty, start new one */
array->child = item;
item->prev = item;
item->next = NULL;
}
else {
/* append to the end */
while (child->next) {
child = child->next;
if (child->prev) {
suffix_object(child->prev, item);
array->child->prev = item;
}
suffix_object(child, item);
}
return true;
@ -1847,7 +1942,8 @@ add_item_to_object(cJSON *const object, const char *const string,
char *new_key = NULL;
int new_type = cJSON_Invalid;
if ((object == NULL) || (string == NULL) || (item == NULL)) {
if ((object == NULL) || (string == NULL) || (item == NULL)
|| (object == item)) {
return false;
}
@ -2028,7 +2124,7 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item)
return NULL;
}
if (item->prev != NULL) {
if (item != parent->child) {
/* not the first element */
item->prev->next = item->next;
}
@ -2041,6 +2137,11 @@ cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item)
/* first element */
parent->child = item->next;
}
else if (item->next == NULL) {
/* last element */
parent->child->prev = item->prev;
}
/* make sure the detached item doesn't point anywhere anymore */
item->prev = NULL;
item->next = NULL;
@ -2121,7 +2222,8 @@ CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item,
cJSON *replacement)
{
if ((parent == NULL) || (replacement == NULL) || (item == NULL)) {
if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL)
|| (item == NULL)) {
return false;
}
@ -2135,11 +2237,23 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item,
if (replacement->next != NULL) {
replacement->next->prev = replacement;
}
if (parent->child == item) {
if (parent->child->prev == parent->child) {
replacement->prev = replacement;
}
parent->child = replacement;
}
else { /*
* To find the last item in array quickly, we use prev in array.
* We can't modify the last item's next pointer where this item was
* the parent's child
*/
if (replacement->prev != NULL) {
replacement->prev->next = replacement;
}
if (parent->child == item) {
parent->child = replacement;
if (replacement->next == NULL) {
parent->child->prev = replacement;
}
}
item->next = NULL;
@ -2149,15 +2263,15 @@ cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item,
return true;
}
CJSON_PUBLIC(void)
CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
{
if (which < 0) {
return;
return false;
}
cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which),
newitem);
return cJSON_ReplaceItemViaPointer(
array, get_array_item(array, (size_t)which), newitem);
}
static cJSON_bool
@ -2175,25 +2289,27 @@ replace_item_in_object(cJSON *object, const char *string, cJSON *replacement,
}
replacement->string =
(char *)cJSON_strdup((const unsigned char *)string, &global_hooks);
if (replacement->string == NULL) {
return false;
}
replacement->type &= ~cJSON_StringIsConst;
cJSON_ReplaceItemViaPointer(
return cJSON_ReplaceItemViaPointer(
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)
{
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 *newitem)
{
replace_item_in_object(object, string, newitem, true);
return replace_item_in_object(object, string, newitem, true);
}
/* Create basic types: */
@ -2227,11 +2343,11 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
return item;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
{
cJSON *item = cJSON_New_Item(&global_hooks);
if (item) {
item->type = b ? cJSON_True : cJSON_False;
item->type = boolean ? cJSON_True : cJSON_False;
}
return item;
@ -2357,6 +2473,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
}
a = cJSON_CreateArray();
for (i = 0; a && (i < (size_t)count); i++) {
n = cJSON_CreateNumber(numbers[i]);
if (!n) {
@ -2372,6 +2489,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
@ -2403,6 +2524,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
@ -2434,10 +2559,15 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
CJSON_PUBLIC(cJSON *)
cJSON_CreateStringArray(const char *const *strings, int count)
{
size_t i = 0;
cJSON *n = NULL;
@ -2465,6 +2595,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
p = n;
}
if (a && a->child) {
a->child->prev = n;
}
return a;
}
@ -2532,6 +2666,9 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
}
child = child->next;
}
if (newitem && newitem->child) {
newitem->child->prev = newchild;
}
return newitem;
@ -2543,55 +2680,93 @@ fail:
return NULL;
}
static void
skip_oneline_comment(char **input)
{
*input += static_strlen("//");
for (; (*input)[0] != '\0'; ++(*input)) {
if ((*input)[0] == '\n') {
*input += static_strlen("\n");
return;
}
}
}
static void
skip_multiline_comment(char **input)
{
*input += static_strlen("/*");
for (; (*input)[0] != '\0'; ++(*input)) {
if (((*input)[0] == '*') && ((*input)[1] == '/')) {
*input += static_strlen("*/");
return;
}
}
}
static void
minify_string(char **input, char **output)
{
(*output)[0] = (*input)[0];
*input += static_strlen("\"");
*output += static_strlen("\"");
for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
(*output)[0] = (*input)[0];
if ((*input)[0] == '\"') {
(*output)[0] = '\"';
*input += static_strlen("\"");
*output += static_strlen("\"");
return;
}
else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
(*output)[1] = (*input)[1];
*input += static_strlen("\"");
*output += static_strlen("\"");
}
}
}
CJSON_PUBLIC(void) cJSON_Minify(char *json)
{
unsigned char *into = (unsigned char *)json;
char *into = json;
if (json == NULL) {
return;
}
while (*json) {
if (*json == ' ') {
while (json[0] != '\0') {
switch (json[0]) {
case ' ':
case '\t':
case '\r':
case '\n':
json++;
break;
case '/':
if (json[1] == '/') {
skip_oneline_comment(&json);
}
else if (*json == '\t') {
/* Whitespace characters. */
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 if (json[1] == '*') {
skip_multiline_comment(&json);
}
else {
/* All other characters. */
*into++ = (unsigned char)*json++;
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,
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;
}
@ -2726,7 +2900,7 @@ cJSON_Compare(const cJSON *const a, const cJSON *const b,
return true;
case cJSON_Number:
if (a->valuedouble == b->valuedouble) {
if (compare_double(a->valuedouble, b->valuedouble)) {
return true;
}
return false;

View File

@ -35,30 +35,34 @@ extern "C" {
#ifdef __WINDOWS__
/**
* When compiling for windows, we specify a specific calling convention to avoid
* issues where we are being called from a project with a different default
* calling convention. For windows you have 3 define options:
* CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever
* dllexport symbols
* CJSON_EXPORT_SYMBOLS - Define this on library build when you want to
* dllexport symbols (default)
* CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
*
* For *nix builds that support visibility attribute, you can define similar
* behavior by setting default visibility to hidden by adding
* -fvisibility=hidden (for gcc)
* or
* -xldscope=hidden (for sun cc)
* to CFLAGS, then using the CJSON_API_VISIBILITY flag to "export" the same
* symbols the way CJSON_EXPORT_SYMBOLS does
/* When compiling for windows, we specify a specific calling convention to avoid
issues where we are being called from a project with a different default calling
convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever
dllexport symbols CJSON_EXPORT_SYMBOLS - Define this on library build when you
want to dllexport symbols (default) CJSON_IMPORT_SYMBOLS - Define this if you
want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar
behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way
CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and
header file */
* header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) \
&& !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
@ -86,7 +90,7 @@ extern "C" {
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 10
#define CJSON_VERSION_PATCH 16
#include <stddef.h>
@ -107,11 +111,11 @@ extern "C" {
/* The cJSON structure: */
typedef struct cJSON {
/* next/prev allow you to walk array/object chains. Alternatively, use
GetArraySize/GetArrayItem/GetObjectItem */
* GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* 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;
/* The type of the item, as above. */
@ -125,7 +129,7 @@ typedef struct cJSON {
double valuedouble;
/* 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;
} cJSON;
@ -140,7 +144,7 @@ typedef struct cJSON_Hooks {
typedef int cJSON_bool;
/* 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
#define CJSON_NESTING_LIMIT 1000
#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.
*/
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *)
cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null
* terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then
@ -167,6 +173,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *)
cJSON_ParseWithOpts(const char *value, const char **return_parse_end,
cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *)
cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length,
const char **return_parse_end,
cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
@ -185,7 +195,7 @@ CJSON_PUBLIC(cJSON_bool)
cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length,
const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
@ -205,8 +215,9 @@ cJSON_HasObjectItem(const cJSON *object, const char *string);
* when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check if the item is a string and return its valuestring */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item);
@ -233,18 +244,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* 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);
/* Create an object/arrray that only references it's elements so
they will not be freed by cJSON_Delete */
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items. */
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the
* number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
CJSON_PUBLIC(cJSON *)
cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
@ -264,7 +278,7 @@ cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool)
cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *)
cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
@ -286,32 +300,35 @@ cJSON_InsertItemInArray(
CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item,
cJSON *replacement);
CJSON_PUBLIC(void)
CJSON_PUBLIC(cJSON_bool)
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_PUBLIC(void)
CJSON_PUBLIC(cJSON_bool)
cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string,
cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new
memory that will need to be released. With recurse!=0, it will duplicate any
children connected to the item. The item->next and ->prev pointers are always
zero on return from Duplicate. */
* memory that will need to be released. With recurse!=0, it will duplicate any
* children connected to the item. The item->next and ->prev pointers are always
* zero on return from Duplicate. */
/* 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) */
* invalid, they will be considered unequal. case_sensitive determines if object
* keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool)
cJSON_Compare(const cJSON *const a, const cJSON *const b,
const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from
* strings. The input pointer json cannot point to a read-only address area,
* such as a string constant, but should point to a readable and writable
* address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
They return the added item or NULL on failure. */
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON *)
cJSON_AddNullToObject(cJSON *const object, const char *const name);
CJSON_PUBLIC(cJSON *)
@ -336,7 +353,7 @@ CJSON_PUBLIC(cJSON *)
cJSON_AddArrayToObject(cJSON *const object, const char *const name);
/* When assigning an integer value, it needs to be propagated to valuedouble
too. */
* too. */
#define cJSON_SetIntValue(object, number) \
((object) ? (object)->valueint = (object)->valuedouble = (number) \
: (number))
@ -345,6 +362,18 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) \
((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) \
: (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type
* of object is cJSON_String */
CJSON_PUBLIC(char *)
cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns
* cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) \
((object != NULL && ((object)->type & (cJSON_False | cJSON_True))) \
? (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) \
| ((boolValue) ? cJSON_True : cJSON_False) \
: cJSON_Invalid)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) \
@ -352,7 +381,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
element = element->next)
/* 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_free(void *object);