Compare commits

...

52 Commits

Author SHA1 Message Date
Max Bruckner
de8eaaba89 Release version 1.2.0 2017-01-09 12:25:31 +01:00
Max Bruckner
b2da44d6cb Merge pull request #90 from DaveGamble/cJSON_Raw
Add support for raw JSON
2017-01-09 12:22:00 +01:00
Max Bruckner
f6998a6a34 Contributors: Add Jiri Zouhar 2017-01-09 12:02:21 +01:00
Max Bruckner
e3e0b5150b cJSON_CreateRaw: Format fixes 2017-01-05 21:33:52 +01:00
Max Bruckner
1df987a170 cJSON_strdup: Check for NULL string 2017-01-05 21:31:17 +01:00
Max Bruckner
ddadb44a67 cJSON_Raw: Additional checks in print_value 2017-01-05 21:30:37 +01:00
Max Bruckner
9ef44fc0b6 Remove C++ comment in header 2017-01-05 21:12:10 +01:00
Max Bruckner
8c58e62597 Merge remote-tracking branch 'loigu/master' into cJSON_Raw 2017-01-05 21:07:08 +01:00
Max Bruckner
8893e39712 gitignore: ignore *.orig 2017-01-04 20:40:34 +01:00
Max Bruckner
3d6ae11340 Make cJSON C++ compatible 2016-12-28 12:33:20 +01:00
Max Bruckner
a1f2600883 Contributors: Add Romain Porte 2016-12-28 12:29:03 +01:00
Max Bruckner
fcc85bdfbc Gitignore: Add Makefile output 2016-12-28 12:23:56 +01:00
Max Bruckner
7d08a3518a Merge pull request #88 from MicroJoe/fix-readme-tests
Fix bad CMake argument in README
2016-12-28 12:20:37 +01:00
Romain Porte
cc486a0354 Fix bad CMake argument in README 2016-12-27 11:32:41 +01:00
Max Bruckner
fcc89c4bb2 Move increment out of loop condition fixes #85 2016-12-15 11:12:42 +01:00
Max Bruckner
a0431e226f Merge pull request #83 from gatzka/feature/cast_qual_v3
Introduce compiler check if const is casted away.
2016-12-08 21:59:32 +07:00
Stephan Gatzka
89edfb6741 Warn if cast removes a type qualifier like const. 2016-12-08 13:21:30 +01:00
Stephan
e69db83de5 Temporarily disable warning when const is cast away.
There was a long running discussion here
https://github.com/DaveGamble/cJSON/pull/80 how to provide const
correctness for users of cJSON.

To avoid breaking changes for users of cJSON v1 it was decided to
disable this warning.

pragma was tested with gcc 5.4.0/6.2.1 and clang 3.8/3.9.
2016-12-08 13:21:18 +01:00
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
Jiri Zouhar
06008b0444 add support to insert raw json 2016-11-14 11:20:10 +01:00
9 changed files with 232 additions and 59 deletions

5
.gitignore vendored
View File

@@ -8,3 +8,8 @@ test
tags
*.dylib
build/
cJSON_test
cJSON_test_utils
libcjson.so.*
libcjson_utils.so.*
*.orig

View File

@@ -6,16 +6,16 @@ include(GNUInstallDirs)
project(cJSON C)
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 0)
set(PROJECT_VERSION_PATCH 2)
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()

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

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.2
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

View File

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

87
cJSON.c
View File

@@ -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. */
@@ -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 */
@@ -882,10 +894,20 @@ char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool 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)
@@ -972,6 +994,27 @@ static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *
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, cjbool fmt, printbuffer *
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;
@@ -1137,7 +1183,10 @@ static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *
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)
{
@@ -1434,7 +1483,10 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer
}
/* 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, cjbool fmt, printbuffer
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 */
@@ -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);
}
@@ -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();
@@ -2128,7 +2203,7 @@ cJSON *cJSON_Duplicate(const cJSON *item, cjbool 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
View File

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

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

View File

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