Compare commits

...

41 Commits

Author SHA1 Message Date
Max Bruckner
5310da351d contributors: Add Alper Akcan 2016-12-06 09:01:12 +07:00
Max Bruckner
68196f5b14 Release version 1.1.0 2016-12-06 08:56:23 +07:00
Max Bruckner
d992cd46e6 test: Handle cJSON_PrintPreallocated return values correctly 2016-12-06 08:47:44 +07:00
Max Bruckner
84b48121bb header: explain PrintPreallocated return value 2016-12-06 08:46:48 +07:00
Max Bruckner
f10e2f884a test: exit on malloc failure 2016-12-06 08:41:51 +07:00
Max Bruckner
eeb6d237b6 Merge pull request #81 from alperakcan/master
fix memory leak in cJSON_Duplicate
2016-12-06 08:36:47 +07:00
Alper Akcan
5b4420298f fix memory leak in cJSON_Duplicate 2016-12-05 14:23:04 +03:00
Max Bruckner
e1eb06fae0 cJSON.h warn about write access to constants (#80)
Add a comment that warns about potential write access to constant memory
locations after using cJSON_AddItemToObjectCS.
2016-11-30 22:14:16 +07:00
Max Bruckner
6aefa45056 Merge pull request #79 from gatzka/fix/test
Make print_preallocated static.
2016-11-29 08:19:33 +07:00
Stephan Gatzka
345d57e9e5 Make print_preallocated static.
Otherwise compilation failes due to missing prototypes.
2016-11-28 20:21:38 +01:00
Max Bruckner
3da18a2df9 contributors: Add Kyle Chisholm 2016-11-29 00:01:21 +07:00
Max Bruckner
bf17703012 Merge branch 'print_preallocated' 2016-11-28 23:08:25 +07:00
Max Bruckner
6622c54f18 Handle out of memory when printing string 2016-11-28 23:06:38 +07:00
Kyle Chisholm
8df4cd46eb more concise return 2016-11-28 22:59:55 +07:00
Kyle Chisholm
3917fb5255 use print_preallocated function to test printout of JSON 2016-11-28 22:59:55 +07:00
Kyle Chisholm
99896d879c function to print and compare to preallocated buffer 2016-11-28 22:59:55 +07:00
Kyle Chisholm
4d1dcaa160 check print_value return 2016-11-28 22:59:54 +07:00
Kyle Chisholm
de93d76d0b changed to cJSON_PrintPreallocated, added flag in printbuffer 2016-11-28 22:59:53 +07:00
Kyle Chisholm
602c241a0b fixed "make test" on Mac (clang) 2016-11-28 22:53:36 +07:00
Kyle Chisholm
23dafa4739 added Print function call for pre-allocated buffer 2016-11-28 22:53:33 +07:00
Max Bruckner
59cf4112d2 Merge pull request #78 from gatzka/feature/gcc_check_strict_overflow_v2
gcc check strict overflow v2
2016-11-28 22:29:03 +07:00
Stephan
5cfda2292f Warn if compiler optimizes based on asumption signed overflow does not occur.
This switch is only active when making a release build.
2016-11-28 09:12:17 +01:00
Stephan
038b04d80a Take out len from condition check.
Otherwise, the check is just undefined behaviour. gcc even takes out
this check because len can never be zero if len does not wrap around.

Found with -Wstrict-overflow=2
2016-11-28 09:11:14 +01:00
Max Bruckner
624bc85143 contributors: add Stephan Gatzka 2016-11-28 01:03:04 +07:00
Max Bruckner
1f0ad823c9 Merge pull request #75 from gatzka/feature/enhance_gcc_checks_v2
Enhance gcc checks v2
2016-11-28 00:58:45 +07:00
Stephan Gatzka
29b6643bab Warn about missing prototypes.
This switch warns about missing prototypes. It does not warn if
functions are declared static. So this switch encourages the usage of
static whenever possible. This enables the compiler to perform inlining.
2016-11-27 18:22:12 +01:00
Stephan Gatzka
a8e1368697 Make function static when possible.
This is a prerequisite to later enable -Wmissing-prototypes.
2016-11-27 18:20:58 +01:00
Stephan Gatzka
bea0be48b6 Perform additional format checks. 2016-11-27 18:20:41 +01:00
Stephan Gatzka
91d11cd050 Warn if casting a pointer increases alignment of target. 2016-11-27 18:19:52 +01:00
Stephan Gatzka
9591ecddbe Warn about variables initialized by themselves. 2016-11-27 18:19:07 +01:00
Stephan Gatzka
1568015de6 Warn about shadowing variables and functions. 2016-11-27 18:18:00 +01:00
Stephan Gatzka
7ed067e680 Rename some variables to avoid shadowing. 2016-11-27 18:16:28 +01:00
Max Bruckner
4703f01cf4 Make/CMake: Fix use of compiler flags
CMake: Option was not enabled by default as intended.
Makefile: Flags were not passed when building the tests
2016-11-26 22:09:20 +07:00
Max Bruckner
d0a9f46888 Release v1.0.2 2016-11-25 08:22:41 +07:00
Max Bruckner
23b269d5f9 Rename bool -> cjbool, fix #71 2016-11-25 08:19:18 +07:00
Max Bruckner
11fd27ade7 Change version to 1.0.1 2016-11-20 01:08:54 +07:00
Max Bruckner
65ac0a1a2b cJSON_Utils tests: fix formatting 2016-11-19 17:50:01 +07:00
Max Bruckner
679004914f Define a boolean type
This is not changing the behavior of the code, but it is improving the
readability and helps to make the intention clearer.

One thing to take care: 'true' should never be compared against.
2016-11-19 17:29:22 +07:00
Max Bruckner
b88da9b0de Initialize all variables 2016-11-19 17:29:21 +07:00
Max Bruckner
a5ff796c20 Replace 0 with more expressive NULL or '\0' 2016-11-19 17:28:14 +07:00
Max Bruckner
d47339e274 cJSON_Utils: Fix comparing of cJSON_ types
When comparing the type, it has to be masked with 0xFF because of
cJSON_IsConst and cJSON_IsReference.
2016-11-18 22:52:52 +07:00
8 changed files with 552 additions and 400 deletions

View File

@@ -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()

View File

@@ -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)

View File

@@ -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
View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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
View File

@@ -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)

View File

@@ -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;
}