Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de8eaaba89 | ||
|
|
b2da44d6cb | ||
|
|
f6998a6a34 | ||
|
|
e3e0b5150b | ||
|
|
1df987a170 | ||
|
|
ddadb44a67 | ||
|
|
9ef44fc0b6 | ||
|
|
8c58e62597 | ||
|
|
8893e39712 | ||
|
|
3d6ae11340 | ||
|
|
a1f2600883 | ||
|
|
fcc85bdfbc | ||
|
|
7d08a3518a | ||
|
|
cc486a0354 | ||
|
|
fcc89c4bb2 | ||
|
|
a0431e226f | ||
|
|
89edfb6741 | ||
|
|
e69db83de5 | ||
|
|
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 | ||
|
|
06008b0444 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -8,3 +8,8 @@ test
|
||||
tags
|
||||
*.dylib
|
||||
build/
|
||||
cJSON_test
|
||||
cJSON_test_utils
|
||||
libcjson.so.*
|
||||
libcjson_utils.so.*
|
||||
*.orig
|
||||
|
||||
@@ -6,16 +6,16 @@ include(GNUInstallDirs)
|
||||
project(cJSON C)
|
||||
|
||||
set(PROJECT_VERSION_MAJOR 1)
|
||||
set(PROJECT_VERSION_MINOR 0)
|
||||
set(PROJECT_VERSION_PATCH 1)
|
||||
set(PROJECT_VERSION_MINOR 2)
|
||||
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 -Wcast-qual -Wc++-compat")
|
||||
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)
|
||||
@@ -13,8 +14,10 @@ Contributors
|
||||
* Ian Mobley
|
||||
* Irwan Djadjadi
|
||||
* [IvanVoid](https://github.com/npi3pak)
|
||||
* [Jiri Zouhar](https://github.com/loigu)
|
||||
* [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 +25,8 @@ Contributors
|
||||
* [Rafael Leal Dias](https://github.com/rafaeldias)
|
||||
* [Rod Vagg](https://github.com/rvagg)
|
||||
* [Roland Meertens](https://github.com/rmeertens)
|
||||
* [Romain Porte](https://github.com/MicroJoe)
|
||||
* [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.1
|
||||
LIBVERSION = 1.2.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 -Wcast-qual -Wc++-compat $(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
|
||||
|
||||
@@ -79,7 +79,7 @@ make
|
||||
And install it with `make install` if you want. By default it installs the headers `/usr/local/include/cjson` and the libraries to `/usr/local/lib`. It also installs files for pkg-config to make it easier to detect and use an existing installation of CMake. And it installs CMake config files, that can be used by other CMake based projects to discover the library.
|
||||
|
||||
You can change the build process with a list of different options that you can pass to CMake. Turn them on with `On` and off with `Off`:
|
||||
* `-DENABLE_CJSON_TESTS=On`: Enable building the tests. (on by default)
|
||||
* `-DENABLE_CJSON_TEST=On`: Enable building the tests. (on by default)
|
||||
* `-DENABLE_CJSON_UTILS=On`: Enable building cJSON_Utils. (off by default)
|
||||
* `-DENABLE_TARGET_EXPORT=On`: Enable the export of CMake targets. Turn off if it makes problems. (on by default)
|
||||
* `-DENABLE_CUSTOM_COMPILER_FLAGS=On`: Enable custom compiler flags (currently for Clang and GCC). Turn off if it makes problems. (on by default)
|
||||
@@ -90,7 +90,7 @@ If you are packaging cJSON for a distribution of Linux, you would probably take
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TESTS=Off -DCMAKE_INSTALL_PREFIX=/usr
|
||||
cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr
|
||||
make
|
||||
make DESTDIR=$pkgdir install
|
||||
```
|
||||
|
||||
121
cJSON.c
121
cJSON.c
@@ -47,9 +47,9 @@
|
||||
#endif
|
||||
|
||||
/* define our own boolean type */
|
||||
typedef int bool;
|
||||
#define true ((bool)1)
|
||||
#define false ((bool)0)
|
||||
typedef int cjbool;
|
||||
#define true ((cjbool)1)
|
||||
#define false ((cjbool)0)
|
||||
|
||||
static const char *global_ep = NULL;
|
||||
|
||||
@@ -88,6 +88,11 @@ static char* cJSON_strdup(const char* str)
|
||||
size_t len = 0;
|
||||
char *copy = NULL;
|
||||
|
||||
if (str == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen(str) + 1;
|
||||
if (!(copy = (char*)cJSON_malloc(len)))
|
||||
{
|
||||
@@ -244,6 +249,7 @@ typedef struct
|
||||
char *buffer;
|
||||
int length;
|
||||
int offset;
|
||||
cjbool noalloc;
|
||||
} printbuffer;
|
||||
|
||||
/* realloc printbuffer if necessary to have at least "needed" bytes more */
|
||||
@@ -261,6 +267,10 @@ 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)
|
||||
@@ -486,7 +496,7 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((*end_ptr != '\"') && *end_ptr && ++len)
|
||||
while ((*end_ptr != '\"') && *end_ptr)
|
||||
{
|
||||
if (*end_ptr++ == '\\')
|
||||
{
|
||||
@@ -498,6 +508,7 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep)
|
||||
/* Skip escaped quotes. */
|
||||
end_ptr++;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
|
||||
/* This is at most how long we need for the string, roughly. */
|
||||
@@ -652,7 +663,7 @@ static char *print_string_ptr(const char *str, printbuffer *p)
|
||||
char *ptr2 = NULL;
|
||||
char *out = NULL;
|
||||
int len = 0;
|
||||
bool flag = false;
|
||||
cjbool flag = false;
|
||||
unsigned char token = '\0';
|
||||
|
||||
/* empty string */
|
||||
@@ -712,8 +723,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 */
|
||||
@@ -798,11 +810,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, bool 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, bool 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, bool 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)
|
||||
@@ -816,7 +828,7 @@ 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, bool require_null_terminated)
|
||||
cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cjbool require_null_terminated)
|
||||
{
|
||||
const char *end = NULL;
|
||||
/* use global error pointer if no specific one was given */
|
||||
@@ -872,7 +884,7 @@ char *cJSON_PrintUnformatted(const cJSON *item)
|
||||
return print_value(item, 0, 0, 0);
|
||||
}
|
||||
|
||||
char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, bool fmt)
|
||||
char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt)
|
||||
{
|
||||
printbuffer p;
|
||||
p.buffer = (char*)cJSON_malloc(prebuffer);
|
||||
@@ -882,10 +894,20 @@ char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, bool fmt)
|
||||
}
|
||||
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)
|
||||
@@ -936,7 +958,7 @@ static const char *parse_value(cJSON *item, const char *value, const char **ep)
|
||||
}
|
||||
|
||||
/* Render a value to text. */
|
||||
static char *print_value(const cJSON *item, int depth, bool fmt, printbuffer *p)
|
||||
static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *p)
|
||||
{
|
||||
char *out = NULL;
|
||||
|
||||
@@ -972,6 +994,27 @@ static char *print_value(const cJSON *item, int depth, bool fmt, printbuffer *p)
|
||||
case cJSON_Number:
|
||||
out = print_number(item, p);
|
||||
break;
|
||||
case cJSON_Raw:
|
||||
{
|
||||
size_t raw_length = 0;
|
||||
if (item->valuestring == NULL)
|
||||
{
|
||||
if (!p->noalloc)
|
||||
{
|
||||
cJSON_free(p->buffer);
|
||||
}
|
||||
out = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
raw_length = strlen(item->valuestring) + sizeof('\0');
|
||||
out = ensure(p, raw_length);
|
||||
if (out)
|
||||
{
|
||||
memcpy(out, item->valuestring, raw_length);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cJSON_String:
|
||||
out = print_string(item, p);
|
||||
break;
|
||||
@@ -999,6 +1042,9 @@ static char *print_value(const cJSON *item, int depth, bool fmt, printbuffer *p)
|
||||
case cJSON_Number:
|
||||
out = print_number(item, 0);
|
||||
break;
|
||||
case cJSON_Raw:
|
||||
out = cJSON_strdup(item->valuestring);
|
||||
break;
|
||||
case cJSON_String:
|
||||
out = print_string(item, 0);
|
||||
break;
|
||||
@@ -1082,7 +1128,7 @@ static const char *parse_array(cJSON *item,const char *value,const char **ep)
|
||||
}
|
||||
|
||||
/* Render an array to text */
|
||||
static char *print_array(const cJSON *item, int depth, bool fmt, printbuffer *p)
|
||||
static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *p)
|
||||
{
|
||||
char **entries;
|
||||
char *out = NULL;
|
||||
@@ -1092,7 +1138,7 @@ static char *print_array(const cJSON *item, int depth, bool fmt, printbuffer *p)
|
||||
cJSON *child = item->child;
|
||||
int numentries = 0;
|
||||
int i = 0;
|
||||
bool fail = false;
|
||||
cjbool fail = false;
|
||||
size_t tmplen = 0;
|
||||
|
||||
/* How many entries in the array? */
|
||||
@@ -1137,7 +1183,10 @@ static char *print_array(const cJSON *item, int depth, bool 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)
|
||||
{
|
||||
@@ -1343,7 +1392,7 @@ static const char *parse_object(cJSON *item, const char *value, const char **ep)
|
||||
}
|
||||
|
||||
/* Render an object to text. */
|
||||
static char *print_object(const cJSON *item, int depth, bool fmt, printbuffer *p)
|
||||
static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *p)
|
||||
{
|
||||
char **entries = NULL;
|
||||
char **names = NULL;
|
||||
@@ -1356,7 +1405,7 @@ static char *print_object(const cJSON *item, int depth, bool fmt, printbuffer *p
|
||||
int j = 0;
|
||||
cJSON *child = item->child;
|
||||
int numentries = 0;
|
||||
bool fail = false;
|
||||
cjbool fail = false;
|
||||
size_t tmplen = 0;
|
||||
|
||||
/* Count the number of entries. */
|
||||
@@ -1434,7 +1483,10 @@ static char *print_object(const cJSON *item, int depth, bool 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;
|
||||
@@ -1451,7 +1503,10 @@ static char *print_object(const cJSON *item, int depth, bool 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 */
|
||||
@@ -1652,7 +1707,7 @@ cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string)
|
||||
return c;
|
||||
}
|
||||
|
||||
bool cJSON_HasObjectItem(const cJSON *object,const char *string)
|
||||
cjbool cJSON_HasObjectItem(const cJSON *object,const char *string)
|
||||
{
|
||||
return cJSON_GetObjectItem(object, string) ? 1 : 0;
|
||||
}
|
||||
@@ -1731,7 +1786,10 @@ void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
|
||||
{
|
||||
cJSON_free(item->string);
|
||||
}
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
item->string = (char*)string;
|
||||
#pragma GCC diagnostic pop
|
||||
item->type |= cJSON_StringIsConst;
|
||||
cJSON_AddItemToArray(object, item);
|
||||
}
|
||||
@@ -1918,7 +1976,7 @@ cJSON *cJSON_CreateFalse(void)
|
||||
return item;
|
||||
}
|
||||
|
||||
cJSON *cJSON_CreateBool(bool b)
|
||||
cJSON *cJSON_CreateBool(cjbool b)
|
||||
{
|
||||
cJSON *item = cJSON_New_Item();
|
||||
if(item)
|
||||
@@ -1959,6 +2017,23 @@ cJSON *cJSON_CreateString(const char *string)
|
||||
return item;
|
||||
}
|
||||
|
||||
extern cJSON *cJSON_CreateRaw(const char *raw)
|
||||
{
|
||||
cJSON *item = cJSON_New_Item();
|
||||
if(item)
|
||||
{
|
||||
item->type = cJSON_Raw;
|
||||
item->valuestring = cJSON_strdup(raw);
|
||||
if(!item->valuestring)
|
||||
{
|
||||
cJSON_Delete(item);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
cJSON *cJSON_CreateArray(void)
|
||||
{
|
||||
cJSON *item = cJSON_New_Item();
|
||||
@@ -2095,7 +2170,7 @@ cJSON *cJSON_CreateStringArray(const char **strings, int count)
|
||||
}
|
||||
|
||||
/* Duplication */
|
||||
cJSON *cJSON_Duplicate(const cJSON *item, bool recurse)
|
||||
cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse)
|
||||
{
|
||||
cJSON *newitem = NULL;
|
||||
cJSON *cptr = NULL;
|
||||
@@ -2128,7 +2203,7 @@ cJSON *cJSON_Duplicate(const cJSON *item, bool recurse)
|
||||
}
|
||||
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);
|
||||
|
||||
13
cJSON.h
13
cJSON.h
@@ -38,6 +38,7 @@ extern "C"
|
||||
#define cJSON_String (1 << 4)
|
||||
#define cJSON_Array (1 << 5)
|
||||
#define cJSON_Object (1 << 6)
|
||||
#define cJSON_Raw (1 << 7) /* raw json */
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
#define cJSON_StringIsConst 512
|
||||
@@ -54,7 +55,7 @@ typedef struct cJSON
|
||||
/* The type of the item, as above. */
|
||||
int type;
|
||||
|
||||
/* The item's string, if type==cJSON_String */
|
||||
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
|
||||
char *valuestring;
|
||||
/* The item's number, if type==cJSON_Number */
|
||||
int valueint;
|
||||
@@ -83,6 +84,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);
|
||||
|
||||
@@ -103,6 +106,8 @@ extern cJSON *cJSON_CreateFalse(void);
|
||||
extern cJSON *cJSON_CreateBool(int b);
|
||||
extern cJSON *cJSON_CreateNumber(double num);
|
||||
extern cJSON *cJSON_CreateString(const char *string);
|
||||
/* raw json */
|
||||
extern cJSON *cJSON_CreateRaw(const char *raw);
|
||||
extern cJSON *cJSON_CreateArray(void);
|
||||
extern cJSON *cJSON_CreateObject(void);
|
||||
|
||||
@@ -115,7 +120,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);
|
||||
@@ -150,6 +158,7 @@ extern void cJSON_Minify(char *json);
|
||||
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
|
||||
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
|
||||
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
|
||||
#define cJSON_AddRawToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateRaw(s))
|
||||
|
||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||
#define cJSON_SetIntValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
|
||||
|
||||
130
test.c
130
test.c
@@ -22,10 +22,11 @@
|
||||
|
||||
#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 = NULL;
|
||||
cJSON *json = NULL;
|
||||
@@ -44,8 +45,9 @@ void doit(char *text)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Read a file, parse, render back, etc. */
|
||||
void dofile(char *filename)
|
||||
static void dofile(char *filename)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
long len = 0;
|
||||
@@ -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,8 +89,75 @@ 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 = (char*)malloc(len);
|
||||
if (buf == NULL)
|
||||
{
|
||||
printf("Failed to allocate memory.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* create buffer to fail */
|
||||
len_fail = strlen(out);
|
||||
buf_fail = (char*)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 = NULL;
|
||||
@@ -90,7 +165,6 @@ void create_objects(void)
|
||||
cJSON *img = NULL;
|
||||
cJSON *thm = NULL;
|
||||
cJSON *fld = NULL;
|
||||
char *out = NULL;
|
||||
int i = 0;
|
||||
|
||||
/* Our "days of the week" array: */
|
||||
@@ -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)
|
||||
|
||||
22
test_utils.c
22
test_utils.c
@@ -96,14 +96,14 @@ int main(void)
|
||||
printf("JSON Apply Patch Tests\n");
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
cJSON *object = cJSON_Parse(patches[i][0]);
|
||||
cJSON *object_to_be_patched = cJSON_Parse(patches[i][0]);
|
||||
cJSON *patch = cJSON_Parse(patches[i][1]);
|
||||
int err = cJSONUtils_ApplyPatches(object, patch);
|
||||
char *output = cJSON_Print(object);
|
||||
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);
|
||||
|
||||
free(output);
|
||||
cJSON_Delete(object);
|
||||
cJSON_Delete(object_to_be_patched);
|
||||
cJSON_Delete(patch);
|
||||
}
|
||||
|
||||
@@ -168,19 +168,19 @@ int main(void)
|
||||
printf("JSON Merge Patch tests\n");
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
cJSON *object = cJSON_Parse(merges[i][0]);
|
||||
cJSON *object_to_be_merged = cJSON_Parse(merges[i][0]);
|
||||
cJSON *patch = cJSON_Parse(merges[i][1]);
|
||||
char *before = cJSON_PrintUnformatted(object);
|
||||
char *before_merge = cJSON_PrintUnformatted(object_to_be_merged);
|
||||
patchtext = cJSON_PrintUnformatted(patch);
|
||||
printf("Before: [%s] -> [%s] = ", before, patchtext);
|
||||
object = cJSONUtils_MergePatch(object, patch);
|
||||
after = cJSON_PrintUnformatted(object);
|
||||
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);
|
||||
free(before_merge);
|
||||
free(patchtext);
|
||||
free(after);
|
||||
cJSON_Delete(object);
|
||||
cJSON_Delete(object_to_be_merged);
|
||||
cJSON_Delete(patch);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user