Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5310da351d | ||
|
|
68196f5b14 | ||
|
|
d992cd46e6 | ||
|
|
84b48121bb | ||
|
|
f10e2f884a | ||
|
|
eeb6d237b6 | ||
|
|
5b4420298f | ||
|
|
e1eb06fae0 | ||
|
|
6aefa45056 | ||
|
|
345d57e9e5 | ||
|
|
3da18a2df9 | ||
|
|
bf17703012 | ||
|
|
6622c54f18 | ||
|
|
8df4cd46eb | ||
|
|
3917fb5255 | ||
|
|
99896d879c | ||
|
|
4d1dcaa160 | ||
|
|
de93d76d0b | ||
|
|
602c241a0b | ||
|
|
23dafa4739 | ||
|
|
59cf4112d2 | ||
|
|
5cfda2292f | ||
|
|
038b04d80a | ||
|
|
624bc85143 | ||
|
|
1f0ad823c9 | ||
|
|
29b6643bab | ||
|
|
a8e1368697 | ||
|
|
bea0be48b6 | ||
|
|
91d11cd050 | ||
|
|
9591ecddbe | ||
|
|
1568015de6 | ||
|
|
7ed067e680 | ||
|
|
4703f01cf4 | ||
|
|
d0a9f46888 | ||
|
|
23b269d5f9 | ||
|
|
11fd27ade7 | ||
|
|
65ac0a1a2b | ||
|
|
679004914f | ||
|
|
b88da9b0de | ||
|
|
a5ff796c20 | ||
|
|
d47339e274 |
@@ -6,16 +6,16 @@ include(GNUInstallDirs)
|
||||
project(cJSON C)
|
||||
|
||||
set(PROJECT_VERSION_MAJOR 1)
|
||||
set(PROJECT_VERSION_MINOR 0)
|
||||
set(PROJECT_VERSION_MINOR 1)
|
||||
set(PROJECT_VERSION_PATCH 0)
|
||||
set(CJSON_VERSION_SO 1)
|
||||
set(CJSON_UTILS_VERSION_SO 1)
|
||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
|
||||
option(ENABLE_CUSTOM_COMPILER_FLAGS ON)
|
||||
option(ENABLE_CUSTOM_COMPILER_FLAGS "Enables custom compiler flags for Clang and GCC" ON)
|
||||
if (ENABLE_CUSTOM_COMPILER_FLAGS)
|
||||
if(("${CMAKE_C_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang"))
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c89 -pedantic -Wall -Wextra -Werror -Wstrict-prototypes -Wwrite-strings")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c89 -pedantic -Wall -Wextra -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ Contributors
|
||||
============
|
||||
|
||||
* [Ajay Bhargav](https://github.com/ajaybhargav)
|
||||
* [Alper Akcan](https://github.com/alperakcan)
|
||||
* [Anton Sergeev](https://github.com/anton-sergeev)
|
||||
* [Christian Schulze](https://github.com/ChristianSch)
|
||||
* [Dave Gamble](https://github.com/DaveGamble)
|
||||
@@ -15,6 +16,7 @@ Contributors
|
||||
* [IvanVoid](https://github.com/npi3pak)
|
||||
* [Jonathan Fether](https://github.com/jfether)
|
||||
* [Kevin Branigan](https://github.com/kbranigan)
|
||||
* [Kyle Chisholm](https://github.com/ChisholmKyle)
|
||||
* [Linus Wallgren](https://github.com/ecksun)
|
||||
* [Max Bruckner](https://github.com/FSMaxB)
|
||||
* Mike Pontillo
|
||||
@@ -22,6 +24,7 @@ Contributors
|
||||
* [Rafael Leal Dias](https://github.com/rafaeldias)
|
||||
* [Rod Vagg](https://github.com/rvagg)
|
||||
* [Roland Meertens](https://github.com/rmeertens)
|
||||
* [Stephan Gatzka](https://github.com/gatzka)
|
||||
* [Weston Schmidt](https://github.com/schmidtw)
|
||||
|
||||
And probably more people on [SourceForge](https://sourceforge.net/p/cjson/bugs/search/?q=status%3Aclosed-rejected+or+status%3Aclosed-out-of-date+or+status%3Awont-fix+or+status%3Aclosed-fixed+or+status%3Aclosed&page=0)
|
||||
|
||||
17
Makefile
17
Makefile
@@ -5,9 +5,12 @@ UTILS_LIBNAME = libcjson_utils
|
||||
CJSON_TEST = cJSON_test
|
||||
UTILS_TEST = cJSON_test_utils
|
||||
|
||||
CJSON_TEST_SRC = cJSON.c test.c
|
||||
UTILS_TEST_SRC = cJSON.c cJSON_Utils.c test_utils.c
|
||||
|
||||
LDLIBS = -lm
|
||||
|
||||
LIBVERSION = 1.0.0
|
||||
LIBVERSION = 1.1.0
|
||||
CJSON_SOVERSION = 1
|
||||
UTILS_SOVERSION = 1
|
||||
|
||||
@@ -20,7 +23,7 @@ INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH)
|
||||
|
||||
INSTALL ?= cp -a
|
||||
|
||||
R_CFLAGS = -fPIC -std=c89 -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings $(CFLAGS)
|
||||
R_CFLAGS = -fPIC -std=c89 -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 $(CFLAGS)
|
||||
|
||||
uname := $(shell sh -c 'uname -s 2>/dev/null || echo false')
|
||||
|
||||
@@ -62,15 +65,15 @@ test: tests
|
||||
./$(UTILS_TEST)
|
||||
|
||||
.c.o:
|
||||
$(CC) -ansi -pedantic -c $(R_CFLAGS) $<
|
||||
$(CC) -c $(R_CFLAGS) $<
|
||||
|
||||
#tests
|
||||
#cJSON
|
||||
$(CJSON_TEST): cJSON.c cJSON.h test.c
|
||||
$(CC) $^ -o $@ $(LDLIBS) -I.
|
||||
$(CJSON_TEST): $(CJSON_TEST_SRC) cJSON.h
|
||||
$(CC) $(R_CFLAGS) $(CJSON_TEST_SRC) -o $@ $(LDLIBS) -I.
|
||||
#cJSON_Utils
|
||||
$(UTILS_TEST): cJSON.c cJSON.h test.c
|
||||
$(CC) $^ -o $@ $(LDLIBS) -I.
|
||||
$(UTILS_TEST): $(UTILS_TEST_SRC) cJSON.h cJSON_Utils.h
|
||||
$(CC) $(R_CFLAGS) $(UTILS_TEST_SRC) -o $@ $(LDLIBS) -I.
|
||||
|
||||
#static libraries
|
||||
#cJSON
|
||||
|
||||
340
cJSON.c
340
cJSON.c
@@ -46,7 +46,12 @@
|
||||
#error "Failed to determine the size of an integer"
|
||||
#endif
|
||||
|
||||
static const char *global_ep;
|
||||
/* define our own boolean type */
|
||||
typedef int cjbool;
|
||||
#define true ((cjbool)1)
|
||||
#define false ((cjbool)0)
|
||||
|
||||
static const char *global_ep = NULL;
|
||||
|
||||
const char *cJSON_GetErrorPtr(void)
|
||||
{
|
||||
@@ -66,7 +71,7 @@ static int cJSON_strcasecmp(const char *s1, const char *s2)
|
||||
}
|
||||
for(; tolower(*(const unsigned char *)s1) == tolower(*(const unsigned char *)s2); ++s1, ++s2)
|
||||
{
|
||||
if (*s1 == 0)
|
||||
if (*s1 == '\0')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -80,13 +85,13 @@ static void (*cJSON_free)(void *ptr) = free;
|
||||
|
||||
static char* cJSON_strdup(const char* str)
|
||||
{
|
||||
size_t len;
|
||||
char* copy;
|
||||
size_t len = 0;
|
||||
char *copy = NULL;
|
||||
|
||||
len = strlen(str) + 1;
|
||||
if (!(copy = (char*)cJSON_malloc(len)))
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
memcpy(copy, str, len);
|
||||
|
||||
@@ -113,7 +118,7 @@ static cJSON *cJSON_New_Item(void)
|
||||
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
|
||||
if (node)
|
||||
{
|
||||
memset(node, 0, sizeof(cJSON));
|
||||
memset(node, '\0', sizeof(cJSON));
|
||||
}
|
||||
|
||||
return node;
|
||||
@@ -122,7 +127,7 @@ static cJSON *cJSON_New_Item(void)
|
||||
/* Delete a cJSON structure. */
|
||||
void cJSON_Delete(cJSON *c)
|
||||
{
|
||||
cJSON *next;
|
||||
cJSON *next = NULL;
|
||||
while (c)
|
||||
{
|
||||
next = c->next;
|
||||
@@ -239,16 +244,17 @@ typedef struct
|
||||
char *buffer;
|
||||
int length;
|
||||
int offset;
|
||||
cjbool noalloc;
|
||||
} printbuffer;
|
||||
|
||||
/* realloc printbuffer if necessary to have at least "needed" bytes more */
|
||||
static char* ensure(printbuffer *p, int needed)
|
||||
{
|
||||
char *newbuffer;
|
||||
int newsize;
|
||||
char *newbuffer = NULL;
|
||||
int newsize = 0;
|
||||
if (!p || !p->buffer)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
needed += p->offset;
|
||||
if (needed <= p->length)
|
||||
@@ -256,15 +262,19 @@ static char* ensure(printbuffer *p, int needed)
|
||||
return p->buffer + p->offset;
|
||||
}
|
||||
|
||||
if (p->noalloc) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newsize = pow2gt(needed);
|
||||
newbuffer = (char*)cJSON_malloc(newsize);
|
||||
if (!newbuffer)
|
||||
{
|
||||
cJSON_free(p->buffer);
|
||||
p->length = 0;
|
||||
p->buffer = 0;
|
||||
p->buffer = NULL;
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if (newbuffer)
|
||||
{
|
||||
@@ -280,7 +290,7 @@ static char* ensure(printbuffer *p, int needed)
|
||||
/* calculate the new length of the string in a printbuffer */
|
||||
static int update(const printbuffer *p)
|
||||
{
|
||||
char *str;
|
||||
char *str = NULL;
|
||||
if (!p || !p->buffer)
|
||||
{
|
||||
return 0;
|
||||
@@ -293,7 +303,7 @@ static int update(const printbuffer *p)
|
||||
/* Render the number nicely from the given item into a string. */
|
||||
static char *print_number(const cJSON *item, printbuffer *p)
|
||||
{
|
||||
char *str = 0;
|
||||
char *str = NULL;
|
||||
double d = item->valuedouble;
|
||||
/* special case for 0. */
|
||||
if (d == 0)
|
||||
@@ -468,17 +478,17 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
{
|
||||
const char *ptr = str + 1;
|
||||
const char *end_ptr =str + 1;
|
||||
char *ptr2;
|
||||
char *out;
|
||||
char *ptr2 = NULL;
|
||||
char *out = NULL;
|
||||
int len = 0;
|
||||
unsigned uc;
|
||||
unsigned uc2;
|
||||
unsigned uc = 0;
|
||||
unsigned uc2 = 0;
|
||||
|
||||
/* not a string! */
|
||||
if (*str != '\"')
|
||||
{
|
||||
*ep = str;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((*end_ptr != '\"') && *end_ptr && ++len)
|
||||
@@ -488,7 +498,7 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
if (*end_ptr == '\0')
|
||||
{
|
||||
/* prevent buffer overflow when last input character is a backslash */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* Skip escaped quotes. */
|
||||
end_ptr++;
|
||||
@@ -499,7 +509,7 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
out = (char*)cJSON_malloc(len + 1);
|
||||
if (!out)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
item->valuestring = out; /* assign here so out will be deleted during cJSON_Delete() later */
|
||||
item->type = cJSON_String;
|
||||
@@ -547,13 +557,13 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
{
|
||||
/* invalid */
|
||||
*ep = str;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* check for invalid. */
|
||||
if (((uc >= 0xDC00) && (uc <= 0xDFFF)) || (uc == 0))
|
||||
{
|
||||
*ep = str;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* UTF16 surrogate pairs. */
|
||||
@@ -563,13 +573,13 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
{
|
||||
/* invalid */
|
||||
*ep = str;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if ((ptr[1] != '\\') || (ptr[2] != 'u'))
|
||||
{
|
||||
/* missing second-half of surrogate. */
|
||||
*ep = str;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
uc2 = parse_hex4(ptr + 3);
|
||||
ptr += 6; /* \uXXXX */
|
||||
@@ -577,7 +587,7 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
{
|
||||
/* invalid second-half of surrogate. */
|
||||
*ep = str;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* calculate unicode codepoint from the surrogate pair */
|
||||
uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
|
||||
@@ -626,7 +636,7 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
break;
|
||||
default:
|
||||
*ep = str;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
@@ -643,12 +653,12 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
/* Render the cstring provided to an escaped version that can be printed. */
|
||||
static char *print_string_ptr(const char *str, printbuffer *p)
|
||||
{
|
||||
const char *ptr;
|
||||
char *ptr2;
|
||||
char *out;
|
||||
const char *ptr = NULL;
|
||||
char *ptr2 = NULL;
|
||||
char *out = NULL;
|
||||
int len = 0;
|
||||
int flag = 0;
|
||||
unsigned char token;
|
||||
cjbool flag = false;
|
||||
unsigned char token = '\0';
|
||||
|
||||
/* empty string */
|
||||
if (!str)
|
||||
@@ -663,7 +673,7 @@ static char *print_string_ptr(const char *str, printbuffer *p)
|
||||
}
|
||||
if (!out)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
strcpy(out, "\"\"");
|
||||
|
||||
@@ -693,7 +703,7 @@ static char *print_string_ptr(const char *str, printbuffer *p)
|
||||
}
|
||||
if (!out)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr2 = out;
|
||||
@@ -707,8 +717,9 @@ static char *print_string_ptr(const char *str, printbuffer *p)
|
||||
|
||||
ptr = str;
|
||||
/* calculate additional space that is needed for escaping */
|
||||
while ((token = *ptr) && ++len)
|
||||
while ((token = *ptr))
|
||||
{
|
||||
++len;
|
||||
if (strchr("\"\\\b\f\n\r\t", token))
|
||||
{
|
||||
len++; /* +1 for the backslash */
|
||||
@@ -730,7 +741,7 @@ static char *print_string_ptr(const char *str, printbuffer *p)
|
||||
}
|
||||
if (!out)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr2 = out;
|
||||
@@ -793,11 +804,11 @@ static char *print_string(const cJSON *item, printbuffer *p)
|
||||
|
||||
/* Predeclare these prototypes. */
|
||||
static const char *parse_value(cJSON *item, const char *value, const char **ep);
|
||||
static char *print_value(const cJSON *item, int depth, int fmt, printbuffer *p);
|
||||
static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *p);
|
||||
static const char *parse_array(cJSON *item, const char *value, const char **ep);
|
||||
static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p);
|
||||
static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *p);
|
||||
static const char *parse_object(cJSON *item, const char *value, const char **ep);
|
||||
static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p);
|
||||
static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *p);
|
||||
|
||||
/* Utility to jump whitespace and cr/lf */
|
||||
static const char *skip(const char *in)
|
||||
@@ -811,16 +822,16 @@ static const char *skip(const char *in)
|
||||
}
|
||||
|
||||
/* Parse an object - create a new root, and populate. */
|
||||
cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated)
|
||||
cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cjbool require_null_terminated)
|
||||
{
|
||||
const char *end = 0;
|
||||
const char *end = NULL;
|
||||
/* use global error pointer if no specific one was given */
|
||||
const char **ep = return_parse_end ? return_parse_end : &global_ep;
|
||||
cJSON *c = cJSON_New_Item();
|
||||
*ep = 0;
|
||||
*ep = NULL;
|
||||
if (!c) /* memory fail */
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
end = parse_value(c, skip(value), ep);
|
||||
@@ -828,7 +839,7 @@ cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int
|
||||
{
|
||||
/* parse failure. ep is set. */
|
||||
cJSON_Delete(c);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
|
||||
@@ -839,7 +850,7 @@ cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int
|
||||
{
|
||||
cJSON_Delete(c);
|
||||
*ep = end;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (return_parse_end)
|
||||
@@ -867,20 +878,30 @@ char *cJSON_PrintUnformatted(const cJSON *item)
|
||||
return print_value(item, 0, 0, 0);
|
||||
}
|
||||
|
||||
char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, int fmt)
|
||||
char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt)
|
||||
{
|
||||
printbuffer p;
|
||||
p.buffer = (char*)cJSON_malloc(prebuffer);
|
||||
if (!p.buffer)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
p.length = prebuffer;
|
||||
p.offset = 0;
|
||||
p.noalloc = false;
|
||||
|
||||
return print_value(item, 0, fmt, &p);
|
||||
}
|
||||
|
||||
int cJSON_PrintPreallocated(cJSON *item,char *buf, const int len, const cjbool fmt)
|
||||
{
|
||||
printbuffer p;
|
||||
p.buffer = buf;
|
||||
p.length = len;
|
||||
p.offset = 0;
|
||||
p.noalloc = true;
|
||||
return print_value(item,0,fmt,&p) != NULL;
|
||||
}
|
||||
|
||||
/* Parser core - when encountering text, process appropriately. */
|
||||
static const char *parse_value(cJSON *item, const char *value, const char **ep)
|
||||
@@ -888,7 +909,7 @@ static const char *parse_value(cJSON *item, const char *value, const char **ep)
|
||||
if (!value)
|
||||
{
|
||||
/* Fail on null. */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* parse the different types of values */
|
||||
@@ -927,17 +948,17 @@ static const char *parse_value(cJSON *item, const char *value, const char **ep)
|
||||
|
||||
/* failure. */
|
||||
*ep = value;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Render a value to text. */
|
||||
static char *print_value(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *p)
|
||||
{
|
||||
char *out = 0;
|
||||
char *out = NULL;
|
||||
|
||||
if (!item)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if (p)
|
||||
{
|
||||
@@ -1012,12 +1033,12 @@ static char *print_value(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
/* Build an array from input text. */
|
||||
static const char *parse_array(cJSON *item,const char *value,const char **ep)
|
||||
{
|
||||
cJSON *child;
|
||||
cJSON *child = NULL;
|
||||
if (*value != '[')
|
||||
{
|
||||
/* not an array! */
|
||||
*ep = value;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item->type = cJSON_Array;
|
||||
@@ -1032,23 +1053,23 @@ static const char *parse_array(cJSON *item,const char *value,const char **ep)
|
||||
if (!item->child)
|
||||
{
|
||||
/* memory fail */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* skip any spacing, get the value. */
|
||||
value = skip(parse_value(child, skip(value), ep));
|
||||
if (!value)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* loop through the comma separated array elements */
|
||||
while (*value == ',')
|
||||
{
|
||||
cJSON *new_item;
|
||||
cJSON *new_item = NULL;
|
||||
if (!(new_item = cJSON_New_Item()))
|
||||
{
|
||||
/* memory fail */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* add new item to end of the linked list */
|
||||
child->next = new_item;
|
||||
@@ -1060,7 +1081,7 @@ static const char *parse_array(cJSON *item,const char *value,const char **ep)
|
||||
if (!value)
|
||||
{
|
||||
/* memory fail */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1073,21 +1094,21 @@ static const char *parse_array(cJSON *item,const char *value,const char **ep)
|
||||
/* malformed. */
|
||||
*ep = value;
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Render an array to text */
|
||||
static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *p)
|
||||
{
|
||||
char **entries;
|
||||
char *out = 0;
|
||||
char *ptr;
|
||||
char *ret;
|
||||
char *out = NULL;
|
||||
char *ptr = NULL;
|
||||
char *ret = NULL;
|
||||
int len = 5;
|
||||
cJSON *child = item->child;
|
||||
int numentries = 0;
|
||||
int i = 0;
|
||||
int fail = 0;
|
||||
cjbool fail = false;
|
||||
size_t tmplen = 0;
|
||||
|
||||
/* How many entries in the array? */
|
||||
@@ -1124,7 +1145,7 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
ptr = ensure(p, 1);
|
||||
if (!ptr)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
*ptr = '[';
|
||||
p->offset++;
|
||||
@@ -1132,7 +1153,10 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
child = item->child;
|
||||
while (child && !fail)
|
||||
{
|
||||
print_value(child, depth + 1, fmt, p);
|
||||
if (!print_value(child, depth + 1, fmt, p))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
p->offset = update(p);
|
||||
if (child->next)
|
||||
{
|
||||
@@ -1140,14 +1164,14 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
ptr = ensure(p, len + 1);
|
||||
if (!ptr)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
*ptr++ = ',';
|
||||
if(fmt)
|
||||
{
|
||||
*ptr++ = ' ';
|
||||
}
|
||||
*ptr = 0;
|
||||
*ptr = '\0';
|
||||
p->offset += len;
|
||||
}
|
||||
child = child->next;
|
||||
@@ -1155,7 +1179,7 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
ptr = ensure(p, 2);
|
||||
if (!ptr)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
*ptr++ = ']';
|
||||
*ptr = '\0';
|
||||
@@ -1167,9 +1191,9 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
entries = (char**)cJSON_malloc(numentries * sizeof(char*));
|
||||
if (!entries)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
memset(entries, 0, numentries * sizeof(char*));
|
||||
memset(entries, '\0', numentries * sizeof(char*));
|
||||
|
||||
/* Retrieve all the results: */
|
||||
child = item->child;
|
||||
@@ -1183,7 +1207,7 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
}
|
||||
else
|
||||
{
|
||||
fail = 1;
|
||||
fail = true;
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
@@ -1196,7 +1220,7 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
/* If that fails, we fail. */
|
||||
if (!out)
|
||||
{
|
||||
fail = 1;
|
||||
fail = true;
|
||||
}
|
||||
|
||||
/* Handle failure. */
|
||||
@@ -1211,7 +1235,7 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
}
|
||||
}
|
||||
cJSON_free(entries);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Compose the output array. */
|
||||
@@ -1230,7 +1254,7 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
{
|
||||
*ptr++ = ' ';
|
||||
}
|
||||
*ptr = 0;
|
||||
*ptr = '\0';
|
||||
}
|
||||
cJSON_free(entries[i]);
|
||||
}
|
||||
@@ -1245,12 +1269,12 @@ static char *print_array(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
/* Build an object from the text. */
|
||||
static const char *parse_object(cJSON *item, const char *value, const char **ep)
|
||||
{
|
||||
cJSON *child;
|
||||
cJSON *child = NULL;
|
||||
if (*value != '{')
|
||||
{
|
||||
/* not an object! */
|
||||
*ep = value;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item->type = cJSON_Object;
|
||||
@@ -1265,38 +1289,38 @@ static const char *parse_object(cJSON *item, const char *value, const char **ep)
|
||||
item->child = child;
|
||||
if (!item->child)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* parse first key */
|
||||
value = skip(parse_string(child, skip(value), ep));
|
||||
if (!value)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* use string as key, not value */
|
||||
child->string = child->valuestring;
|
||||
child->valuestring = 0;
|
||||
child->valuestring = NULL;
|
||||
|
||||
if (*value != ':')
|
||||
{
|
||||
/* invalid object. */
|
||||
*ep = value;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* skip any spacing, get the value. */
|
||||
value = skip(parse_value(child, skip(value + 1), ep));
|
||||
if (!value)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*value == ',')
|
||||
{
|
||||
cJSON *new_item;
|
||||
cJSON *new_item = NULL;
|
||||
if (!(new_item = cJSON_New_Item()))
|
||||
{
|
||||
/* memory fail */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* add to linked list */
|
||||
child->next = new_item;
|
||||
@@ -1306,24 +1330,24 @@ static const char *parse_object(cJSON *item, const char *value, const char **ep)
|
||||
value = skip(parse_string(child, skip(value + 1), ep));
|
||||
if (!value)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* use string as key, not value */
|
||||
child->string = child->valuestring;
|
||||
child->valuestring = 0;
|
||||
child->valuestring = NULL;
|
||||
|
||||
if (*value != ':')
|
||||
{
|
||||
/* invalid object. */
|
||||
*ep = value;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* skip any spacing, get the value. */
|
||||
value = skip(parse_value(child, skip(value + 1), ep));
|
||||
if (!value)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* end of object */
|
||||
@@ -1334,24 +1358,24 @@ static const char *parse_object(cJSON *item, const char *value, const char **ep)
|
||||
|
||||
/* malformed */
|
||||
*ep = value;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Render an object to text. */
|
||||
static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *p)
|
||||
{
|
||||
char **entries = 0;
|
||||
char **names = 0;
|
||||
char *out = 0;
|
||||
char *ptr;
|
||||
char *ret;
|
||||
char *str;
|
||||
char **entries = NULL;
|
||||
char **names = NULL;
|
||||
char *out = NULL;
|
||||
char *ptr = NULL;
|
||||
char *ret = NULL;
|
||||
char *str = NULL;
|
||||
int len = 7;
|
||||
int i = 0;
|
||||
int j;
|
||||
int j = 0;
|
||||
cJSON *child = item->child;
|
||||
int numentries = 0;
|
||||
int fail = 0;
|
||||
cjbool fail = false;
|
||||
size_t tmplen = 0;
|
||||
|
||||
/* Count the number of entries. */
|
||||
@@ -1374,7 +1398,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
}
|
||||
if (!out)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
ptr = out;
|
||||
*ptr++ = '{';
|
||||
@@ -1399,7 +1423,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
ptr = ensure(p, len + 1);
|
||||
if (!ptr)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*ptr++ = '{';
|
||||
@@ -1419,7 +1443,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
ptr = ensure(p, depth);
|
||||
if (!ptr)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
for (j = 0; j < depth; j++)
|
||||
{
|
||||
@@ -1429,14 +1453,17 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
}
|
||||
|
||||
/* print key */
|
||||
print_string_ptr(child->string, p);
|
||||
if (!print_string_ptr(child->string, p))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
p->offset = update(p);
|
||||
|
||||
len = fmt ? 2 : 1;
|
||||
ptr = ensure(p, len);
|
||||
if (!ptr)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
*ptr++ = ':';
|
||||
if (fmt)
|
||||
@@ -1446,7 +1473,10 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
p->offset+=len;
|
||||
|
||||
/* print value */
|
||||
print_value(child, depth, fmt, p);
|
||||
if (!print_value(child, depth, fmt, p))
|
||||
{
|
||||
return NULL;
|
||||
};
|
||||
p->offset = update(p);
|
||||
|
||||
/* print comma if not last */
|
||||
@@ -1454,7 +1484,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
ptr = ensure(p, len + 1);
|
||||
if (!ptr)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if (child->next)
|
||||
{
|
||||
@@ -1474,7 +1504,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
ptr = ensure(p, fmt ? (depth + 1) : 2);
|
||||
if (!ptr)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if (fmt)
|
||||
{
|
||||
@@ -1493,16 +1523,16 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
entries = (char**)cJSON_malloc(numentries * sizeof(char*));
|
||||
if (!entries)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
names = (char**)cJSON_malloc(numentries * sizeof(char*));
|
||||
if (!names)
|
||||
{
|
||||
cJSON_free(entries);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
memset(entries,0, sizeof(char*) * numentries);
|
||||
memset(names, 0, sizeof(char*) * numentries);
|
||||
memset(entries, '\0', sizeof(char*) * numentries);
|
||||
memset(names, '\0', sizeof(char*) * numentries);
|
||||
|
||||
/* Collect all the results into our arrays: */
|
||||
child = item->child;
|
||||
@@ -1521,7 +1551,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
}
|
||||
else
|
||||
{
|
||||
fail = 1;
|
||||
fail = true;
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
@@ -1533,7 +1563,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
}
|
||||
if (!out)
|
||||
{
|
||||
fail = 1;
|
||||
fail = true;
|
||||
}
|
||||
|
||||
/* Handle failure */
|
||||
@@ -1553,7 +1583,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
}
|
||||
cJSON_free(names);
|
||||
cJSON_free(entries);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Compose the output: */
|
||||
@@ -1563,7 +1593,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
{
|
||||
*ptr++ = '\n';
|
||||
}
|
||||
*ptr = 0;
|
||||
*ptr = '\0';
|
||||
for (i = 0; i < numentries; i++)
|
||||
{
|
||||
if (fmt)
|
||||
@@ -1591,7 +1621,7 @@ static char *print_object(const cJSON *item, int depth, int fmt, printbuffer *p)
|
||||
{
|
||||
*ptr++ = '\n';
|
||||
}
|
||||
*ptr = 0;
|
||||
*ptr = '\0';
|
||||
cJSON_free(names[i]);
|
||||
cJSON_free(entries[i]);
|
||||
}
|
||||
@@ -1627,7 +1657,7 @@ int cJSON_GetArraySize(const cJSON *array)
|
||||
|
||||
cJSON *cJSON_GetArrayItem(const cJSON *array, int item)
|
||||
{
|
||||
cJSON *c = array ? array->child : 0;
|
||||
cJSON *c = array ? array->child : NULL;
|
||||
while (c && item > 0)
|
||||
{
|
||||
item--;
|
||||
@@ -1639,7 +1669,7 @@ cJSON *cJSON_GetArrayItem(const cJSON *array, int item)
|
||||
|
||||
cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string)
|
||||
{
|
||||
cJSON *c = object ? object->child : 0;
|
||||
cJSON *c = object ? object->child : NULL;
|
||||
while (c && cJSON_strcasecmp(c->string, string))
|
||||
{
|
||||
c = c->next;
|
||||
@@ -1647,7 +1677,7 @@ cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string)
|
||||
return c;
|
||||
}
|
||||
|
||||
int cJSON_HasObjectItem(const cJSON *object,const char *string)
|
||||
cjbool cJSON_HasObjectItem(const cJSON *object,const char *string)
|
||||
{
|
||||
return cJSON_GetObjectItem(object, string) ? 1 : 0;
|
||||
}
|
||||
@@ -1665,12 +1695,12 @@ static cJSON *create_reference(const cJSON *item)
|
||||
cJSON *ref = cJSON_New_Item();
|
||||
if (!ref)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
memcpy(ref, item, sizeof(cJSON));
|
||||
ref->string = 0;
|
||||
ref->string = NULL;
|
||||
ref->type |= cJSON_IsReference;
|
||||
ref->next = ref->prev = 0;
|
||||
ref->next = ref->prev = NULL;
|
||||
return ref;
|
||||
}
|
||||
|
||||
@@ -1752,7 +1782,7 @@ cJSON *cJSON_DetachItemFromArray(cJSON *array, int which)
|
||||
if (!c)
|
||||
{
|
||||
/* item doesn't exist */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if (c->prev)
|
||||
{
|
||||
@@ -1768,7 +1798,7 @@ cJSON *cJSON_DetachItemFromArray(cJSON *array, int which)
|
||||
array->child = c->next;
|
||||
}
|
||||
/* make sure the detached item doesn't point anywhere anymore */
|
||||
c->prev = c->next = 0;
|
||||
c->prev = c->next = NULL;
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -1792,7 +1822,7 @@ cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string)
|
||||
return cJSON_DetachItemFromArray(object, i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cJSON_DeleteItemFromObject(cJSON *object, const char *string)
|
||||
@@ -1853,7 +1883,7 @@ void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
|
||||
{
|
||||
newitem->prev->next = newitem;
|
||||
}
|
||||
c->next = c->prev = 0;
|
||||
c->next = c->prev = NULL;
|
||||
cJSON_Delete(c);
|
||||
}
|
||||
|
||||
@@ -1913,7 +1943,7 @@ cJSON *cJSON_CreateFalse(void)
|
||||
return item;
|
||||
}
|
||||
|
||||
cJSON *cJSON_CreateBool(int b)
|
||||
cJSON *cJSON_CreateBool(cjbool b)
|
||||
{
|
||||
cJSON *item = cJSON_New_Item();
|
||||
if(item)
|
||||
@@ -1947,7 +1977,7 @@ cJSON *cJSON_CreateString(const char *string)
|
||||
if(!item->valuestring)
|
||||
{
|
||||
cJSON_Delete(item);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1979,9 +2009,9 @@ cJSON *cJSON_CreateObject(void)
|
||||
/* Create Arrays: */
|
||||
cJSON *cJSON_CreateIntArray(const int *numbers, int count)
|
||||
{
|
||||
int i;
|
||||
cJSON *n = 0;
|
||||
cJSON *p = 0;
|
||||
int i = 0;
|
||||
cJSON *n = NULL;
|
||||
cJSON *p = NULL;
|
||||
cJSON *a = cJSON_CreateArray();
|
||||
for(i = 0; a && (i < count); i++)
|
||||
{
|
||||
@@ -1989,7 +2019,7 @@ cJSON *cJSON_CreateIntArray(const int *numbers, int count)
|
||||
if (!n)
|
||||
{
|
||||
cJSON_Delete(a);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if(!i)
|
||||
{
|
||||
@@ -2007,9 +2037,9 @@ cJSON *cJSON_CreateIntArray(const int *numbers, int count)
|
||||
|
||||
cJSON *cJSON_CreateFloatArray(const float *numbers, int count)
|
||||
{
|
||||
int i;
|
||||
cJSON *n = 0;
|
||||
cJSON *p = 0;
|
||||
int i = 0;
|
||||
cJSON *n = NULL;
|
||||
cJSON *p = NULL;
|
||||
cJSON *a = cJSON_CreateArray();
|
||||
for(i = 0; a && (i < count); i++)
|
||||
{
|
||||
@@ -2017,7 +2047,7 @@ cJSON *cJSON_CreateFloatArray(const float *numbers, int count)
|
||||
if(!n)
|
||||
{
|
||||
cJSON_Delete(a);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if(!i)
|
||||
{
|
||||
@@ -2035,9 +2065,9 @@ cJSON *cJSON_CreateFloatArray(const float *numbers, int count)
|
||||
|
||||
cJSON *cJSON_CreateDoubleArray(const double *numbers, int count)
|
||||
{
|
||||
int i;
|
||||
cJSON *n = 0;
|
||||
cJSON *p = 0;
|
||||
int i = 0;
|
||||
cJSON *n = NULL;
|
||||
cJSON *p = NULL;
|
||||
cJSON *a = cJSON_CreateArray();
|
||||
for(i = 0;a && (i < count); i++)
|
||||
{
|
||||
@@ -2045,7 +2075,7 @@ cJSON *cJSON_CreateDoubleArray(const double *numbers, int count)
|
||||
if(!n)
|
||||
{
|
||||
cJSON_Delete(a);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if(!i)
|
||||
{
|
||||
@@ -2063,9 +2093,9 @@ cJSON *cJSON_CreateDoubleArray(const double *numbers, int count)
|
||||
|
||||
cJSON *cJSON_CreateStringArray(const char **strings, int count)
|
||||
{
|
||||
int i;
|
||||
cJSON *n = 0;
|
||||
cJSON *p = 0;
|
||||
int i = 0;
|
||||
cJSON *n = NULL;
|
||||
cJSON *p = NULL;
|
||||
cJSON *a = cJSON_CreateArray();
|
||||
for (i = 0; a && (i < count); i++)
|
||||
{
|
||||
@@ -2073,7 +2103,7 @@ cJSON *cJSON_CreateStringArray(const char **strings, int count)
|
||||
if(!n)
|
||||
{
|
||||
cJSON_Delete(a);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if(!i)
|
||||
{
|
||||
@@ -2090,23 +2120,23 @@ cJSON *cJSON_CreateStringArray(const char **strings, int count)
|
||||
}
|
||||
|
||||
/* Duplication */
|
||||
cJSON *cJSON_Duplicate(const cJSON *item, int recurse)
|
||||
cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse)
|
||||
{
|
||||
cJSON *newitem;
|
||||
cJSON *cptr;
|
||||
cJSON *nptr = 0;
|
||||
cJSON *newchild;
|
||||
cJSON *newitem = NULL;
|
||||
cJSON *cptr = NULL;
|
||||
cJSON *nptr = NULL;
|
||||
cJSON *newchild = NULL;
|
||||
|
||||
/* Bail on bad ptr */
|
||||
if (!item)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* Create new item */
|
||||
newitem = cJSON_New_Item();
|
||||
if (!newitem)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
/* Copy over all vars */
|
||||
newitem->type = item->type & (~cJSON_IsReference);
|
||||
@@ -2118,16 +2148,16 @@ cJSON *cJSON_Duplicate(const cJSON *item, int recurse)
|
||||
if (!newitem->valuestring)
|
||||
{
|
||||
cJSON_Delete(newitem);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (item->string)
|
||||
{
|
||||
newitem->string = cJSON_strdup(item->string);
|
||||
newitem->string = (item->type&cJSON_StringIsConst) ? item->string : cJSON_strdup(item->string);
|
||||
if (!newitem->string)
|
||||
{
|
||||
cJSON_Delete(newitem);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* If non-recursive, then we're done! */
|
||||
@@ -2143,7 +2173,7 @@ cJSON *cJSON_Duplicate(const cJSON *item, int recurse)
|
||||
if (!newchild)
|
||||
{
|
||||
cJSON_Delete(newitem);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
if (nptr)
|
||||
{
|
||||
|
||||
7
cJSON.h
7
cJSON.h
@@ -83,6 +83,8 @@ extern char *cJSON_Print(const cJSON *item);
|
||||
extern char *cJSON_PrintUnformatted(const cJSON *item);
|
||||
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
|
||||
extern char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, int fmt);
|
||||
/* Render a cJSON entity to text using a buffer already allocated in memory with length buf_len. Returns 1 on success and 0 on failure. */
|
||||
extern int cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const int fmt);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
extern void cJSON_Delete(cJSON *c);
|
||||
|
||||
@@ -115,7 +117,10 @@ extern cJSON *cJSON_CreateStringArray(const char **strings, int count);
|
||||
/* Append item to the specified array/object. */
|
||||
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
|
||||
extern void cJSON_AddItemToObjectCS(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
|
||||
* writing to `item->string` */
|
||||
extern void 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. */
|
||||
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
static char* cJSONUtils_strdup(const char* str)
|
||||
{
|
||||
size_t len;
|
||||
char* copy;
|
||||
size_t len = 0;
|
||||
char *copy = NULL;
|
||||
|
||||
len = strlen(str) + 1;
|
||||
if (!(copy = (char*)malloc(len)))
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
memcpy(copy, str, len);
|
||||
|
||||
@@ -131,7 +131,7 @@ char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
|
||||
char *found = cJSONUtils_FindPointerFromObjectTo(obj, target);
|
||||
if (found)
|
||||
{
|
||||
if (type == cJSON_Array)
|
||||
if ((type & 0xFF) == cJSON_Array)
|
||||
{
|
||||
/* reserve enough memory for a 64 bit integer + '/' and '\0' */
|
||||
char *ret = (char*)malloc(strlen(found) + 23);
|
||||
@@ -140,7 +140,7 @@ char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
|
||||
|
||||
return ret;
|
||||
}
|
||||
else if (type == cJSON_Object)
|
||||
else if ((type & 0xFF) == cJSON_Object)
|
||||
{
|
||||
char *ret = (char*)malloc(strlen(found) + cJSONUtils_PointerEncodedstrlen(obj->string) + 2);
|
||||
*ret = '/';
|
||||
@@ -153,12 +153,12 @@ char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
|
||||
|
||||
/* reached leaf of the tree, found nothing */
|
||||
free(found);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* not found */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
|
||||
@@ -166,7 +166,7 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
|
||||
/* follow path of the pointer */
|
||||
while ((*pointer++ == '/') && object)
|
||||
{
|
||||
if (object->type == cJSON_Array)
|
||||
if ((object->type & 0xFF) == cJSON_Array)
|
||||
{
|
||||
int which = 0;
|
||||
/* parse array index */
|
||||
@@ -177,11 +177,11 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
|
||||
if (*pointer && (*pointer != '/'))
|
||||
{
|
||||
/* not end of string or new path token */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
object = cJSON_GetArrayItem(object, which);
|
||||
}
|
||||
else if (object->type == cJSON_Object)
|
||||
else if ((object->type & 0xFF) == cJSON_Object)
|
||||
{
|
||||
object = object->child;
|
||||
/* GetObjectItem. */
|
||||
@@ -197,7 +197,7 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,10 +222,10 @@ static void cJSONUtils_InplaceDecodePointerString(char *string)
|
||||
|
||||
static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path)
|
||||
{
|
||||
char *parentptr = 0;
|
||||
char *childptr = 0;
|
||||
cJSON *parent = 0;
|
||||
cJSON *ret = 0;
|
||||
char *parentptr = NULL;
|
||||
char *childptr = NULL;
|
||||
cJSON *parent = NULL;
|
||||
cJSON *ret = NULL;
|
||||
|
||||
/* copy path and split it in parent and child */
|
||||
parentptr = cJSONUtils_strdup(path);
|
||||
@@ -241,13 +241,13 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path)
|
||||
if (!parent)
|
||||
{
|
||||
/* Couldn't find object to remove child from. */
|
||||
ret = 0;
|
||||
ret = NULL;
|
||||
}
|
||||
else if (parent->type == cJSON_Array)
|
||||
else if ((parent->type & 0xFF) == cJSON_Array)
|
||||
{
|
||||
ret = cJSON_DetachItemFromArray(parent, atoi(childptr));
|
||||
}
|
||||
else if (parent->type == cJSON_Object)
|
||||
else if ((parent->type & 0xFF) == cJSON_Object)
|
||||
{
|
||||
ret = cJSON_DetachItemFromObject(parent, childptr);
|
||||
}
|
||||
@@ -259,12 +259,12 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path)
|
||||
|
||||
static int cJSONUtils_Compare(cJSON *a, cJSON *b)
|
||||
{
|
||||
if (a->type != b->type)
|
||||
if ((a->type & 0xFF) != (b->type & 0xFF))
|
||||
{
|
||||
/* mismatched type. */
|
||||
return -1;
|
||||
}
|
||||
switch (a->type)
|
||||
switch (a->type & 0xFF)
|
||||
{
|
||||
case cJSON_Number:
|
||||
/* numeric mismatch. */
|
||||
@@ -290,7 +290,7 @@ static int cJSONUtils_Compare(cJSON *a, cJSON *b)
|
||||
b = b->child;
|
||||
while (a && b)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
/* compare object keys */
|
||||
if (cJSONUtils_strcasecmp(a->string, b->string))
|
||||
{
|
||||
@@ -317,13 +317,13 @@ static int cJSONUtils_Compare(cJSON *a, cJSON *b)
|
||||
|
||||
static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
||||
{
|
||||
cJSON *op = 0;
|
||||
cJSON *path = 0;
|
||||
cJSON *value = 0;
|
||||
cJSON *parent = 0;
|
||||
cJSON *op = NULL;
|
||||
cJSON *path = NULL;
|
||||
cJSON *value = NULL;
|
||||
cJSON *parent = NULL;
|
||||
int opcode = 0;
|
||||
char *parentptr = 0;
|
||||
char *childptr = 0;
|
||||
char *parentptr = NULL;
|
||||
char *childptr = NULL;
|
||||
|
||||
op = cJSON_GetObjectItem(patch, "op");
|
||||
path = cJSON_GetObjectItem(patch, "path");
|
||||
@@ -448,7 +448,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
||||
cJSON_Delete(value);
|
||||
return 9;
|
||||
}
|
||||
else if (parent->type == cJSON_Array)
|
||||
else if ((parent->type & 0xFF) == cJSON_Array)
|
||||
{
|
||||
if (!strcmp(childptr, "-"))
|
||||
{
|
||||
@@ -459,7 +459,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
||||
cJSON_InsertItemInArray(parent, atoi(childptr), value);
|
||||
}
|
||||
}
|
||||
else if (parent->type == cJSON_Object)
|
||||
else if ((parent->type & 0xFF) == cJSON_Object)
|
||||
{
|
||||
cJSON_DeleteItemFromObject(parent, childptr);
|
||||
cJSON_AddItemToObject(parent, childptr, value);
|
||||
@@ -475,8 +475,8 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
||||
|
||||
int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches)
|
||||
{
|
||||
int err;
|
||||
if (patches->type != cJSON_Array)
|
||||
int err = 0;
|
||||
if ((patches->type & 0xFF) != cJSON_Array)
|
||||
{
|
||||
/* malformed patches. */
|
||||
return 1;
|
||||
@@ -526,13 +526,13 @@ void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path,
|
||||
|
||||
static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *from, cJSON *to)
|
||||
{
|
||||
if (from->type != to->type)
|
||||
if ((from->type & 0xFF) != (to->type & 0xFF))
|
||||
{
|
||||
cJSONUtils_GeneratePatch(patches, "replace", path, 0, to);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (from->type)
|
||||
switch ((from->type & 0xFF))
|
||||
{
|
||||
case cJSON_Number:
|
||||
if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble))
|
||||
@@ -550,7 +550,7 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f
|
||||
|
||||
case cJSON_Array:
|
||||
{
|
||||
int c;
|
||||
int c = 0;
|
||||
char *newpath = (char*)malloc(strlen(path) + 23); /* Allow space for 64bit int. */
|
||||
/* generate patches for all array elements that exist in "from" and "to" */
|
||||
for (c = 0, from = from->child, to = to->child; from && to; from = from->next, to = to->next, c++)
|
||||
@@ -575,8 +575,8 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f
|
||||
|
||||
case cJSON_Object:
|
||||
{
|
||||
cJSON *a;
|
||||
cJSON *b;
|
||||
cJSON *a = NULL;
|
||||
cJSON *b = NULL;
|
||||
cJSONUtils_SortObject(from);
|
||||
cJSONUtils_SortObject(to);
|
||||
|
||||
@@ -666,13 +666,13 @@ static cJSON *cJSONUtils_SortList(cJSON *list)
|
||||
if (second && second->prev)
|
||||
{
|
||||
/* Split the lists */
|
||||
second->prev->next = 0;
|
||||
second->prev->next = NULL;
|
||||
}
|
||||
|
||||
/* Recursively sort the sub-lists. */
|
||||
first = cJSONUtils_SortList(first);
|
||||
second = cJSONUtils_SortList(second);
|
||||
list = ptr = 0;
|
||||
list = ptr = NULL;
|
||||
|
||||
while (first && second) /* Merge the sub-lists */
|
||||
{
|
||||
@@ -740,14 +740,14 @@ void cJSONUtils_SortObject(cJSON *object)
|
||||
|
||||
cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
|
||||
{
|
||||
if (!patch || (patch->type != cJSON_Object))
|
||||
if (!patch || ((patch->type & 0xFF) != cJSON_Object))
|
||||
{
|
||||
/* scalar value, array or NULL, just duplicate */
|
||||
cJSON_Delete(target);
|
||||
return cJSON_Duplicate(patch, 1);
|
||||
}
|
||||
|
||||
if (!target || (target->type != cJSON_Object))
|
||||
if (!target || ((target->type & 0xFF) != cJSON_Object))
|
||||
{
|
||||
cJSON_Delete(target);
|
||||
target = cJSON_CreateObject();
|
||||
@@ -756,7 +756,7 @@ cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
|
||||
patch = patch->child;
|
||||
while (patch)
|
||||
{
|
||||
if (patch->type == cJSON_NULL)
|
||||
if ((patch->type & 0xFF) == cJSON_NULL)
|
||||
{
|
||||
/* NULL is the indicator to remove a value, see RFC7396 */
|
||||
cJSON_DeleteItemFromObject(target, patch->string);
|
||||
@@ -773,13 +773,13 @@ cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
|
||||
|
||||
cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to)
|
||||
{
|
||||
cJSON *patch = 0;
|
||||
cJSON *patch = NULL;
|
||||
if (!to)
|
||||
{
|
||||
/* patch to delete everything */
|
||||
return cJSON_CreateNull();
|
||||
}
|
||||
if ((to->type != cJSON_Object) || !from || (from->type != cJSON_Object))
|
||||
if (((to->type & 0xFF) != cJSON_Object) || !from || ((from->type & 0xFF) != cJSON_Object))
|
||||
{
|
||||
return cJSON_Duplicate(to, 1);
|
||||
}
|
||||
@@ -821,7 +821,7 @@ cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to)
|
||||
if (!patch->child)
|
||||
{
|
||||
cJSON_Delete(patch);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return patch;
|
||||
|
||||
152
test.c
152
test.c
@@ -22,13 +22,14 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cJSON.h"
|
||||
|
||||
/* Parse text to JSON, then render back to text, and print! */
|
||||
void doit(char *text)
|
||||
static void doit(char *text)
|
||||
{
|
||||
char *out;
|
||||
cJSON *json;
|
||||
char *out = NULL;
|
||||
cJSON *json = NULL;
|
||||
|
||||
json = cJSON_Parse(text);
|
||||
if (!json)
|
||||
@@ -44,12 +45,13 @@ void doit(char *text)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Read a file, parse, render back, etc. */
|
||||
void dofile(char *filename)
|
||||
static void dofile(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
long len;
|
||||
char *data;
|
||||
FILE *f = NULL;
|
||||
long len = 0;
|
||||
char *data = NULL;
|
||||
|
||||
/* open in read binary mode */
|
||||
f = fopen(filename,"rb");
|
||||
@@ -59,6 +61,11 @@ void dofile(char *filename)
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
data = (char*)malloc(len + 1);
|
||||
if (data == NULL)
|
||||
{
|
||||
printf("Failed to allocate memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fread(data, 1, len, f);
|
||||
data[len] = '\0';
|
||||
@@ -67,6 +74,7 @@ void dofile(char *filename)
|
||||
doit(data);
|
||||
free(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Used by some code below as an example datatype. */
|
||||
struct record
|
||||
@@ -81,17 +89,83 @@ struct record
|
||||
const char *country;
|
||||
};
|
||||
|
||||
|
||||
/* Create a bunch of objects as demonstration. */
|
||||
void create_objects(void)
|
||||
static int print_preallocated(cJSON *root)
|
||||
{
|
||||
/* declarations */
|
||||
char *out = NULL;
|
||||
char *buf = NULL;
|
||||
char *buf_fail = NULL;
|
||||
int len = 0;
|
||||
int len_fail = 0;
|
||||
|
||||
/* formatted print */
|
||||
out = cJSON_Print(root);
|
||||
|
||||
/* create buffer to succeed */
|
||||
/* the extra 64 bytes are in case a floating point value is printed */
|
||||
len = strlen(out) + 64;
|
||||
buf = malloc(len);
|
||||
if (buf == NULL)
|
||||
{
|
||||
printf("Failed to allocate memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* create buffer to fail */
|
||||
len_fail = strlen(out);
|
||||
buf_fail = malloc(len_fail);
|
||||
if (buf_fail == NULL)
|
||||
{
|
||||
printf("Failed to allocate memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Print to buffer */
|
||||
if (!cJSON_PrintPreallocated(root, buf, len, 1)) {
|
||||
printf("cJSON_PrintPreallocated failed!\n");
|
||||
if (strcmp(out, buf) != 0) {
|
||||
printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n");
|
||||
printf("cJSON_Print result:\n%s\n", out);
|
||||
printf("cJSON_PrintPreallocated result:\n%s\n", buf);
|
||||
}
|
||||
free(out);
|
||||
free(buf_fail);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* success */
|
||||
printf("%s\n", buf);
|
||||
|
||||
/* force it to fail */
|
||||
if (cJSON_PrintPreallocated(root, buf_fail, len_fail, 1)) {
|
||||
printf("cJSON_PrintPreallocated failed to show error with insufficient memory!\n");
|
||||
printf("cJSON_Print result:\n%s\n", out);
|
||||
printf("cJSON_PrintPreallocated result:\n%s\n", buf_fail);
|
||||
free(out);
|
||||
free(buf_fail);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(out);
|
||||
free(buf_fail);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a bunch of objects as demonstration. */
|
||||
static void create_objects(void)
|
||||
{
|
||||
/* declare a few. */
|
||||
cJSON *root;
|
||||
cJSON *fmt;
|
||||
cJSON *img;
|
||||
cJSON *thm;
|
||||
cJSON *fld;
|
||||
char *out;
|
||||
int i;
|
||||
cJSON *root = NULL;
|
||||
cJSON *fmt = NULL;
|
||||
cJSON *img = NULL;
|
||||
cJSON *thm = NULL;
|
||||
cJSON *fld = NULL;
|
||||
int i = 0;
|
||||
|
||||
/* Our "days of the week" array: */
|
||||
const char *strings[7] =
|
||||
@@ -152,21 +226,20 @@ void create_objects(void)
|
||||
cJSON_AddNumberToObject(fmt, "frame rate", 24);
|
||||
|
||||
/* Print to text */
|
||||
out = cJSON_Print(root);
|
||||
/* Delete the cJSON */
|
||||
if (print_preallocated(root) != 0) {
|
||||
cJSON_Delete(root);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
/* print it */
|
||||
printf("%s\n",out);
|
||||
/* release the string */
|
||||
free(out);
|
||||
|
||||
/* Our "days of the week" array: */
|
||||
root = cJSON_CreateStringArray(strings, 7);
|
||||
|
||||
out = cJSON_Print(root);
|
||||
if (print_preallocated(root) != 0) {
|
||||
cJSON_Delete(root);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
printf("%s\n", out);
|
||||
free(out);
|
||||
|
||||
/* Our matrix: */
|
||||
root = cJSON_CreateArray();
|
||||
@@ -177,11 +250,11 @@ void create_objects(void)
|
||||
|
||||
/* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */
|
||||
|
||||
out = cJSON_Print(root);
|
||||
if (print_preallocated(root) != 0) {
|
||||
cJSON_Delete(root);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
printf("%s\n", out);
|
||||
free(out);
|
||||
|
||||
|
||||
/* Our "gallery" item: */
|
||||
root = cJSON_CreateObject();
|
||||
@@ -195,13 +268,13 @@ void create_objects(void)
|
||||
cJSON_AddStringToObject(thm, "Width", "100");
|
||||
cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4));
|
||||
|
||||
out = cJSON_Print(root);
|
||||
if (print_preallocated(root) != 0) {
|
||||
cJSON_Delete(root);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
printf("%s\n", out);
|
||||
free(out);
|
||||
|
||||
/* Our array of "records": */
|
||||
|
||||
root = cJSON_CreateArray();
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
@@ -218,17 +291,20 @@ void create_objects(void)
|
||||
|
||||
/* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */
|
||||
|
||||
out = cJSON_Print(root);
|
||||
if (print_preallocated(root) != 0) {
|
||||
cJSON_Delete(root);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
printf("%s\n", out);
|
||||
free(out);
|
||||
|
||||
root = cJSON_CreateObject();
|
||||
cJSON_AddNumberToObject(root, "number", 1.0 / zero);
|
||||
out = cJSON_Print(root);
|
||||
|
||||
if (print_preallocated(root) != 0) {
|
||||
cJSON_Delete(root);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
printf("%s\n", out);
|
||||
free(out);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
||||
339
test_utils.c
339
test_utils.c
@@ -5,167 +5,202 @@
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* Some variables */
|
||||
char *temp = NULL;
|
||||
char *patchtext = NULL;
|
||||
char *patchedtext = NULL;
|
||||
/* Some variables */
|
||||
char *temp = NULL;
|
||||
char *patchtext = NULL;
|
||||
char *patchedtext = NULL;
|
||||
|
||||
int i;
|
||||
/* JSON Pointer tests: */
|
||||
cJSON *root;
|
||||
const char *json="{"
|
||||
"\"foo\": [\"bar\", \"baz\"],"
|
||||
"\"\": 0,"
|
||||
"\"a/b\": 1,"
|
||||
"\"c%d\": 2,"
|
||||
"\"e^f\": 3,"
|
||||
"\"g|h\": 4,"
|
||||
"\"i\\\\j\": 5,"
|
||||
"\"k\\\"l\": 6,"
|
||||
"\" \": 7,"
|
||||
"\"m~n\": 8"
|
||||
"}";
|
||||
|
||||
const char *tests[12]={"","/foo","/foo/0","/","/a~1b","/c%d","/e^f","/g|h","/i\\j","/k\"l","/ ","/m~0n"};
|
||||
|
||||
/* JSON Apply Patch tests: */
|
||||
const char *patches[15][3]={
|
||||
{"{ \"foo\": \"bar\"}", "[{ \"op\": \"add\", \"path\": \"/baz\", \"value\": \"qux\" }]","{\"baz\": \"qux\",\"foo\": \"bar\"}"},
|
||||
{"{ \"foo\": [ \"bar\", \"baz\" ] }", "[{ \"op\": \"add\", \"path\": \"/foo/1\", \"value\": \"qux\" }]","{\"foo\": [ \"bar\", \"qux\", \"baz\" ] }"},
|
||||
{"{\"baz\": \"qux\",\"foo\": \"bar\"}"," [{ \"op\": \"remove\", \"path\": \"/baz\" }]","{\"foo\": \"bar\" }"},
|
||||
{"{ \"foo\": [ \"bar\", \"qux\", \"baz\" ] }","[{ \"op\": \"remove\", \"path\": \"/foo/1\" }]","{\"foo\": [ \"bar\", \"baz\" ] }"},
|
||||
{"{ \"baz\": \"qux\",\"foo\": \"bar\"}","[{ \"op\": \"replace\", \"path\": \"/baz\", \"value\": \"boo\" }]","{\"baz\": \"boo\",\"foo\": \"bar\"}"},
|
||||
{"{\"foo\": {\"bar\": \"baz\",\"waldo\": \"fred\"},\"qux\": {\"corge\": \"grault\"}}","[{ \"op\": \"move\", \"from\": \"/foo/waldo\", \"path\": \"/qux/thud\" }]","{\"foo\": {\"bar\": \"baz\"},\"qux\": {\"corge\": \"grault\",\"thud\": \"fred\"}}"},
|
||||
{"{ \"foo\": [ \"all\", \"grass\", \"cows\", \"eat\" ] }","[ { \"op\": \"move\", \"from\": \"/foo/1\", \"path\": \"/foo/3\" }]","{ \"foo\": [ \"all\", \"cows\", \"eat\", \"grass\" ] }"},
|
||||
{"{\"baz\": \"qux\",\"foo\": [ \"a\", 2, \"c\" ]}","[{ \"op\": \"test\", \"path\": \"/baz\", \"value\": \"qux\" },{ \"op\": \"test\", \"path\": \"/foo/1\", \"value\": 2 }]",""},
|
||||
{"{ \"baz\": \"qux\" }","[ { \"op\": \"test\", \"path\": \"/baz\", \"value\": \"bar\" }]",""},
|
||||
{"{ \"foo\": \"bar\" }","[{ \"op\": \"add\", \"path\": \"/child\", \"value\": { \"grandchild\": { } } }]","{\"foo\": \"bar\",\"child\": {\"grandchild\": {}}}"},
|
||||
{"{ \"foo\": \"bar\" }","[{ \"op\": \"add\", \"path\": \"/baz\", \"value\": \"qux\", \"xyz\": 123 }]","{\"foo\": \"bar\",\"baz\": \"qux\"}"},
|
||||
{"{ \"foo\": \"bar\" }","[{ \"op\": \"add\", \"path\": \"/baz/bat\", \"value\": \"qux\" }]",""},
|
||||
{"{\"/\": 9,\"~1\": 10}","[{\"op\": \"test\", \"path\": \"/~01\", \"value\": 10}]",""},
|
||||
{"{\"/\": 9,\"~1\": 10}","[{\"op\": \"test\", \"path\": \"/~01\", \"value\": \"10\"}]",""},
|
||||
{"{ \"foo\": [\"bar\"] }","[ { \"op\": \"add\", \"path\": \"/foo/-\", \"value\": [\"abc\", \"def\"] }]","{\"foo\": [\"bar\", [\"abc\", \"def\"]] }"}};
|
||||
|
||||
/* JSON Apply Merge tests: */
|
||||
const char *merges[15][3]={
|
||||
{"{\"a\":\"b\"}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"},
|
||||
{"{\"a\":\"b\"}", "{\"b\":\"c\"}", "{\"a\":\"b\",\"b\":\"c\"}"},
|
||||
{"{\"a\":\"b\"}", "{\"a\":null}", "{}"},
|
||||
{"{\"a\":\"b\",\"b\":\"c\"}", "{\"a\":null}", "{\"b\":\"c\"}"},
|
||||
{"{\"a\":[\"b\"]}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"},
|
||||
{"{\"a\":\"c\"}", "{\"a\":[\"b\"]}", "{\"a\":[\"b\"]}"},
|
||||
{"{\"a\":{\"b\":\"c\"}}", "{\"a\":{\"b\":\"d\",\"c\":null}}", "{\"a\":{\"b\":\"d\"}}"},
|
||||
{"{\"a\":[{\"b\":\"c\"}]}", "{\"a\":[1]}", "{\"a\":[1]}"},
|
||||
{"[\"a\",\"b\"]", "[\"c\",\"d\"]", "[\"c\",\"d\"]"},
|
||||
{"{\"a\":\"b\"}", "[\"c\"]", "[\"c\"]"},
|
||||
{"{\"a\":\"foo\"}", "null", "null"},
|
||||
{"{\"a\":\"foo\"}", "\"bar\"", "\"bar\""},
|
||||
{"{\"e\":null}", "{\"a\":1}", "{\"e\":null,\"a\":1}"},
|
||||
{"[1,2]", "{\"a\":\"b\",\"c\":null}", "{\"a\":\"b\"}"},
|
||||
{"{}","{\"a\":{\"bb\":{\"ccc\":null}}}", "{\"a\":{\"bb\":{}}}"}};
|
||||
|
||||
int i = 0;
|
||||
/* JSON Pointer tests: */
|
||||
cJSON *root = NULL;
|
||||
const char *json=
|
||||
"{"
|
||||
"\"foo\": [\"bar\", \"baz\"],"
|
||||
"\"\": 0,"
|
||||
"\"a/b\": 1,"
|
||||
"\"c%d\": 2,"
|
||||
"\"e^f\": 3,"
|
||||
"\"g|h\": 4,"
|
||||
"\"i\\\\j\": 5,"
|
||||
"\"k\\\"l\": 6,"
|
||||
"\" \": 7,"
|
||||
"\"m~n\": 8"
|
||||
"}";
|
||||
|
||||
/* Misc tests */
|
||||
int numbers[10]={0,1,2,3,4,5,6,7,8,9};
|
||||
const char *random="QWERTYUIOPASDFGHJKLZXCVBNM";
|
||||
char buf[2]={0,0},*before,*after;
|
||||
cJSON *object,*nums,*num6,*sortme;
|
||||
const char *tests[12] = {"","/foo","/foo/0","/","/a~1b","/c%d","/e^f","/g|h","/i\\j","/k\"l","/ ","/m~0n"};
|
||||
|
||||
/* JSON Apply Patch tests: */
|
||||
const char *patches[15][3] =
|
||||
{
|
||||
{"{ \"foo\": \"bar\"}", "[{ \"op\": \"add\", \"path\": \"/baz\", \"value\": \"qux\" }]","{\"baz\": \"qux\",\"foo\": \"bar\"}"},
|
||||
{"{ \"foo\": [ \"bar\", \"baz\" ] }", "[{ \"op\": \"add\", \"path\": \"/foo/1\", \"value\": \"qux\" }]","{\"foo\": [ \"bar\", \"qux\", \"baz\" ] }"},
|
||||
{"{\"baz\": \"qux\",\"foo\": \"bar\"}"," [{ \"op\": \"remove\", \"path\": \"/baz\" }]","{\"foo\": \"bar\" }"},
|
||||
{"{ \"foo\": [ \"bar\", \"qux\", \"baz\" ] }","[{ \"op\": \"remove\", \"path\": \"/foo/1\" }]","{\"foo\": [ \"bar\", \"baz\" ] }"},
|
||||
{"{ \"baz\": \"qux\",\"foo\": \"bar\"}","[{ \"op\": \"replace\", \"path\": \"/baz\", \"value\": \"boo\" }]","{\"baz\": \"boo\",\"foo\": \"bar\"}"},
|
||||
{"{\"foo\": {\"bar\": \"baz\",\"waldo\": \"fred\"},\"qux\": {\"corge\": \"grault\"}}","[{ \"op\": \"move\", \"from\": \"/foo/waldo\", \"path\": \"/qux/thud\" }]","{\"foo\": {\"bar\": \"baz\"},\"qux\": {\"corge\": \"grault\",\"thud\": \"fred\"}}"},
|
||||
{"{ \"foo\": [ \"all\", \"grass\", \"cows\", \"eat\" ] }","[ { \"op\": \"move\", \"from\": \"/foo/1\", \"path\": \"/foo/3\" }]","{ \"foo\": [ \"all\", \"cows\", \"eat\", \"grass\" ] }"},
|
||||
{"{\"baz\": \"qux\",\"foo\": [ \"a\", 2, \"c\" ]}","[{ \"op\": \"test\", \"path\": \"/baz\", \"value\": \"qux\" },{ \"op\": \"test\", \"path\": \"/foo/1\", \"value\": 2 }]",""},
|
||||
{"{ \"baz\": \"qux\" }","[ { \"op\": \"test\", \"path\": \"/baz\", \"value\": \"bar\" }]",""},
|
||||
{"{ \"foo\": \"bar\" }","[{ \"op\": \"add\", \"path\": \"/child\", \"value\": { \"grandchild\": { } } }]","{\"foo\": \"bar\",\"child\": {\"grandchild\": {}}}"},
|
||||
{"{ \"foo\": \"bar\" }","[{ \"op\": \"add\", \"path\": \"/baz\", \"value\": \"qux\", \"xyz\": 123 }]","{\"foo\": \"bar\",\"baz\": \"qux\"}"},
|
||||
{"{ \"foo\": \"bar\" }","[{ \"op\": \"add\", \"path\": \"/baz/bat\", \"value\": \"qux\" }]",""},
|
||||
{"{\"/\": 9,\"~1\": 10}","[{\"op\": \"test\", \"path\": \"/~01\", \"value\": 10}]",""},
|
||||
{"{\"/\": 9,\"~1\": 10}","[{\"op\": \"test\", \"path\": \"/~01\", \"value\": \"10\"}]",""},
|
||||
{"{ \"foo\": [\"bar\"] }","[ { \"op\": \"add\", \"path\": \"/foo/-\", \"value\": [\"abc\", \"def\"] }]","{\"foo\": [\"bar\", [\"abc\", \"def\"]] }"}
|
||||
};
|
||||
|
||||
/* JSON Apply Merge tests: */
|
||||
const char *merges[15][3] =
|
||||
{
|
||||
{"{\"a\":\"b\"}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"},
|
||||
{"{\"a\":\"b\"}", "{\"b\":\"c\"}", "{\"a\":\"b\",\"b\":\"c\"}"},
|
||||
{"{\"a\":\"b\"}", "{\"a\":null}", "{}"},
|
||||
{"{\"a\":\"b\",\"b\":\"c\"}", "{\"a\":null}", "{\"b\":\"c\"}"},
|
||||
{"{\"a\":[\"b\"]}", "{\"a\":\"c\"}", "{\"a\":\"c\"}"},
|
||||
{"{\"a\":\"c\"}", "{\"a\":[\"b\"]}", "{\"a\":[\"b\"]}"},
|
||||
{"{\"a\":{\"b\":\"c\"}}", "{\"a\":{\"b\":\"d\",\"c\":null}}", "{\"a\":{\"b\":\"d\"}}"},
|
||||
{"{\"a\":[{\"b\":\"c\"}]}", "{\"a\":[1]}", "{\"a\":[1]}"},
|
||||
{"[\"a\",\"b\"]", "[\"c\",\"d\"]", "[\"c\",\"d\"]"},
|
||||
{"{\"a\":\"b\"}", "[\"c\"]", "[\"c\"]"},
|
||||
{"{\"a\":\"foo\"}", "null", "null"},
|
||||
{"{\"a\":\"foo\"}", "\"bar\"", "\"bar\""},
|
||||
{"{\"e\":null}", "{\"a\":1}", "{\"e\":null,\"a\":1}"},
|
||||
{"[1,2]", "{\"a\":\"b\",\"c\":null}", "{\"a\":\"b\"}"},
|
||||
{"{}","{\"a\":{\"bb\":{\"ccc\":null}}}", "{\"a\":{\"bb\":{}}}"}
|
||||
};
|
||||
|
||||
|
||||
|
||||
printf("JSON Pointer Tests\n");
|
||||
root=cJSON_Parse(json);
|
||||
for (i=0;i<12;i++)
|
||||
{
|
||||
char *output=cJSON_Print(cJSONUtils_GetPointer(root,tests[i]));
|
||||
printf("Test %d:\n%s\n\n",i+1,output);
|
||||
free(output);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
/* Misc tests */
|
||||
int numbers[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
const char *random = "QWERTYUIOPASDFGHJKLZXCVBNM";
|
||||
char buf[2] = {0,0};
|
||||
char *before = NULL;
|
||||
char *after = NULL;
|
||||
cJSON *object = NULL;
|
||||
cJSON *nums = NULL;
|
||||
cJSON *num6 = NULL;
|
||||
cJSON *sortme = NULL;
|
||||
|
||||
|
||||
printf("JSON Apply Patch Tests\n");
|
||||
for (i=0;i<15;i++)
|
||||
{
|
||||
cJSON *object=cJSON_Parse(patches[i][0]);
|
||||
cJSON *patch=cJSON_Parse(patches[i][1]);
|
||||
int err=cJSONUtils_ApplyPatches(object,patch);
|
||||
char *output=cJSON_Print(object);
|
||||
printf("Test %d (err %d):\n%s\n\n",i+1,err,output);
|
||||
free(output);cJSON_Delete(object);cJSON_Delete(patch);
|
||||
}
|
||||
printf("JSON Pointer Tests\n");
|
||||
root = cJSON_Parse(json);
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
char *output = cJSON_Print(cJSONUtils_GetPointer(root, tests[i]));
|
||||
printf("Test %d:\n%s\n\n", i + 1, output);
|
||||
free(output);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
|
||||
/* JSON Generate Patch tests: */
|
||||
printf("JSON Generate Patch Tests\n");
|
||||
for (i=0;i<15;i++)
|
||||
{
|
||||
cJSON *from,*to,*patch;char *out;
|
||||
if (!strlen(patches[i][2])) continue;
|
||||
from=cJSON_Parse(patches[i][0]);
|
||||
to=cJSON_Parse(patches[i][2]);
|
||||
patch=cJSONUtils_GeneratePatches(from,to);
|
||||
out=cJSON_Print(patch);
|
||||
printf("Test %d: (patch: %s):\n%s\n\n",i+1,patches[i][1],out);
|
||||
free(out);cJSON_Delete(from);cJSON_Delete(to);cJSON_Delete(patch);
|
||||
}
|
||||
|
||||
/* Misc tests: */
|
||||
printf("JSON Pointer construct\n");
|
||||
object=cJSON_CreateObject();
|
||||
nums=cJSON_CreateIntArray(numbers,10);
|
||||
num6=cJSON_GetArrayItem(nums,6);
|
||||
cJSON_AddItemToObject(object,"numbers",nums);
|
||||
temp=cJSONUtils_FindPointerFromObjectTo(object,num6);
|
||||
printf("Pointer: [%s]\n",temp);
|
||||
free(temp);
|
||||
temp=cJSONUtils_FindPointerFromObjectTo(object,nums);
|
||||
printf("Pointer: [%s]\n",temp);
|
||||
free(temp);
|
||||
temp=cJSONUtils_FindPointerFromObjectTo(object,object);
|
||||
printf("Pointer: [%s]\n",temp);
|
||||
free(temp);
|
||||
cJSON_Delete(object);
|
||||
printf("JSON Apply Patch Tests\n");
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
cJSON *object_to_be_patched = cJSON_Parse(patches[i][0]);
|
||||
cJSON *patch = cJSON_Parse(patches[i][1]);
|
||||
int err = cJSONUtils_ApplyPatches(object_to_be_patched, patch);
|
||||
char *output = cJSON_Print(object_to_be_patched);
|
||||
printf("Test %d (err %d):\n%s\n\n", i + 1, err, output);
|
||||
|
||||
/* JSON Sort test: */
|
||||
sortme=cJSON_CreateObject();
|
||||
for (i=0;i<26;i++)
|
||||
{
|
||||
buf[0]=random[i];cJSON_AddItemToObject(sortme,buf,cJSON_CreateNumber(1));
|
||||
}
|
||||
before=cJSON_PrintUnformatted(sortme);
|
||||
cJSONUtils_SortObject(sortme);
|
||||
after=cJSON_PrintUnformatted(sortme);
|
||||
printf("Before: [%s]\nAfter: [%s]\n\n",before,after);
|
||||
free(before);free(after);cJSON_Delete(sortme);
|
||||
|
||||
/* Merge tests: */
|
||||
printf("JSON Merge Patch tests\n");
|
||||
for (i=0;i<15;i++)
|
||||
{
|
||||
cJSON *object=cJSON_Parse(merges[i][0]);
|
||||
cJSON *patch=cJSON_Parse(merges[i][1]);
|
||||
char *before=cJSON_PrintUnformatted(object);
|
||||
patchtext=cJSON_PrintUnformatted(patch);
|
||||
printf("Before: [%s] -> [%s] = ",before,patchtext);
|
||||
object=cJSONUtils_MergePatch(object,patch);
|
||||
after=cJSON_PrintUnformatted(object);
|
||||
printf("[%s] vs [%s] (%s)\n",after,merges[i][2],strcmp(after,merges[i][2])?"FAIL":"OK");
|
||||
free(output);
|
||||
cJSON_Delete(object_to_be_patched);
|
||||
cJSON_Delete(patch);
|
||||
}
|
||||
|
||||
free(before);free(patchtext);free(after);cJSON_Delete(object);cJSON_Delete(patch);
|
||||
}
|
||||
|
||||
/* Generate Merge tests: */
|
||||
for (i=0;i<15;i++)
|
||||
{
|
||||
cJSON *from=cJSON_Parse(merges[i][0]);
|
||||
cJSON *to=cJSON_Parse(merges[i][2]);
|
||||
cJSON *patch=cJSONUtils_GenerateMergePatch(from,to);
|
||||
from=cJSONUtils_MergePatch(from,patch);
|
||||
patchtext=cJSON_PrintUnformatted(patch);
|
||||
patchedtext=cJSON_PrintUnformatted(from);
|
||||
printf("Patch [%s] vs [%s] = [%s] vs [%s] (%s)\n",patchtext,merges[i][1],patchedtext,merges[i][2],strcmp(patchedtext,merges[i][2])?"FAIL":"OK");
|
||||
cJSON_Delete(from);cJSON_Delete(to);cJSON_Delete(patch);free(patchtext);free(patchedtext);
|
||||
}
|
||||
/* JSON Generate Patch tests: */
|
||||
printf("JSON Generate Patch Tests\n");
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
cJSON *from;
|
||||
cJSON *to;
|
||||
cJSON *patch;
|
||||
char *out;
|
||||
if (!strlen(patches[i][2]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
from = cJSON_Parse(patches[i][0]);
|
||||
to = cJSON_Parse(patches[i][2]);
|
||||
patch = cJSONUtils_GeneratePatches(from, to);
|
||||
out = cJSON_Print(patch);
|
||||
printf("Test %d: (patch: %s):\n%s\n\n", i + 1, patches[i][1], out);
|
||||
|
||||
return 0;
|
||||
free(out);
|
||||
cJSON_Delete(from);
|
||||
cJSON_Delete(to);
|
||||
cJSON_Delete(patch);
|
||||
}
|
||||
|
||||
/* Misc tests: */
|
||||
printf("JSON Pointer construct\n");
|
||||
object = cJSON_CreateObject();
|
||||
nums = cJSON_CreateIntArray(numbers, 10);
|
||||
num6 = cJSON_GetArrayItem(nums, 6);
|
||||
cJSON_AddItemToObject(object, "numbers", nums);
|
||||
temp = cJSONUtils_FindPointerFromObjectTo(object, num6);
|
||||
printf("Pointer: [%s]\n", temp);
|
||||
free(temp);
|
||||
temp = cJSONUtils_FindPointerFromObjectTo(object, nums);
|
||||
printf("Pointer: [%s]\n", temp);
|
||||
free(temp);
|
||||
temp = cJSONUtils_FindPointerFromObjectTo(object, object);
|
||||
printf("Pointer: [%s]\n", temp);
|
||||
free(temp);
|
||||
cJSON_Delete(object);
|
||||
|
||||
/* JSON Sort test: */
|
||||
sortme = cJSON_CreateObject();
|
||||
for (i = 0; i < 26; i++)
|
||||
{
|
||||
buf[0] = random[i];
|
||||
cJSON_AddItemToObject(sortme, buf, cJSON_CreateNumber(1));
|
||||
}
|
||||
before = cJSON_PrintUnformatted(sortme);
|
||||
cJSONUtils_SortObject(sortme);
|
||||
after = cJSON_PrintUnformatted(sortme);
|
||||
printf("Before: [%s]\nAfter: [%s]\n\n", before, after);
|
||||
|
||||
free(before);
|
||||
free(after);
|
||||
cJSON_Delete(sortme);
|
||||
|
||||
/* Merge tests: */
|
||||
printf("JSON Merge Patch tests\n");
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
cJSON *object_to_be_merged = cJSON_Parse(merges[i][0]);
|
||||
cJSON *patch = cJSON_Parse(merges[i][1]);
|
||||
char *before_merge = cJSON_PrintUnformatted(object_to_be_merged);
|
||||
patchtext = cJSON_PrintUnformatted(patch);
|
||||
printf("Before: [%s] -> [%s] = ", before_merge, patchtext);
|
||||
object_to_be_merged = cJSONUtils_MergePatch(object_to_be_merged, patch);
|
||||
after = cJSON_PrintUnformatted(object_to_be_merged);
|
||||
printf("[%s] vs [%s] (%s)\n", after, merges[i][2], strcmp(after, merges[i][2]) ? "FAIL" : "OK");
|
||||
|
||||
free(before_merge);
|
||||
free(patchtext);
|
||||
free(after);
|
||||
cJSON_Delete(object_to_be_merged);
|
||||
cJSON_Delete(patch);
|
||||
}
|
||||
|
||||
/* Generate Merge tests: */
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
cJSON *from = cJSON_Parse(merges[i][0]);
|
||||
cJSON *to = cJSON_Parse(merges[i][2]);
|
||||
cJSON *patch = cJSONUtils_GenerateMergePatch(from,to);
|
||||
from = cJSONUtils_MergePatch(from,patch);
|
||||
patchtext = cJSON_PrintUnformatted(patch);
|
||||
patchedtext = cJSON_PrintUnformatted(from);
|
||||
printf("Patch [%s] vs [%s] = [%s] vs [%s] (%s)\n", patchtext, merges[i][1], patchedtext, merges[i][2], strcmp(patchedtext, merges[i][2]) ? "FAIL" : "OK");
|
||||
|
||||
cJSON_Delete(from);
|
||||
cJSON_Delete(to);
|
||||
cJSON_Delete(patch);
|
||||
free(patchtext);
|
||||
free(patchedtext);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user