Compare commits
86 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
030d0c14cc | ||
|
|
02cd3eec37 | ||
|
|
bdb59f09de | ||
|
|
5f783fff11 | ||
|
|
7969af6434 | ||
|
|
0bb1843925 | ||
|
|
5ea4fad263 | ||
|
|
1749de02f8 | ||
|
|
748f4bfd4f | ||
|
|
bea1d102fd | ||
|
|
d441fa05b3 | ||
|
|
3fe72cf2b8 | ||
|
|
d8d0ae66d3 | ||
|
|
9d07917feb | ||
|
|
ad5abf4c5b | ||
|
|
2c45ad7816 | ||
|
|
6405fd15e3 | ||
|
|
b44c917be9 | ||
|
|
2d3520e0b9 | ||
|
|
2e118df0cd | ||
|
|
412f4f7d62 | ||
|
|
0aea75fbda | ||
|
|
0c0dd4a5b0 | ||
|
|
dd4cb5400f | ||
|
|
1ea72f8260 | ||
|
|
e78bc42362 | ||
|
|
6f271e511f | ||
|
|
bee069b4e7 | ||
|
|
1e0bd24f2c | ||
|
|
5cf56fa4fa | ||
|
|
3f349a4258 | ||
|
|
40e3781e9b | ||
|
|
b056d7cb74 | ||
|
|
1f422b586a | ||
|
|
899529e866 | ||
|
|
2837aac23e | ||
|
|
024f690289 | ||
|
|
039b1cc653 | ||
|
|
2302f4f0b2 | ||
|
|
c45dc12fd7 | ||
|
|
ed8dc53699 | ||
|
|
c26d53f0d7 | ||
|
|
501046247d | ||
|
|
68cd0d4a11 | ||
|
|
56b819bfbc | ||
|
|
605422c60a | ||
|
|
cbbcc91498 | ||
|
|
b47d0e34ca | ||
|
|
bc12c69b54 | ||
|
|
1d42c9bc60 | ||
|
|
b71db93e03 | ||
|
|
6d5a7c8c40 | ||
|
|
8c1ed3ab82 | ||
|
|
f16dd7e028 | ||
|
|
08770fc246 | ||
|
|
0ca8587acc | ||
|
|
88e38d042f | ||
|
|
6a746a230a | ||
|
|
1e999352d3 | ||
|
|
6815d96617 | ||
|
|
61921498d0 | ||
|
|
4758d62fd4 | ||
|
|
1bc1a9748a | ||
|
|
de36476092 | ||
|
|
983a4cd286 | ||
|
|
b6abef94ff | ||
|
|
3d66766231 | ||
|
|
924122904e | ||
|
|
87691a86e5 | ||
|
|
8aa324fdc8 | ||
|
|
3c4d309f62 | ||
|
|
9bf531ca05 | ||
|
|
80354bdb06 | ||
|
|
fe2e0956ad | ||
|
|
cf71f3d627 | ||
|
|
da551c753f | ||
|
|
ae4681b787 | ||
|
|
c5a09a32a9 | ||
|
|
4785070ad3 | ||
|
|
0e0cd5bae5 | ||
|
|
44512f643e | ||
|
|
331c18d09a | ||
|
|
4fff92140e | ||
|
|
fc1d4b07df | ||
|
|
bd073343fa | ||
|
|
7c722dca5f |
54
.github/CONTRIBUTING.md
vendored
Normal file
54
.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
Contribution Guidelines
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Contributions to cJSON are welcome. If you find a bug or want to improve cJSON in another way, pull requests are appreciated.
|
||||||
|
|
||||||
|
For bigger changes, in order to avoid wasted effort, please open an issue to discuss the technical details before creating a pull request.
|
||||||
|
|
||||||
|
The further sections explain the process in more detail and provides some guidelines on how contributions should look like.
|
||||||
|
|
||||||
|
Branches
|
||||||
|
--------
|
||||||
|
There are two branches to be aware of, the `master` and the `develop` branch. The `master` branch is reserved for the latest release, so only make pull requests to the `master` branch for small bug- or security fixes (these are usually just a few lines). In all other cases, please make a pull request to the `develop` branch.
|
||||||
|
|
||||||
|
Coding Style
|
||||||
|
------------
|
||||||
|
The coding style has been discussed in [#24](https://github.com/DaveGamble/cJSON/issues/24). The basics are:
|
||||||
|
|
||||||
|
* Use 4 tabs for indentation
|
||||||
|
* No oneliners (conditions, loops, variable declarations ...)
|
||||||
|
* Always use parenthesis for control structures
|
||||||
|
* Don't implicitly rely on operator precedence, use round brackets in expressions. e.g. `(a > b) && (c < d)` instead of `a>b && c<d`
|
||||||
|
* opening curly braces start in the next line
|
||||||
|
* use spaces around operators
|
||||||
|
* lines should not have trailing whitespace
|
||||||
|
* use spaces between function parameters
|
||||||
|
* use pronouncable variable names, not just a combination of letters
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* calculate the new length of the string in a printbuffer and update the offset */
|
||||||
|
static void update_offset(printbuffer * const buffer)
|
||||||
|
{
|
||||||
|
const unsigned char *buffer_pointer = NULL;
|
||||||
|
if ((buffer == NULL) || (buffer->buffer == NULL))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buffer_pointer = buffer->buffer + buffer->offset;
|
||||||
|
|
||||||
|
buffer->offset += strlen((const char*)buffer_pointer);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Unit Tests
|
||||||
|
----------
|
||||||
|
cJSON uses the [Unity](https://github.com/ThrowTheSwitch/Unity) library for unit tests. The tests are located in the `tests` directory. In order to add a new test, either add it to one of the existing files (if it fits) or add a new C file for the test. That new file has to be added to the list of tests in `tests/CMakeLists.txt`.
|
||||||
|
|
||||||
|
All new features have to be covered by unit tests.
|
||||||
|
|
||||||
|
Other Notes
|
||||||
|
-----------
|
||||||
|
* Internal functions are to be declared static.
|
||||||
|
* Wrap the return type of external function in the `CJSON_PUBLIC` macro.
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
|
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
subdirs(tests)
|
subdirs(tests fuzzing)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
project(cJSON C)
|
project(cJSON C)
|
||||||
|
|
||||||
set(PROJECT_VERSION_MAJOR 1)
|
set(PROJECT_VERSION_MAJOR 1)
|
||||||
set(PROJECT_VERSION_MINOR 3)
|
set(PROJECT_VERSION_MINOR 4)
|
||||||
set(PROJECT_VERSION_PATCH 2)
|
set(PROJECT_VERSION_PATCH 0)
|
||||||
set(CJSON_VERSION_SO 1)
|
set(CJSON_VERSION_SO 1)
|
||||||
set(CJSON_UTILS_VERSION_SO 1)
|
set(CJSON_UTILS_VERSION_SO 1)
|
||||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
@@ -40,6 +40,9 @@ if (ENABLE_CUSTOM_COMPILER_FLAGS)
|
|||||||
-Wconversion
|
-Wconversion
|
||||||
-Wc++-compat
|
-Wc++-compat
|
||||||
-fstack-protector-strong
|
-fstack-protector-strong
|
||||||
|
-Wcomma
|
||||||
|
-Wdouble-promotion
|
||||||
|
-Wparentheses
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -58,6 +61,16 @@ if (ENABLE_SANITIZERS)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(ENABLE_PUBLIC_SYMBOLS "Export library symbols." On)
|
||||||
|
if (ENABLE_PUBLIC_SYMBOLS)
|
||||||
|
list(APPEND custom_compiler_flags -fvisibility=hidden)
|
||||||
|
add_definitions(-DCJSON_EXPORT_SYMBOLS -DCJSON_API_VISIBILITY)
|
||||||
|
endif()
|
||||||
|
option(ENABLE_HIDDEN_SYMBOLS "Hide library symbols." Off)
|
||||||
|
if (ENABLE_HIDDEN_SYMBOLS)
|
||||||
|
add_definitions(-DCJSON_HIDE_SYMBOLS -UCJSON_API_VISIBILITY)
|
||||||
|
endif()
|
||||||
|
|
||||||
# apply custom compiler flags
|
# apply custom compiler flags
|
||||||
foreach(compiler_flag ${custom_compiler_flags})
|
foreach(compiler_flag ${custom_compiler_flags})
|
||||||
#remove problematic characters
|
#remove problematic characters
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ Contributors
|
|||||||
* [Linus Wallgren](https://github.com/ecksun)
|
* [Linus Wallgren](https://github.com/ecksun)
|
||||||
* [Max Bruckner](https://github.com/FSMaxB)
|
* [Max Bruckner](https://github.com/FSMaxB)
|
||||||
* Mike Pontillo
|
* Mike Pontillo
|
||||||
|
* [Mike Jerris](https://github.com/mjerris)
|
||||||
* Paulo Antonio Alvarez
|
* Paulo Antonio Alvarez
|
||||||
* [Rafael Leal Dias](https://github.com/rafaeldias)
|
* [Rafael Leal Dias](https://github.com/rafaeldias)
|
||||||
* [Rod Vagg](https://github.com/rvagg)
|
* [Rod Vagg](https://github.com/rvagg)
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -10,7 +10,7 @@ UTILS_TEST_SRC = cJSON.c cJSON_Utils.c test_utils.c
|
|||||||
|
|
||||||
LDLIBS = -lm
|
LDLIBS = -lm
|
||||||
|
|
||||||
LIBVERSION = 1.3.2
|
LIBVERSION = 1.4.0
|
||||||
CJSON_SOVERSION = 1
|
CJSON_SOVERSION = 1
|
||||||
UTILS_SOVERSION = 1
|
UTILS_SOVERSION = 1
|
||||||
|
|
||||||
|
|||||||
148
cJSON.h
148
cJSON.h
@@ -30,11 +30,8 @@ extern "C"
|
|||||||
|
|
||||||
/* project version */
|
/* project version */
|
||||||
#define CJSON_VERSION_MAJOR 1
|
#define CJSON_VERSION_MAJOR 1
|
||||||
#define CJSON_VERSION_MINOR 3
|
#define CJSON_VERSION_MINOR 4
|
||||||
#define CJSON_VERSION_PATCH 2
|
#define CJSON_VERSION_PATCH 0
|
||||||
|
|
||||||
/* returns the version of cJSON as a string */
|
|
||||||
extern const char* cJSON_Version(void);
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@@ -81,84 +78,139 @@ typedef struct cJSON_Hooks
|
|||||||
void (*free_fn)(void *ptr);
|
void (*free_fn)(void *ptr);
|
||||||
} cJSON_Hooks;
|
} cJSON_Hooks;
|
||||||
|
|
||||||
|
typedef int cJSON_bool;
|
||||||
|
|
||||||
|
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
|
||||||
|
#define __WINDOWS__
|
||||||
|
#endif
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
|
||||||
|
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options:
|
||||||
|
|
||||||
|
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
|
||||||
|
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols
|
||||||
|
|
||||||
|
For *nix builds that support visibility attribute, you can define similar behavior by
|
||||||
|
|
||||||
|
setting default visibility to hidden by adding
|
||||||
|
-fvisibility=hidden (for gcc)
|
||||||
|
or
|
||||||
|
-xldscope=hidden (for sun cc)
|
||||||
|
to CFLAGS
|
||||||
|
|
||||||
|
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(CJSON_HIDE_SYMBOLS)
|
||||||
|
#define CJSON_PUBLIC(type) type __stdcall
|
||||||
|
#elif defined(CJSON_EXPORT_SYMBOLS)
|
||||||
|
#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall
|
||||||
|
#else
|
||||||
|
#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall
|
||||||
|
#endif
|
||||||
|
#else /* !WIN32 */
|
||||||
|
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
|
||||||
|
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
|
||||||
|
#else
|
||||||
|
#define CJSON_PUBLIC(type) type
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* returns the version of cJSON as a string */
|
||||||
|
CJSON_PUBLIC(const char*) cJSON_Version(void);
|
||||||
|
|
||||||
/* Supply malloc, realloc and free functions to cJSON */
|
/* Supply malloc, realloc and free functions to cJSON */
|
||||||
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
|
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||||
|
|
||||||
|
|
||||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
|
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
|
||||||
extern cJSON *cJSON_Parse(const char *value);
|
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
|
||||||
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
|
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
|
||||||
extern char *cJSON_Print(const cJSON *item);
|
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
|
||||||
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
|
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
|
||||||
extern char *cJSON_PrintUnformatted(const cJSON *item);
|
CJSON_PUBLIC(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 */
|
/* 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);
|
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool 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. */
|
/* 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);
|
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt);
|
||||||
/* Delete a cJSON entity and all subentities. */
|
/* Delete a cJSON entity and all subentities. */
|
||||||
extern void cJSON_Delete(cJSON *c);
|
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
|
||||||
|
|
||||||
/* Returns the number of items in an array (or object). */
|
/* Returns the number of items in an array (or object). */
|
||||||
extern int cJSON_GetArraySize(const cJSON *array);
|
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
|
||||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||||
extern cJSON *cJSON_GetArrayItem(const cJSON *array, int item);
|
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item);
|
||||||
/* Get item "string" from object. Case insensitive. */
|
/* Get item "string" from object. Case insensitive. */
|
||||||
extern cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string);
|
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string);
|
||||||
extern int cJSON_HasObjectItem(const cJSON *object, const char *string);
|
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *object, const char *string);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
|
||||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||||
extern const char *cJSON_GetErrorPtr(void);
|
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
|
||||||
|
|
||||||
|
/* These functions check the type of an item */
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
|
||||||
|
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
|
||||||
|
|
||||||
/* These calls create a cJSON item of the appropriate type. */
|
/* These calls create a cJSON item of the appropriate type. */
|
||||||
extern cJSON *cJSON_CreateNull(void);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
|
||||||
extern cJSON *cJSON_CreateTrue(void);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
|
||||||
extern cJSON *cJSON_CreateFalse(void);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
|
||||||
extern cJSON *cJSON_CreateBool(int b);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
|
||||||
extern cJSON *cJSON_CreateNumber(double num);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
|
||||||
extern cJSON *cJSON_CreateString(const char *string);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
|
||||||
/* raw json */
|
/* raw json */
|
||||||
extern cJSON *cJSON_CreateRaw(const char *raw);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
|
||||||
extern cJSON *cJSON_CreateArray(void);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
|
||||||
extern cJSON *cJSON_CreateObject(void);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
|
||||||
|
|
||||||
/* These utilities create an Array of count items. */
|
/* These utilities create an Array of count items. */
|
||||||
extern cJSON *cJSON_CreateIntArray(const int *numbers, int count);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
|
||||||
extern cJSON *cJSON_CreateFloatArray(const float *numbers, int count);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
|
||||||
extern cJSON *cJSON_CreateDoubleArray(const double *numbers, int count);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
|
||||||
extern cJSON *cJSON_CreateStringArray(const char **strings, int count);
|
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
|
||||||
|
|
||||||
/* Append item to the specified array/object. */
|
/* Append item to the specified array/object. */
|
||||||
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||||
extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
|
CJSON_PUBLIC(void) cJSON_AddItemToObject(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
|
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
|
||||||
* writing to `item->string` */
|
* writing to `item->string` */
|
||||||
extern void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
|
CJSON_PUBLIC(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. */
|
/* 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);
|
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||||
extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||||
|
|
||||||
/* Remove/Detatch items from Arrays/Objects. */
|
/* Remove/Detatch items from Arrays/Objects. */
|
||||||
extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which);
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
|
||||||
extern void cJSON_DeleteItemFromArray(cJSON *array, int which);
|
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
|
||||||
extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string);
|
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
|
||||||
extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string);
|
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
|
||||||
|
|
||||||
/* Update array items. */
|
/* Update array items. */
|
||||||
extern void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
||||||
extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
||||||
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||||
|
|
||||||
/* Duplicate a cJSON item */
|
/* Duplicate a cJSON item */
|
||||||
extern cJSON *cJSON_Duplicate(const cJSON *item, int recurse);
|
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
|
||||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||||
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||||
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||||
|
|
||||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||||
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
|
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
|
||||||
extern cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated);
|
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
|
||||||
|
|
||||||
extern void cJSON_Minify(char *json);
|
CJSON_PUBLIC(void) cJSON_Minify(char *json);
|
||||||
|
|
||||||
/* Macros for creating things quickly. */
|
/* Macros for creating things quickly. */
|
||||||
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
|
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
|
||||||
@@ -172,11 +224,11 @@ extern void cJSON_Minify(char *json);
|
|||||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||||
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
|
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
|
||||||
/* helper for the cJSON_SetNumberValue macro */
|
/* helper for the cJSON_SetNumberValue macro */
|
||||||
extern double cJSON_SetNumberHelper(cJSON *object, double number);
|
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
|
||||||
#define cJSON_SetNumberValue(object, number) ((object) ? cJSON_SetNumberHelper(object, (double)number) : (number))
|
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
|
||||||
|
|
||||||
/* Macro for iterating over an array */
|
/* Macro for iterating over an array */
|
||||||
#define cJSON_ArrayForEach(pos, head) for(pos = (head)->child; pos != NULL; pos = pos->next)
|
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
#pragma GCC visibility push(default)
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#pragma GCC visibility pop
|
||||||
|
|
||||||
#include "cJSON_Utils.h"
|
#include "cJSON_Utils.h"
|
||||||
|
|
||||||
@@ -31,7 +33,7 @@ static int cJSONUtils_strcasecmp(const unsigned char *s1, const unsigned char *s
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)
|
for(; tolower(*s1) == tolower(*s2); (void)++s1, ++s2)
|
||||||
{
|
{
|
||||||
if(*s1 == 0)
|
if(*s1 == 0)
|
||||||
{
|
{
|
||||||
@@ -49,7 +51,7 @@ static int cJSONUtils_Pstrcasecmp(const unsigned char *a, const unsigned char *e
|
|||||||
{
|
{
|
||||||
return (a == e) ? 0 : 1; /* both NULL? */
|
return (a == e) ? 0 : 1; /* both NULL? */
|
||||||
}
|
}
|
||||||
for (; *a && *e && (*e != '/'); a++, e++) /* compare until next '/' */
|
for (; *a && *e && (*e != '/'); (void)a++, e++) /* compare until next '/' */
|
||||||
{
|
{
|
||||||
if (*e == '~')
|
if (*e == '~')
|
||||||
{
|
{
|
||||||
@@ -81,7 +83,7 @@ static int cJSONUtils_Pstrcasecmp(const unsigned char *a, const unsigned char *e
|
|||||||
static size_t cJSONUtils_PointerEncodedstrlen(const unsigned char *s)
|
static size_t cJSONUtils_PointerEncodedstrlen(const unsigned char *s)
|
||||||
{
|
{
|
||||||
size_t l = 0;
|
size_t l = 0;
|
||||||
for (; *s; s++, l++)
|
for (; *s; (void)s++, l++)
|
||||||
{
|
{
|
||||||
if ((*s == '~') || (*s == '/'))
|
if ((*s == '~') || (*s == '/'))
|
||||||
{
|
{
|
||||||
@@ -115,9 +117,8 @@ static void cJSONUtils_PointerEncodedstrcpy(unsigned char *d, const unsigned cha
|
|||||||
*d = '\0';
|
*d = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
|
CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
|
||||||
{
|
{
|
||||||
int type = object->type;
|
|
||||||
size_t c = 0;
|
size_t c = 0;
|
||||||
cJSON *obj = 0;
|
cJSON *obj = 0;
|
||||||
|
|
||||||
@@ -128,12 +129,12 @@ char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* recursively search all children of the object */
|
/* recursively search all children of the object */
|
||||||
for (obj = object->child; obj; obj = obj->next, c++)
|
for (obj = object->child; obj; (void)(obj = obj->next), c++)
|
||||||
{
|
{
|
||||||
unsigned char *found = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(obj, target);
|
unsigned char *found = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(obj, target);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if ((type & 0xFF) == cJSON_Array)
|
if (cJSON_IsArray(object))
|
||||||
{
|
{
|
||||||
/* reserve enough memory for a 64 bit integer + '/' and '\0' */
|
/* reserve enough memory for a 64 bit integer + '/' and '\0' */
|
||||||
unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + 23);
|
unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + 23);
|
||||||
@@ -150,7 +151,7 @@ char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
|
|||||||
|
|
||||||
return (char*)ret;
|
return (char*)ret;
|
||||||
}
|
}
|
||||||
else if ((type & 0xFF) == cJSON_Object)
|
else if (cJSON_IsObject(object))
|
||||||
{
|
{
|
||||||
unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + cJSONUtils_PointerEncodedstrlen((unsigned char*)obj->string) + 2);
|
unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + cJSONUtils_PointerEncodedstrlen((unsigned char*)obj->string) + 2);
|
||||||
*ret = '/';
|
*ret = '/';
|
||||||
@@ -171,12 +172,12 @@ char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON *object, const char *pointer)
|
||||||
{
|
{
|
||||||
/* follow path of the pointer */
|
/* follow path of the pointer */
|
||||||
while ((*pointer++ == '/') && object)
|
while ((*pointer++ == '/') && object)
|
||||||
{
|
{
|
||||||
if ((object->type & 0xFF) == cJSON_Array)
|
if (cJSON_IsArray(object))
|
||||||
{
|
{
|
||||||
size_t which = 0;
|
size_t which = 0;
|
||||||
/* parse array index */
|
/* parse array index */
|
||||||
@@ -195,7 +196,7 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
|
|||||||
}
|
}
|
||||||
object = cJSON_GetArrayItem(object, (int)which);
|
object = cJSON_GetArrayItem(object, (int)which);
|
||||||
}
|
}
|
||||||
else if ((object->type & 0xFF) == cJSON_Object)
|
else if (cJSON_IsObject(object))
|
||||||
{
|
{
|
||||||
object = object->child;
|
object = object->child;
|
||||||
/* GetObjectItem. */
|
/* GetObjectItem. */
|
||||||
@@ -227,7 +228,7 @@ static void cJSONUtils_InplaceDecodePointerString(unsigned char *string)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; *string; s2++, string++)
|
for (; *string; (void)s2++, string++)
|
||||||
{
|
{
|
||||||
*s2 = (*string != '~')
|
*s2 = (*string != '~')
|
||||||
? (*string)
|
? (*string)
|
||||||
@@ -269,11 +270,11 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const unsigned char *path)
|
|||||||
/* Couldn't find object to remove child from. */
|
/* Couldn't find object to remove child from. */
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
}
|
}
|
||||||
else if ((parent->type & 0xFF) == cJSON_Array)
|
else if (cJSON_IsArray(parent))
|
||||||
{
|
{
|
||||||
ret = cJSON_DetachItemFromArray(parent, atoi((char*)childptr));
|
ret = cJSON_DetachItemFromArray(parent, atoi((char*)childptr));
|
||||||
}
|
}
|
||||||
else if ((parent->type & 0xFF) == cJSON_Object)
|
else if (cJSON_IsObject(parent))
|
||||||
{
|
{
|
||||||
ret = cJSON_DetachItemFromObject(parent, (char*)childptr);
|
ret = cJSON_DetachItemFromObject(parent, (char*)childptr);
|
||||||
}
|
}
|
||||||
@@ -299,7 +300,7 @@ static int cJSONUtils_Compare(cJSON *a, cJSON *b)
|
|||||||
/* string mismatch. */
|
/* string mismatch. */
|
||||||
return (strcmp(a->valuestring, b->valuestring) != 0) ? -3 : 0;
|
return (strcmp(a->valuestring, b->valuestring) != 0) ? -3 : 0;
|
||||||
case cJSON_Array:
|
case cJSON_Array:
|
||||||
for (a = a->child, b = b->child; a && b; a = a->next, b = b->next)
|
for ((void)(a = a->child), b = b->child; a && b; (void)(a = a->next), b = b->next)
|
||||||
{
|
{
|
||||||
int err = cJSONUtils_Compare(a, b);
|
int err = cJSONUtils_Compare(a, b);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -474,7 +475,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
|||||||
cJSON_Delete(value);
|
cJSON_Delete(value);
|
||||||
return 9;
|
return 9;
|
||||||
}
|
}
|
||||||
else if ((parent->type & 0xFF) == cJSON_Array)
|
else if (cJSON_IsArray(parent))
|
||||||
{
|
{
|
||||||
if (!strcmp((char*)childptr, "-"))
|
if (!strcmp((char*)childptr, "-"))
|
||||||
{
|
{
|
||||||
@@ -485,7 +486,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
|||||||
cJSON_InsertItemInArray(parent, atoi((char*)childptr), value);
|
cJSON_InsertItemInArray(parent, atoi((char*)childptr), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((parent->type & 0xFF) == cJSON_Object)
|
else if (cJSON_IsObject(parent))
|
||||||
{
|
{
|
||||||
cJSON_DeleteItemFromObject(parent, (char*)childptr);
|
cJSON_DeleteItemFromObject(parent, (char*)childptr);
|
||||||
cJSON_AddItemToObject(parent, (char*)childptr, value);
|
cJSON_AddItemToObject(parent, (char*)childptr, value);
|
||||||
@@ -499,7 +500,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches)
|
CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@@ -508,7 +509,7 @@ int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((patches->type & 0xFF) != cJSON_Array)
|
if (cJSON_IsArray(patches))
|
||||||
{
|
{
|
||||||
/* malformed patches. */
|
/* malformed patches. */
|
||||||
return 1;
|
return 1;
|
||||||
@@ -551,7 +552,7 @@ static void cJSONUtils_GeneratePatch(cJSON *patches, const unsigned char *op, co
|
|||||||
cJSON_AddItemToArray(patches, patch);
|
cJSON_AddItemToArray(patches, patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val)
|
CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val)
|
||||||
{
|
{
|
||||||
cJSONUtils_GeneratePatch(array, (const unsigned char*)op, (const unsigned char*)path, 0, val);
|
cJSONUtils_GeneratePatch(array, (const unsigned char*)op, (const unsigned char*)path, 0, val);
|
||||||
}
|
}
|
||||||
@@ -590,7 +591,7 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const unsigned char *path,
|
|||||||
size_t c = 0;
|
size_t c = 0;
|
||||||
unsigned char *newpath = (unsigned char*)malloc(strlen((const char*)path) + 23); /* Allow space for 64bit int. */
|
unsigned char *newpath = (unsigned char*)malloc(strlen((const char*)path) + 23); /* Allow space for 64bit int. */
|
||||||
/* generate patches for all array elements that exist in "from" and "to" */
|
/* 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++)
|
for ((void)(c = 0), (void)(from = from->child), to = to->child; from && to; (void)(from = from->next), (void)(to = to->next), c++)
|
||||||
{
|
{
|
||||||
/* check if conversion to unsigned long is valid
|
/* check if conversion to unsigned long is valid
|
||||||
* This should be eliminated at compile time by dead code elimination
|
* This should be eliminated at compile time by dead code elimination
|
||||||
@@ -604,7 +605,7 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const unsigned char *path,
|
|||||||
cJSONUtils_CompareToPatch(patches, newpath, from, to);
|
cJSONUtils_CompareToPatch(patches, newpath, from, to);
|
||||||
}
|
}
|
||||||
/* remove leftover elements from 'from' that are not in 'to' */
|
/* remove leftover elements from 'from' that are not in 'to' */
|
||||||
for (; from; from = from->next, c++)
|
for (; from; (void)(from = from->next), c++)
|
||||||
{
|
{
|
||||||
/* check if conversion to unsigned long is valid
|
/* check if conversion to unsigned long is valid
|
||||||
* This should be eliminated at compile time by dead code elimination
|
* This should be eliminated at compile time by dead code elimination
|
||||||
@@ -618,7 +619,7 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const unsigned char *path,
|
|||||||
cJSONUtils_GeneratePatch(patches, (const unsigned char*)"remove", path, newpath, 0);
|
cJSONUtils_GeneratePatch(patches, (const unsigned char*)"remove", path, newpath, 0);
|
||||||
}
|
}
|
||||||
/* add new elements in 'to' that were not in 'from' */
|
/* add new elements in 'to' that were not in 'from' */
|
||||||
for (; to; to = to->next, c++)
|
for (; to; (void)(to = to->next), c++)
|
||||||
{
|
{
|
||||||
cJSONUtils_GeneratePatch(patches, (const unsigned char*)"add", path, (const unsigned char*)"-", to);
|
cJSONUtils_GeneratePatch(patches, (const unsigned char*)"add", path, (const unsigned char*)"-", to);
|
||||||
}
|
}
|
||||||
@@ -671,7 +672,7 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const unsigned char *path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSON* cJSONUtils_GeneratePatches(cJSON *from, cJSON *to)
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON *from, cJSON *to)
|
||||||
{
|
{
|
||||||
cJSON *patches = cJSON_CreateArray();
|
cJSON *patches = cJSON_CreateArray();
|
||||||
cJSONUtils_CompareToPatch(patches, (const unsigned char*)"", from, to);
|
cJSONUtils_CompareToPatch(patches, (const unsigned char*)"", from, to);
|
||||||
@@ -786,21 +787,21 @@ static cJSON *cJSONUtils_SortList(cJSON *list)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cJSONUtils_SortObject(cJSON *object)
|
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON *object)
|
||||||
{
|
{
|
||||||
object->child = cJSONUtils_SortList(object->child);
|
object->child = cJSONUtils_SortList(object->child);
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
|
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
|
||||||
{
|
{
|
||||||
if (!patch || ((patch->type & 0xFF) != cJSON_Object))
|
if (!cJSON_IsObject(patch))
|
||||||
{
|
{
|
||||||
/* scalar value, array or NULL, just duplicate */
|
/* scalar value, array or NULL, just duplicate */
|
||||||
cJSON_Delete(target);
|
cJSON_Delete(target);
|
||||||
return cJSON_Duplicate(patch, 1);
|
return cJSON_Duplicate(patch, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target || ((target->type & 0xFF) != cJSON_Object))
|
if (!cJSON_IsObject(target))
|
||||||
{
|
{
|
||||||
cJSON_Delete(target);
|
cJSON_Delete(target);
|
||||||
target = cJSON_CreateObject();
|
target = cJSON_CreateObject();
|
||||||
@@ -809,7 +810,7 @@ cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
|
|||||||
patch = patch->child;
|
patch = patch->child;
|
||||||
while (patch)
|
while (patch)
|
||||||
{
|
{
|
||||||
if ((patch->type & 0xFF) == cJSON_NULL)
|
if (cJSON_IsNull(patch))
|
||||||
{
|
{
|
||||||
/* NULL is the indicator to remove a value, see RFC7396 */
|
/* NULL is the indicator to remove a value, see RFC7396 */
|
||||||
cJSON_DeleteItemFromObject(target, patch->string);
|
cJSON_DeleteItemFromObject(target, patch->string);
|
||||||
@@ -824,7 +825,7 @@ cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to)
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to)
|
||||||
{
|
{
|
||||||
cJSON *patch = NULL;
|
cJSON *patch = NULL;
|
||||||
if (!to)
|
if (!to)
|
||||||
@@ -832,7 +833,7 @@ cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to)
|
|||||||
/* patch to delete everything */
|
/* patch to delete everything */
|
||||||
return cJSON_CreateNull();
|
return cJSON_CreateNull();
|
||||||
}
|
}
|
||||||
if (((to->type & 0xFF) != cJSON_Object) || !from || ((from->type & 0xFF) != cJSON_Object))
|
if (!cJSON_IsObject(to) || !cJSON_IsObject(from))
|
||||||
{
|
{
|
||||||
return cJSON_Duplicate(to, 1);
|
return cJSON_Duplicate(to, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
|
|
||||||
/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
|
/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
|
||||||
cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer);
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON *object, const char *pointer);
|
||||||
|
|
||||||
/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */
|
/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */
|
||||||
cJSON* cJSONUtils_GeneratePatches(cJSON *from, cJSON *to);
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON *from, cJSON *to);
|
||||||
/* Utility for generating patch array entries. */
|
/* Utility for generating patch array entries. */
|
||||||
void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val);
|
CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val);
|
||||||
/* Returns 0 for success. */
|
/* Returns 0 for success. */
|
||||||
int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches);
|
CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use:
|
// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use:
|
||||||
@@ -33,12 +33,12 @@ int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches);
|
|||||||
|
|
||||||
/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */
|
/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */
|
||||||
/* target will be modified by patch. return value is new ptr for target. */
|
/* target will be modified by patch. return value is new ptr for target. */
|
||||||
cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch);
|
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, cJSON *patch);
|
||||||
/* generates a patch to move from -> to */
|
/* generates a patch to move from -> to */
|
||||||
cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to);
|
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to);
|
||||||
|
|
||||||
/* Given a root object and a target object, construct a pointer from one to the other. */
|
/* Given a root object and a target object, construct a pointer from one to the other. */
|
||||||
char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target);
|
CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target);
|
||||||
|
|
||||||
/* Sorts the members of the object into alphabetical order. */
|
/* Sorts the members of the object into alphabetical order. */
|
||||||
void cJSONUtils_SortObject(cJSON *object);
|
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON *object);
|
||||||
|
|||||||
1
fuzzing/.gitignore
vendored
Normal file
1
fuzzing/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
afl-build
|
||||||
28
fuzzing/CMakeLists.txt
Normal file
28
fuzzing/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
option(ENABLE_FUZZING "Create executables and targets for fuzzing cJSON with afl." Off)
|
||||||
|
if (ENABLE_FUZZING)
|
||||||
|
find_program(AFL_FUZZ afl-fuzz)
|
||||||
|
if ("${AFL_FUZZ}" MATCHES "AFL_FUZZ-NOTFOUND")
|
||||||
|
message(FATAL_ERROR "Couldn't find afl-fuzz.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(afl-main afl.c)
|
||||||
|
target_link_libraries(afl-main "${CJSON_LIB}")
|
||||||
|
|
||||||
|
if (NOT ENABLE_SANITIZERS)
|
||||||
|
message(FATAL_ERROR "Enable sanitizers with -DENABLE_SANITIZERS=On to do fuzzing.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(ENABLE_FUZZING_PRINT "Fuzz printing functions together with parser." On)
|
||||||
|
set(fuzz_print_parameter "no")
|
||||||
|
if (ENABLE_FUZZING_PRINT)
|
||||||
|
set(fuzz_print_parameter "yes")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error")
|
||||||
|
|
||||||
|
add_custom_target(afl
|
||||||
|
COMMAND "${AFL_FUZZ}" -i "${CMAKE_CURRENT_SOURCE_DIR}/inputs" -o "${CMAKE_CURRENT_BINARY_DIR}/findings" -x "${CMAKE_CURRENT_SOURCE_DIR}/json.dict" -- "${CMAKE_CURRENT_BINARY_DIR}/afl-main" "@@" "${fuzz_print_parameter}"
|
||||||
|
DEPENDS afl-main)
|
||||||
|
|
||||||
|
|
||||||
|
endif()
|
||||||
5
fuzzing/afl-prepare-linux.sh
Executable file
5
fuzzing/afl-prepare-linux.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -x
|
||||||
|
echo core | sudo tee /proc/sys/kernel/core_pattern
|
||||||
|
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
|
||||||
176
fuzzing/afl.c
Normal file
176
fuzzing/afl.c
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../cJSON.h"
|
||||||
|
|
||||||
|
static char *read_file(const char *filename)
|
||||||
|
{
|
||||||
|
FILE *file = NULL;
|
||||||
|
long length = 0;
|
||||||
|
char *content = NULL;
|
||||||
|
size_t read_chars = 0;
|
||||||
|
|
||||||
|
/* open in read binary mode */
|
||||||
|
file = fopen(filename, "rb");
|
||||||
|
if (file == NULL)
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the length */
|
||||||
|
if (fseek(file, 0, SEEK_END) != 0)
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
length = ftell(file);
|
||||||
|
if (length < 0)
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (fseek(file, 0, SEEK_SET) != 0)
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate content buffer */
|
||||||
|
content = (char*)malloc((size_t)length + sizeof('\0'));
|
||||||
|
if (content == NULL)
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read the file into memory */
|
||||||
|
read_chars = fread(content, sizeof(char), (size_t)length, file);
|
||||||
|
if ((long)read_chars != length)
|
||||||
|
{
|
||||||
|
free(content);
|
||||||
|
content = NULL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
content[read_chars] = '\0';
|
||||||
|
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (file != NULL)
|
||||||
|
{
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
const char *filename = NULL;
|
||||||
|
cJSON *item = NULL;
|
||||||
|
char *json = NULL;
|
||||||
|
int status = EXIT_FAILURE;
|
||||||
|
char *printed_json = NULL;
|
||||||
|
|
||||||
|
if ((argc < 2) || (argc > 3))
|
||||||
|
{
|
||||||
|
printf("Usage:\n");
|
||||||
|
printf("%s input_file [enable_printing]\n", argv[0]);
|
||||||
|
printf("\t input_file: file containing the test data\n");
|
||||||
|
printf("\t enable_printing: print after parsing, 'yes' or 'no', defaults to 'no'\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = argv[1];
|
||||||
|
|
||||||
|
#if __AFL_HAVE_MANUAL_CONTROL
|
||||||
|
while (__AFL_LOOP(1000))
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
status = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
json = read_file(filename);
|
||||||
|
if ((json == NULL) || (json[0] == '\0') || (json[1] == '\0'))
|
||||||
|
{
|
||||||
|
status = EXIT_FAILURE;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
item = cJSON_Parse(json + 2);
|
||||||
|
if (item == NULL)
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((argc == 3) && (strncmp(argv[2], "yes", 3) == 0))
|
||||||
|
{
|
||||||
|
int do_format = 0;
|
||||||
|
if (json[1] == 'f')
|
||||||
|
{
|
||||||
|
do_format = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json[0] == 'b')
|
||||||
|
{
|
||||||
|
/* buffered printing */
|
||||||
|
printed_json = cJSON_PrintBuffered(item, 1, do_format);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* unbuffered printing */
|
||||||
|
if (do_format)
|
||||||
|
{
|
||||||
|
printed_json = cJSON_Print(item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printed_json = cJSON_PrintUnformatted(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (printed_json == NULL)
|
||||||
|
{
|
||||||
|
status = EXIT_FAILURE;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
printf("%s\n", printed_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (item != NULL)
|
||||||
|
{
|
||||||
|
cJSON_Delete(item);
|
||||||
|
item = NULL;
|
||||||
|
}
|
||||||
|
if (json != NULL)
|
||||||
|
{
|
||||||
|
free(json);
|
||||||
|
json = NULL;
|
||||||
|
}
|
||||||
|
if (printed_json != NULL)
|
||||||
|
{
|
||||||
|
free(printed_json);
|
||||||
|
printed_json = NULL;
|
||||||
|
}
|
||||||
|
#if __AFL_HAVE_MANUAL_CONTROL
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
9
fuzzing/afl.sh
Executable file
9
fuzzing/afl.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
mkdir -p afl-build || exit 1
|
||||||
|
cd afl-build || exit 1
|
||||||
|
#cleanup
|
||||||
|
rm -r -- *
|
||||||
|
|
||||||
|
CC=afl-clang-fast cmake ../.. -DENABLE_FUZZING=On -DENABLE_SANITIZERS=On -DBUILD_SHARED_LIBS=Off
|
||||||
|
make afl
|
||||||
22
fuzzing/inputs/test1
Normal file
22
fuzzing/inputs/test1
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
bf{
|
||||||
|
"glossary": {
|
||||||
|
"title": "example glossary",
|
||||||
|
"GlossDiv": {
|
||||||
|
"title": "S",
|
||||||
|
"GlossList": {
|
||||||
|
"GlossEntry": {
|
||||||
|
"ID": "SGML",
|
||||||
|
"SortAs": "SGML",
|
||||||
|
"GlossTerm": "Standard Generalized Markup Language",
|
||||||
|
"Acronym": "SGML",
|
||||||
|
"Abbrev": "ISO 8879:1986",
|
||||||
|
"GlossDef": {
|
||||||
|
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
||||||
|
"GlossSeeAlso": ["GML", "XML"]
|
||||||
|
},
|
||||||
|
"GlossSee": "markup"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
fuzzing/inputs/test10
Normal file
1
fuzzing/inputs/test10
Normal file
@@ -0,0 +1 @@
|
|||||||
|
bf["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
|
||||||
8
fuzzing/inputs/test11
Normal file
8
fuzzing/inputs/test11
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
bf{
|
||||||
|
"name": "Jack (\"Bee\") Nimble",
|
||||||
|
"format": {"type": "rect",
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1080,
|
||||||
|
"interlace": false,"frame rate": 24
|
||||||
|
}
|
||||||
|
}
|
||||||
11
fuzzing/inputs/test2
Normal file
11
fuzzing/inputs/test2
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
bf{"menu": {
|
||||||
|
"id": "file",
|
||||||
|
"value": "File",
|
||||||
|
"popup": {
|
||||||
|
"menuitem": [
|
||||||
|
{"value": "New", "onclick": "CreateNewDoc()"},
|
||||||
|
{"value": "Open", "onclick": "OpenDoc()"},
|
||||||
|
{"value": "Close", "onclick": "CloseDoc()"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}}
|
||||||
26
fuzzing/inputs/test3
Normal file
26
fuzzing/inputs/test3
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
bf{"widget": {
|
||||||
|
"debug": "on",
|
||||||
|
"window": {
|
||||||
|
"title": "Sample Konfabulator Widget",
|
||||||
|
"name": "main_window",
|
||||||
|
"width": 500,
|
||||||
|
"height": 500
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"src": "Images/Sun.png",
|
||||||
|
"name": "sun1",
|
||||||
|
"hOffset": 250,
|
||||||
|
"vOffset": 250,
|
||||||
|
"alignment": "center"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"data": "Click Here",
|
||||||
|
"size": 36,
|
||||||
|
"style": "bold",
|
||||||
|
"name": "text1",
|
||||||
|
"hOffset": 250,
|
||||||
|
"vOffset": 100,
|
||||||
|
"alignment": "center",
|
||||||
|
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
|
||||||
|
}
|
||||||
|
}}
|
||||||
26
fuzzing/inputs/test3.bu
Normal file
26
fuzzing/inputs/test3.bu
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
bu{"widget": {
|
||||||
|
"debug": "on",
|
||||||
|
"window": {
|
||||||
|
"title": "Sample Konfabulator Widget",
|
||||||
|
"name": "main_window",
|
||||||
|
"width": 500,
|
||||||
|
"height": 500
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"src": "Images/Sun.png",
|
||||||
|
"name": "sun1",
|
||||||
|
"hOffset": 250,
|
||||||
|
"vOffset": 250,
|
||||||
|
"alignment": "center"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"data": "Click Here",
|
||||||
|
"size": 36,
|
||||||
|
"style": "bold",
|
||||||
|
"name": "text1",
|
||||||
|
"hOffset": 250,
|
||||||
|
"vOffset": 100,
|
||||||
|
"alignment": "center",
|
||||||
|
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
|
||||||
|
}
|
||||||
|
}}
|
||||||
26
fuzzing/inputs/test3.uf
Normal file
26
fuzzing/inputs/test3.uf
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
uf{"widget": {
|
||||||
|
"debug": "on",
|
||||||
|
"window": {
|
||||||
|
"title": "Sample Konfabulator Widget",
|
||||||
|
"name": "main_window",
|
||||||
|
"width": 500,
|
||||||
|
"height": 500
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"src": "Images/Sun.png",
|
||||||
|
"name": "sun1",
|
||||||
|
"hOffset": 250,
|
||||||
|
"vOffset": 250,
|
||||||
|
"alignment": "center"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"data": "Click Here",
|
||||||
|
"size": 36,
|
||||||
|
"style": "bold",
|
||||||
|
"name": "text1",
|
||||||
|
"hOffset": 250,
|
||||||
|
"vOffset": 100,
|
||||||
|
"alignment": "center",
|
||||||
|
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
|
||||||
|
}
|
||||||
|
}}
|
||||||
26
fuzzing/inputs/test3.uu
Normal file
26
fuzzing/inputs/test3.uu
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
uu{"widget": {
|
||||||
|
"debug": "on",
|
||||||
|
"window": {
|
||||||
|
"title": "Sample Konfabulator Widget",
|
||||||
|
"name": "main_window",
|
||||||
|
"width": 500,
|
||||||
|
"height": 500
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"src": "Images/Sun.png",
|
||||||
|
"name": "sun1",
|
||||||
|
"hOffset": 250,
|
||||||
|
"vOffset": 250,
|
||||||
|
"alignment": "center"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"data": "Click Here",
|
||||||
|
"size": 36,
|
||||||
|
"style": "bold",
|
||||||
|
"name": "text1",
|
||||||
|
"hOffset": 250,
|
||||||
|
"vOffset": 100,
|
||||||
|
"alignment": "center",
|
||||||
|
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
|
||||||
|
}
|
||||||
|
}}
|
||||||
88
fuzzing/inputs/test4
Normal file
88
fuzzing/inputs/test4
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
bf{"web-app": {
|
||||||
|
"servlet": [
|
||||||
|
{
|
||||||
|
"servlet-name": "cofaxCDS",
|
||||||
|
"servlet-class": "org.cofax.cds.CDSServlet",
|
||||||
|
"init-param": {
|
||||||
|
"configGlossary:installationAt": "Philadelphia, PA",
|
||||||
|
"configGlossary:adminEmail": "ksm@pobox.com",
|
||||||
|
"configGlossary:poweredBy": "Cofax",
|
||||||
|
"configGlossary:poweredByIcon": "/images/cofax.gif",
|
||||||
|
"configGlossary:staticPath": "/content/static",
|
||||||
|
"templateProcessorClass": "org.cofax.WysiwygTemplate",
|
||||||
|
"templateLoaderClass": "org.cofax.FilesTemplateLoader",
|
||||||
|
"templatePath": "templates",
|
||||||
|
"templateOverridePath": "",
|
||||||
|
"defaultListTemplate": "listTemplate.htm",
|
||||||
|
"defaultFileTemplate": "articleTemplate.htm",
|
||||||
|
"useJSP": false,
|
||||||
|
"jspListTemplate": "listTemplate.jsp",
|
||||||
|
"jspFileTemplate": "articleTemplate.jsp",
|
||||||
|
"cachePackageTagsTrack": 200,
|
||||||
|
"cachePackageTagsStore": 200,
|
||||||
|
"cachePackageTagsRefresh": 60,
|
||||||
|
"cacheTemplatesTrack": 100,
|
||||||
|
"cacheTemplatesStore": 50,
|
||||||
|
"cacheTemplatesRefresh": 15,
|
||||||
|
"cachePagesTrack": 200,
|
||||||
|
"cachePagesStore": 100,
|
||||||
|
"cachePagesRefresh": 10,
|
||||||
|
"cachePagesDirtyRead": 10,
|
||||||
|
"searchEngineListTemplate": "forSearchEnginesList.htm",
|
||||||
|
"searchEngineFileTemplate": "forSearchEngines.htm",
|
||||||
|
"searchEngineRobotsDb": "WEB-INF/robots.db",
|
||||||
|
"useDataStore": true,
|
||||||
|
"dataStoreClass": "org.cofax.SqlDataStore",
|
||||||
|
"redirectionClass": "org.cofax.SqlRedirection",
|
||||||
|
"dataStoreName": "cofax",
|
||||||
|
"dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
|
||||||
|
"dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
|
||||||
|
"dataStoreUser": "sa",
|
||||||
|
"dataStorePassword": "dataStoreTestQuery",
|
||||||
|
"dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
|
||||||
|
"dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
|
||||||
|
"dataStoreInitConns": 10,
|
||||||
|
"dataStoreMaxConns": 100,
|
||||||
|
"dataStoreConnUsageLimit": 100,
|
||||||
|
"dataStoreLogLevel": "debug",
|
||||||
|
"maxUrlLength": 500}},
|
||||||
|
{
|
||||||
|
"servlet-name": "cofaxEmail",
|
||||||
|
"servlet-class": "org.cofax.cds.EmailServlet",
|
||||||
|
"init-param": {
|
||||||
|
"mailHost": "mail1",
|
||||||
|
"mailHostOverride": "mail2"}},
|
||||||
|
{
|
||||||
|
"servlet-name": "cofaxAdmin",
|
||||||
|
"servlet-class": "org.cofax.cds.AdminServlet"},
|
||||||
|
|
||||||
|
{
|
||||||
|
"servlet-name": "fileServlet",
|
||||||
|
"servlet-class": "org.cofax.cds.FileServlet"},
|
||||||
|
{
|
||||||
|
"servlet-name": "cofaxTools",
|
||||||
|
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
|
||||||
|
"init-param": {
|
||||||
|
"templatePath": "toolstemplates/",
|
||||||
|
"log": 1,
|
||||||
|
"logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
|
||||||
|
"logMaxSize": "",
|
||||||
|
"dataLog": 1,
|
||||||
|
"dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
|
||||||
|
"dataLogMaxSize": "",
|
||||||
|
"removePageCache": "/content/admin/remove?cache=pages&id=",
|
||||||
|
"removeTemplateCache": "/content/admin/remove?cache=templates&id=",
|
||||||
|
"fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
|
||||||
|
"lookInContext": 1,
|
||||||
|
"adminGroupID": 4,
|
||||||
|
"betaServer": true}}],
|
||||||
|
"servlet-mapping": {
|
||||||
|
"cofaxCDS": "/",
|
||||||
|
"cofaxEmail": "/cofaxutil/aemail/*",
|
||||||
|
"cofaxAdmin": "/admin/*",
|
||||||
|
"fileServlet": "/static/*",
|
||||||
|
"cofaxTools": "/tools/*"},
|
||||||
|
|
||||||
|
"taglib": {
|
||||||
|
"taglib-uri": "cofax.tld",
|
||||||
|
"taglib-location": "/WEB-INF/tlds/cofax.tld"}}}
|
||||||
27
fuzzing/inputs/test5
Normal file
27
fuzzing/inputs/test5
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
bf{"menu": {
|
||||||
|
"header": "SVG Viewer",
|
||||||
|
"items": [
|
||||||
|
{"id": "Open"},
|
||||||
|
{"id": "OpenNew", "label": "Open New"},
|
||||||
|
null,
|
||||||
|
{"id": "ZoomIn", "label": "Zoom In"},
|
||||||
|
{"id": "ZoomOut", "label": "Zoom Out"},
|
||||||
|
{"id": "OriginalView", "label": "Original View"},
|
||||||
|
null,
|
||||||
|
{"id": "Quality"},
|
||||||
|
{"id": "Pause"},
|
||||||
|
{"id": "Mute"},
|
||||||
|
null,
|
||||||
|
{"id": "Find", "label": "Find..."},
|
||||||
|
{"id": "FindAgain", "label": "Find Again"},
|
||||||
|
{"id": "Copy"},
|
||||||
|
{"id": "CopyAgain", "label": "Copy Again"},
|
||||||
|
{"id": "CopySVG", "label": "Copy SVG"},
|
||||||
|
{"id": "ViewSVG", "label": "View SVG"},
|
||||||
|
{"id": "ViewSource", "label": "View Source"},
|
||||||
|
{"id": "SaveAs", "label": "Save As"},
|
||||||
|
null,
|
||||||
|
{"id": "Help"},
|
||||||
|
{"id": "About", "label": "About Adobe CVG Viewer..."}
|
||||||
|
]
|
||||||
|
}}
|
||||||
16
fuzzing/inputs/test6
Normal file
16
fuzzing/inputs/test6
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
bf<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style type="text/css">
|
||||||
|
html, body, iframe { margin: 0; padding: 0; height: 100%; }
|
||||||
|
iframe { display: block; width: 100%; border: none; }
|
||||||
|
</style>
|
||||||
|
<title>Application Error</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe src="//s3.amazonaws.com/heroku_pages/error.html">
|
||||||
|
<p>Application Error</p>
|
||||||
|
</iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
22
fuzzing/inputs/test7
Normal file
22
fuzzing/inputs/test7
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
bf[
|
||||||
|
{
|
||||||
|
"precision": "zip",
|
||||||
|
"Latitude": 37.7668,
|
||||||
|
"Longitude": -122.3959,
|
||||||
|
"Address": "",
|
||||||
|
"City": "SAN FRANCISCO",
|
||||||
|
"State": "CA",
|
||||||
|
"Zip": "94107",
|
||||||
|
"Country": "US"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"precision": "zip",
|
||||||
|
"Latitude": 37.371991,
|
||||||
|
"Longitude": -122.026020,
|
||||||
|
"Address": "",
|
||||||
|
"City": "SUNNYVALE",
|
||||||
|
"State": "CA",
|
||||||
|
"Zip": "94085",
|
||||||
|
"Country": "US"
|
||||||
|
}
|
||||||
|
]
|
||||||
13
fuzzing/inputs/test8
Normal file
13
fuzzing/inputs/test8
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
bf{
|
||||||
|
"Image": {
|
||||||
|
"Width": 800,
|
||||||
|
"Height": 600,
|
||||||
|
"Title": "View from 15th Floor",
|
||||||
|
"Thumbnail": {
|
||||||
|
"Url": "http:/*www.example.com/image/481989943",
|
||||||
|
"Height": 125,
|
||||||
|
"Width": "100"
|
||||||
|
},
|
||||||
|
"IDs": [116, 943, 234, 38793]
|
||||||
|
}
|
||||||
|
}
|
||||||
5
fuzzing/inputs/test9
Normal file
5
fuzzing/inputs/test9
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
bf[
|
||||||
|
[0, -1, 0],
|
||||||
|
[1, 0, 0],
|
||||||
|
[0, 0, 1]
|
||||||
|
]
|
||||||
47
fuzzing/json.dict
Normal file
47
fuzzing/json.dict
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#
|
||||||
|
# AFL dictionary for JSON
|
||||||
|
# -----------------------------
|
||||||
|
#
|
||||||
|
|
||||||
|
object_start="{"
|
||||||
|
object_end="}"
|
||||||
|
object_empty="{}"
|
||||||
|
object_one_element="{\"one\":1}"
|
||||||
|
object_two_elements="{\"1\":1,\"2\":2}"
|
||||||
|
object_separator=":"
|
||||||
|
|
||||||
|
array_start="["
|
||||||
|
array_end="]"
|
||||||
|
array_empty="[]"
|
||||||
|
array_one_element="[1]"
|
||||||
|
array_two_elements="[1,2]"
|
||||||
|
|
||||||
|
separator=","
|
||||||
|
|
||||||
|
escape_sequence_b="\\b"
|
||||||
|
escape_sequence_f="\\f"
|
||||||
|
escape_sequence_n="\\n"
|
||||||
|
escape_sequence_r="\\r"
|
||||||
|
escape_sequence_t="\\t"
|
||||||
|
escape_sequence_quote="\\\""
|
||||||
|
escape_sequence_backslash="\\\\"
|
||||||
|
escapce_sequence_slash="\\/"
|
||||||
|
escpae_sequence_utf16_base="\\u"
|
||||||
|
escape_sequence_utf16="\\u12ab"
|
||||||
|
|
||||||
|
number_integer="1"
|
||||||
|
number_double="1.0"
|
||||||
|
number_negative_integer="-1"
|
||||||
|
number_negative_double="-1.0"
|
||||||
|
number_engineering1="1e1"
|
||||||
|
number_engineering2="1e-1"
|
||||||
|
number_positive_integer="+1"
|
||||||
|
number_positive_double="+1.0"
|
||||||
|
number_e="e"
|
||||||
|
number_plus="+"
|
||||||
|
number_minus="-"
|
||||||
|
number_separator="."
|
||||||
|
|
||||||
|
null="null"
|
||||||
|
true="true"
|
||||||
|
false="false"
|
||||||
@@ -1,6 +1,17 @@
|
|||||||
if(ENABLE_CJSON_TEST)
|
if(ENABLE_CJSON_TEST)
|
||||||
add_library(unity unity/src/unity.c)
|
add_library(unity unity/src/unity.c)
|
||||||
|
|
||||||
|
# Disable -Werror for Unity
|
||||||
|
list(FIND custom_compiler_flags "-Werror" werror_found)
|
||||||
|
if (werror_found)
|
||||||
|
target_compile_options(unity PRIVATE "-Wno-error")
|
||||||
|
endif()
|
||||||
|
# Disable -fvisibility=hidden for Unity
|
||||||
|
list(FIND custom_compiler_flags "-fvisibility=hidden" visibility_found)
|
||||||
|
if (visibility_found)
|
||||||
|
target_compile_options(unity PRIVATE "-fvisibility=default")
|
||||||
|
endif()
|
||||||
|
|
||||||
#copy test files
|
#copy test files
|
||||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/inputs")
|
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/inputs")
|
||||||
file(GLOB test_files "inputs/*")
|
file(GLOB test_files "inputs/*")
|
||||||
@@ -14,6 +25,12 @@ if(ENABLE_CJSON_TEST)
|
|||||||
parse_array
|
parse_array
|
||||||
parse_object
|
parse_object
|
||||||
parse_value
|
parse_value
|
||||||
|
print_string
|
||||||
|
print_number
|
||||||
|
print_array
|
||||||
|
print_object
|
||||||
|
print_value
|
||||||
|
misc_tests
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(test-common common.c)
|
add_library(test-common common.c)
|
||||||
@@ -29,6 +46,11 @@ if(ENABLE_CJSON_TEST)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
#"check" target that automatically builds everything and runs the tests
|
||||||
|
add_custom_target(check
|
||||||
|
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
|
||||||
|
DEPENDS ${unity_tests})
|
||||||
|
|
||||||
foreach(unity_test ${unity_tests})
|
foreach(unity_test ${unity_tests})
|
||||||
add_executable("${unity_test}" "${unity_test}.c")
|
add_executable("${unity_test}" "${unity_test}.c")
|
||||||
target_link_libraries("${unity_test}" "${CJSON_LIB}" unity test-common)
|
target_link_libraries("${unity_test}" "${CJSON_LIB}" unity test-common)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
extern void reset(cJSON *item)
|
CJSON_PUBLIC(void) reset(cJSON *item)
|
||||||
{
|
{
|
||||||
if ((item != NULL) && (item->child != NULL))
|
if ((item != NULL) && (item->child != NULL))
|
||||||
{
|
{
|
||||||
@@ -30,17 +30,17 @@ extern void reset(cJSON *item)
|
|||||||
}
|
}
|
||||||
if ((item->valuestring != NULL) && !(item->type & cJSON_IsReference))
|
if ((item->valuestring != NULL) && !(item->type & cJSON_IsReference))
|
||||||
{
|
{
|
||||||
cJSON_free(item->valuestring);
|
global_hooks.deallocate(item->valuestring);
|
||||||
}
|
}
|
||||||
if ((item->string != NULL) && !(item->type & cJSON_StringIsConst))
|
if ((item->string != NULL) && !(item->type & cJSON_StringIsConst))
|
||||||
{
|
{
|
||||||
cJSON_free(item->string);
|
global_hooks.deallocate(item->string);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(item, 0, sizeof(cJSON));
|
memset(item, 0, sizeof(cJSON));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern char *read_file(const char *filename)
|
CJSON_PUBLIC(char*) read_file(const char *filename)
|
||||||
{
|
{
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
long length = 0;
|
long length = 0;
|
||||||
|
|||||||
@@ -25,9 +25,8 @@
|
|||||||
|
|
||||||
#include "../cJSON.c"
|
#include "../cJSON.c"
|
||||||
|
|
||||||
extern void reset(cJSON *item);
|
CJSON_PUBLIC(void) reset(cJSON *item);
|
||||||
extern char *read_file(const char *filename);
|
CJSON_PUBLIC(char*) read_file(const char *filename);
|
||||||
extern cjbool assert_is_invalid(cJSON *item);
|
|
||||||
|
|
||||||
/* assertion helper macros */
|
/* assertion helper macros */
|
||||||
#define assert_has_type(item, item_type) TEST_ASSERT_BITS_MESSAGE(0xFF, item_type, item->type, "Item doesn't have expected type.")
|
#define assert_has_type(item, item_type) TEST_ASSERT_BITS_MESSAGE(0xFF, item_type, item->type, "Item doesn't have expected type.")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[{
|
[{
|
||||||
"precision": "zip",
|
"precision": "zip",
|
||||||
"Latitude": 37.766800,
|
"Latitude": 37.7668,
|
||||||
"Longitude": -122.395900,
|
"Longitude": -122.3959,
|
||||||
"Address": "",
|
"Address": "",
|
||||||
"City": "SAN FRANCISCO",
|
"City": "SAN FRANCISCO",
|
||||||
"State": "CA",
|
"State": "CA",
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
}, {
|
}, {
|
||||||
"precision": "zip",
|
"precision": "zip",
|
||||||
"Latitude": 37.371991,
|
"Latitude": 37.371991,
|
||||||
"Longitude": -122.026020,
|
"Longitude": -122.02602,
|
||||||
"Address": "",
|
"Address": "",
|
||||||
"City": "SUNNYVALE",
|
"City": "SUNNYVALE",
|
||||||
"State": "CA",
|
"State": "CA",
|
||||||
|
|||||||
197
tests/misc_tests.c
Normal file
197
tests/misc_tests.c
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "unity/examples/unity_config.h"
|
||||||
|
#include "unity/src/unity.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void cjson_array_foreach_should_loop_over_arrays(void)
|
||||||
|
{
|
||||||
|
cJSON array[1];
|
||||||
|
cJSON elements[10];
|
||||||
|
cJSON *element_pointer = NULL;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
memset(array, 0, sizeof(array));
|
||||||
|
memset(elements, 0, sizeof(elements));
|
||||||
|
|
||||||
|
/* create array */
|
||||||
|
array[0].child = &elements[0];
|
||||||
|
elements[0].prev = NULL;
|
||||||
|
elements[9].next = NULL;
|
||||||
|
for (i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
elements[i].next = &elements[i + 1];
|
||||||
|
elements[i + 1].prev = &elements[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
cJSON_ArrayForEach(element_pointer, array)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(element_pointer == &elements[i], "Not iterating over array properly");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cjson_array_foreach_should_not_dereference_null_pointer(void)
|
||||||
|
{
|
||||||
|
cJSON *array = NULL;
|
||||||
|
cJSON *element = NULL;
|
||||||
|
cJSON_ArrayForEach(element, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cjson_get_object_item_should_get_object_items(void)
|
||||||
|
{
|
||||||
|
cJSON *item = NULL;
|
||||||
|
cJSON *found = NULL;
|
||||||
|
|
||||||
|
item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}");
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItem(NULL, "test");
|
||||||
|
TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer.");
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItem(item, NULL);
|
||||||
|
TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
|
||||||
|
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItem(item, "one");
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
|
||||||
|
TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItem(item, "tWo");
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
|
||||||
|
TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2);
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItem(item, "three");
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item.");
|
||||||
|
TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3);
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItem(item, "four");
|
||||||
|
TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there.");
|
||||||
|
|
||||||
|
cJSON_Delete(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
|
||||||
|
{
|
||||||
|
cJSON *item = NULL;
|
||||||
|
cJSON *found = NULL;
|
||||||
|
|
||||||
|
item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}");
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItemCaseSensitive(NULL, "test");
|
||||||
|
TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer.");
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItemCaseSensitive(item, NULL);
|
||||||
|
TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItemCaseSensitive(item, "one");
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
|
||||||
|
TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItemCaseSensitive(item, "Two");
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
|
||||||
|
TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2);
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItemCaseSensitive(item, "tHree");
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item.");
|
||||||
|
TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3);
|
||||||
|
|
||||||
|
found = cJSON_GetObjectItemCaseSensitive(item, "One");
|
||||||
|
TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there.");
|
||||||
|
|
||||||
|
cJSON_Delete(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void typecheck_functions_should_check_type(void)
|
||||||
|
{
|
||||||
|
cJSON invalid[1];
|
||||||
|
cJSON item[1];
|
||||||
|
invalid->type = cJSON_Invalid;
|
||||||
|
invalid->type |= cJSON_StringIsConst;
|
||||||
|
item->type = cJSON_False;
|
||||||
|
item->type |= cJSON_StringIsConst;
|
||||||
|
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsInvalid(item));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsInvalid(invalid));
|
||||||
|
|
||||||
|
item->type = cJSON_False | cJSON_StringIsConst;
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsFalse(NULL));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsFalse(invalid));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsFalse(item));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsBool(item));
|
||||||
|
|
||||||
|
item->type = cJSON_True | cJSON_StringIsConst;
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsTrue(NULL));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsTrue(invalid));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsTrue(item));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsBool(item));
|
||||||
|
|
||||||
|
item->type = cJSON_NULL | cJSON_StringIsConst;
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsNull(NULL));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsNull(invalid));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsNull(item));
|
||||||
|
|
||||||
|
item->type = cJSON_Number | cJSON_StringIsConst;
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsNumber(NULL));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsNumber(invalid));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsNumber(item));
|
||||||
|
|
||||||
|
item->type = cJSON_String | cJSON_StringIsConst;
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsString(NULL));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsString(invalid));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsString(item));
|
||||||
|
|
||||||
|
item->type = cJSON_Array | cJSON_StringIsConst;
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsArray(NULL));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsArray(invalid));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsArray(item));
|
||||||
|
|
||||||
|
item->type = cJSON_Object | cJSON_StringIsConst;
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsObject(invalid));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsObject(item));
|
||||||
|
|
||||||
|
item->type = cJSON_Raw | cJSON_StringIsConst;
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsRaw(invalid));
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsRaw(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(cjson_array_foreach_should_loop_over_arrays);
|
||||||
|
RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer);
|
||||||
|
RUN_TEST(cjson_get_object_item_should_get_object_items);
|
||||||
|
RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items);
|
||||||
|
RUN_TEST(typecheck_functions_should_check_type);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
@@ -46,13 +46,13 @@ static void assert_is_array(cJSON *array_item)
|
|||||||
|
|
||||||
static void assert_not_array(const char *json)
|
static void assert_not_array(const char *json)
|
||||||
{
|
{
|
||||||
TEST_ASSERT_NULL(parse_array(item, (const unsigned char*)json, &error_pointer));
|
TEST_ASSERT_NULL(parse_array(item, (const unsigned char*)json, &error_pointer, &global_hooks));
|
||||||
assert_is_invalid(item);
|
assert_is_invalid(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assert_parse_array(const char *json)
|
static void assert_parse_array(const char *json)
|
||||||
{
|
{
|
||||||
TEST_ASSERT_NOT_NULL(parse_array(item, (const unsigned char*)json, &error_pointer));
|
TEST_ASSERT_NOT_NULL(parse_array(item, (const unsigned char*)json, &error_pointer, &global_hooks));
|
||||||
assert_is_array(item);
|
assert_is_array(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ static void parse_array_should_parse_arrays_with_multiple_elements(void)
|
|||||||
i = 0;
|
i = 0;
|
||||||
(i < (sizeof(expected_types)/sizeof(int)))
|
(i < (sizeof(expected_types)/sizeof(int)))
|
||||||
&& (node != NULL);
|
&& (node != NULL);
|
||||||
i++, node = node->next)
|
(void)i++, node = node->next)
|
||||||
{
|
{
|
||||||
TEST_ASSERT_BITS(0xFF, expected_types[i], node->type);
|
TEST_ASSERT_BITS(0xFF, expected_types[i], node->type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,14 +54,14 @@ static void assert_is_child(cJSON *child_item, const char *name, int type)
|
|||||||
|
|
||||||
static void assert_not_object(const char *json)
|
static void assert_not_object(const char *json)
|
||||||
{
|
{
|
||||||
TEST_ASSERT_NULL(parse_object(item, (const unsigned char*)json, &error_pointer));
|
TEST_ASSERT_NULL(parse_object(item, (const unsigned char*)json, &error_pointer, &global_hooks));
|
||||||
assert_is_invalid(item);
|
assert_is_invalid(item);
|
||||||
reset(item);
|
reset(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assert_parse_object(const char *json)
|
static void assert_parse_object(const char *json)
|
||||||
{
|
{
|
||||||
TEST_ASSERT_NOT_NULL(parse_object(item, (const unsigned char*)json, &error_pointer));
|
TEST_ASSERT_NOT_NULL(parse_object(item, (const unsigned char*)json, &error_pointer, &global_hooks));
|
||||||
assert_is_object(item);
|
assert_is_object(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ static void parse_object_should_parse_empty_objects(void)
|
|||||||
reset(item);
|
reset(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_array_should_parse_arrays_with_one_element(void)
|
static void parse_object_should_parse_objects_with_one_element(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert_parse_object("{\"one\":1}");
|
assert_parse_object("{\"one\":1}");
|
||||||
@@ -134,7 +134,7 @@ static void parse_object_should_parse_objects_with_multiple_elements(void)
|
|||||||
i = 0;
|
i = 0;
|
||||||
(i < (sizeof(expected_types)/sizeof(int)))
|
(i < (sizeof(expected_types)/sizeof(int)))
|
||||||
&& (node != NULL);
|
&& (node != NULL);
|
||||||
i++, node = node->next)
|
(void)i++, node = node->next)
|
||||||
{
|
{
|
||||||
assert_is_child(node, expected_names[i], expected_types[i]);
|
assert_is_child(node, expected_names[i], expected_types[i]);
|
||||||
}
|
}
|
||||||
@@ -163,6 +163,6 @@ int main(void)
|
|||||||
RUN_TEST(parse_object_should_parse_empty_objects);
|
RUN_TEST(parse_object_should_parse_empty_objects);
|
||||||
RUN_TEST(parse_object_should_not_parse_non_objects);
|
RUN_TEST(parse_object_should_not_parse_non_objects);
|
||||||
RUN_TEST(parse_object_should_parse_objects_with_multiple_elements);
|
RUN_TEST(parse_object_should_parse_objects_with_multiple_elements);
|
||||||
RUN_TEST(parse_array_should_parse_arrays_with_one_element);
|
RUN_TEST(parse_object_should_parse_objects_with_one_element);
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,15 +47,15 @@ static void assert_is_string(cJSON *string_item)
|
|||||||
|
|
||||||
static void assert_parse_string(const char *string, const char *expected)
|
static void assert_parse_string(const char *string, const char *expected)
|
||||||
{
|
{
|
||||||
TEST_ASSERT_NOT_NULL_MESSAGE(parse_string(item, (const unsigned char*)string, &error_pointer), "Couldn't parse string.");
|
TEST_ASSERT_NOT_NULL_MESSAGE(parse_string(item, (const unsigned char*)string, &error_pointer, &global_hooks), "Couldn't parse string.");
|
||||||
assert_is_string(item);
|
assert_is_string(item);
|
||||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, item->valuestring, "The parsed result isn't as expected.");
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, item->valuestring, "The parsed result isn't as expected.");
|
||||||
cJSON_free(item->valuestring);
|
global_hooks.deallocate(item->valuestring);
|
||||||
item->valuestring = NULL;
|
item->valuestring = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define assert_not_parse_string(string) \
|
#define assert_not_parse_string(string) \
|
||||||
TEST_ASSERT_NULL_MESSAGE(parse_string(item, (const unsigned char*)string, &error_pointer), "Malformed string should not be accepted");\
|
TEST_ASSERT_NULL_MESSAGE(parse_string(item, (const unsigned char*)string, &error_pointer, &global_hooks), "Malformed string should not be accepted");\
|
||||||
assert_is_invalid(item)
|
assert_is_invalid(item)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ static void assert_is_value(cJSON *value_item, int type)
|
|||||||
|
|
||||||
static void assert_parse_value(const char *string, int type)
|
static void assert_parse_value(const char *string, int type)
|
||||||
{
|
{
|
||||||
TEST_ASSERT_NOT_NULL(parse_value(item, (const unsigned char*)string, &error_pointer));
|
TEST_ASSERT_NOT_NULL(parse_value(item, (const unsigned char*)string, &error_pointer, &global_hooks));
|
||||||
assert_is_value(item, type);
|
assert_is_value(item, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
92
tests/print_array.c
Normal file
92
tests/print_array.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "unity/examples/unity_config.h"
|
||||||
|
#include "unity/src/unity.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
static void assert_print_array(const char * const expected, const char * const input)
|
||||||
|
{
|
||||||
|
unsigned char printed_unformatted[1024];
|
||||||
|
unsigned char printed_formatted[1024];
|
||||||
|
|
||||||
|
const unsigned char *error_pointer;
|
||||||
|
cJSON item[1];
|
||||||
|
|
||||||
|
printbuffer formatted_buffer;
|
||||||
|
printbuffer unformatted_buffer;
|
||||||
|
|
||||||
|
/* buffer for formatted printing */
|
||||||
|
formatted_buffer.buffer = printed_formatted;
|
||||||
|
formatted_buffer.length = sizeof(printed_formatted);
|
||||||
|
formatted_buffer.offset = 0;
|
||||||
|
formatted_buffer.noalloc = true;
|
||||||
|
|
||||||
|
/* buffer for unformatted printing */
|
||||||
|
unformatted_buffer.buffer = printed_unformatted;
|
||||||
|
unformatted_buffer.length = sizeof(printed_unformatted);
|
||||||
|
unformatted_buffer.offset = 0;
|
||||||
|
unformatted_buffer.noalloc = true;
|
||||||
|
|
||||||
|
memset(item, 0, sizeof(item));
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(parse_array(item, (const unsigned char*)input, &error_pointer, &global_hooks), "Failed to parse array.");
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(print_array(item, 0, false, &unformatted_buffer, &global_hooks), "Failed to print unformatted string.");
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(input, printed_unformatted, "Unformatted array is not correct.");
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(print_array(item, 0, true, &formatted_buffer, &global_hooks), "Failed to print formatted string.");
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed_formatted, "Formatted array is not correct.");
|
||||||
|
|
||||||
|
reset(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_array_should_print_empty_arrays(void)
|
||||||
|
{
|
||||||
|
assert_print_array("[]", "[]");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_array_should_print_arrays_with_one_element(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert_print_array("[1]", "[1]");
|
||||||
|
assert_print_array("[\"hello!\"]", "[\"hello!\"]");
|
||||||
|
assert_print_array("[[]]", "[[]]");
|
||||||
|
assert_print_array("[null]", "[null]");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_array_should_print_arrays_with_multiple_elements(void)
|
||||||
|
{
|
||||||
|
assert_print_array("[1, 2, 3]", "[1,2,3]");
|
||||||
|
assert_print_array("[1, null, true, false, [], \"hello\", {\n\t}]", "[1,null,true,false,[],\"hello\",{}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
/* initialize cJSON item */
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(print_array_should_print_empty_arrays);
|
||||||
|
RUN_TEST(print_array_should_print_arrays_with_one_element);
|
||||||
|
RUN_TEST(print_array_should_print_arrays_with_multiple_elements);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
119
tests/print_number.c
Normal file
119
tests/print_number.c
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "unity/examples/unity_config.h"
|
||||||
|
#include "unity/src/unity.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
static void assert_print_number(const char *expected, double input)
|
||||||
|
{
|
||||||
|
unsigned char printed[1024];
|
||||||
|
cJSON item[1];
|
||||||
|
printbuffer buffer;
|
||||||
|
buffer.buffer = printed;
|
||||||
|
buffer.length = sizeof(printed);
|
||||||
|
buffer.offset = 0;
|
||||||
|
buffer.noalloc = true;
|
||||||
|
|
||||||
|
memset(item, 0, sizeof(item));
|
||||||
|
cJSON_SetNumberValue(item, input);
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(print_number(item, &buffer, &global_hooks), "Failed to print number.");
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, buffer.buffer, "Printed number is not as expected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_number_should_print_zero(void)
|
||||||
|
{
|
||||||
|
assert_print_number("0", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_number_should_print_negative_integers(void)
|
||||||
|
{
|
||||||
|
assert_print_number("-1", -1);
|
||||||
|
assert_print_number("-32768", -32768);
|
||||||
|
assert_print_number("-2147483648", -2147483648);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_number_should_print_positive_integers(void)
|
||||||
|
{
|
||||||
|
assert_print_number("1", 1);
|
||||||
|
assert_print_number("32767", 32767);
|
||||||
|
assert_print_number("2147483647", 2147483647);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_number_should_print_positive_reals(void)
|
||||||
|
{
|
||||||
|
assert_print_number("0.123", 0.123);
|
||||||
|
assert_print_number("1.000000e-09", 10e-10);
|
||||||
|
assert_print_number("1000000000000", 10e11);
|
||||||
|
assert_print_number("1.230000e+129", 123e+127);
|
||||||
|
assert_print_number("0", 123e-128); /* TODO: Maybe this shouldn't be 0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_number_should_print_negative_reals(void)
|
||||||
|
{
|
||||||
|
assert_print_number("-0.0123", -0.0123);
|
||||||
|
assert_print_number("-1.000000e-09", -10e-10);
|
||||||
|
assert_print_number("-1000000000000000000000", -10e20);
|
||||||
|
assert_print_number("-1.230000e+129", -123e+127);
|
||||||
|
assert_print_number("-1.230000e-126", -123e-128);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_number_should_print_non_number(void)
|
||||||
|
{
|
||||||
|
TEST_IGNORE();
|
||||||
|
/* FIXME: Cannot test this easily in C89! */
|
||||||
|
/* assert_print_number("null", NaN); */
|
||||||
|
/* assert_print_number("null", INFTY); */
|
||||||
|
/* assert_print_number("null", -INFTY); */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void trim_trailing_zeroes_should_trim_trailing_zeroes(void)
|
||||||
|
{
|
||||||
|
printbuffer buffer;
|
||||||
|
unsigned char number[100];
|
||||||
|
buffer.length = sizeof(number);
|
||||||
|
buffer.buffer = number;
|
||||||
|
|
||||||
|
strcpy((char*)number, "10.00");
|
||||||
|
buffer.offset = sizeof("10.00") - 1;
|
||||||
|
TEST_ASSERT_TRUE(trim_trailing_zeroes(&buffer));
|
||||||
|
TEST_ASSERT_EQUAL_UINT8('\0', buffer.buffer[buffer.offset]);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("10", number);
|
||||||
|
TEST_ASSERT_EQUAL_UINT(sizeof("10") - 1, buffer.offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
/* initialize cJSON item */
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(print_number_should_print_zero);
|
||||||
|
RUN_TEST(print_number_should_print_negative_integers);
|
||||||
|
RUN_TEST(print_number_should_print_positive_integers);
|
||||||
|
RUN_TEST(print_number_should_print_positive_reals);
|
||||||
|
RUN_TEST(print_number_should_print_negative_reals);
|
||||||
|
RUN_TEST(print_number_should_print_non_number);
|
||||||
|
RUN_TEST(trim_trailing_zeroes_should_trim_trailing_zeroes);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
92
tests/print_object.c
Normal file
92
tests/print_object.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "unity/examples/unity_config.h"
|
||||||
|
#include "unity/src/unity.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
static void assert_print_object(const char * const expected, const char * const input)
|
||||||
|
{
|
||||||
|
unsigned char printed_unformatted[1024];
|
||||||
|
unsigned char printed_formatted[1024];
|
||||||
|
|
||||||
|
const unsigned char *error_pointer;
|
||||||
|
cJSON item[1];
|
||||||
|
|
||||||
|
printbuffer formatted_buffer;
|
||||||
|
printbuffer unformatted_buffer;
|
||||||
|
|
||||||
|
/* buffer for formatted printing */
|
||||||
|
formatted_buffer.buffer = printed_formatted;
|
||||||
|
formatted_buffer.length = sizeof(printed_formatted);
|
||||||
|
formatted_buffer.offset = 0;
|
||||||
|
formatted_buffer.noalloc = true;
|
||||||
|
|
||||||
|
/* buffer for unformatted printing */
|
||||||
|
unformatted_buffer.buffer = printed_unformatted;
|
||||||
|
unformatted_buffer.length = sizeof(printed_unformatted);
|
||||||
|
unformatted_buffer.offset = 0;
|
||||||
|
unformatted_buffer.noalloc = true;
|
||||||
|
|
||||||
|
memset(item, 0, sizeof(item));
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(parse_object(item, (const unsigned char*)input, &error_pointer, &global_hooks), "Failed to parse object.");
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(print_object(item, 0, false, &unformatted_buffer, &global_hooks), "Failed to print unformatted string.");
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(input, printed_unformatted, "Unformatted object is not correct.");
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(print_object(item, 0, true, &formatted_buffer, &global_hooks), "Failed to print formatted string.");
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed_formatted, "Formatted ojbect is not correct.");
|
||||||
|
|
||||||
|
reset(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_object_should_print_empty_objects(void)
|
||||||
|
{
|
||||||
|
assert_print_object("{\n}", "{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_object_should_print_objects_with_one_element(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert_print_object("{\n\t\"one\":\t1\n}", "{\"one\":1}");
|
||||||
|
assert_print_object("{\n\t\"hello\":\t\"world!\"\n}", "{\"hello\":\"world!\"}");
|
||||||
|
assert_print_object("{\n\t\"array\":\t[]\n}", "{\"array\":[]}");
|
||||||
|
assert_print_object("{\n\t\"null\":\tnull\n}", "{\"null\":null}");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_object_should_print_objects_with_multiple_elements(void)
|
||||||
|
{
|
||||||
|
assert_print_object("{\n\t\"one\":\t1,\n\t\"two\":\t2,\n\t\"three\":\t3\n}", "{\"one\":1,\"two\":2,\"three\":3}");
|
||||||
|
assert_print_object("{\n\t\"one\":\t1,\n\t\"NULL\":\tnull,\n\t\"TRUE\":\ttrue,\n\t\"FALSE\":\tfalse,\n\t\"array\":\t[],\n\t\"world\":\t\"hello\",\n\t\"object\":\t{\n\t}\n}", "{\"one\":1,\"NULL\":null,\"TRUE\":true,\"FALSE\":false,\"array\":[],\"world\":\"hello\",\"object\":{}}");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
/* initialize cJSON item */
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(print_object_should_print_empty_objects);
|
||||||
|
RUN_TEST(print_object_should_print_objects_with_one_element);
|
||||||
|
RUN_TEST(print_object_should_print_objects_with_multiple_elements);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
77
tests/print_string.c
Normal file
77
tests/print_string.c
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "unity/examples/unity_config.h"
|
||||||
|
#include "unity/src/unity.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
static void assert_print_string(const char *expected, const char *input)
|
||||||
|
{
|
||||||
|
unsigned char printed[1024];
|
||||||
|
printbuffer buffer;
|
||||||
|
buffer.buffer = printed;
|
||||||
|
buffer.length = sizeof(printed);
|
||||||
|
buffer.offset = 0;
|
||||||
|
buffer.noalloc = true;
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(print_string_ptr((const unsigned char*)input, &buffer, &global_hooks), "Failed to print string.");
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, printed, "The printed string isn't as expected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_string_should_print_empty_strings(void)
|
||||||
|
{
|
||||||
|
assert_print_string("\"\"", "");
|
||||||
|
assert_print_string("\"\"", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_string_should_print_ascii(void)
|
||||||
|
{
|
||||||
|
char ascii[0x7F];
|
||||||
|
size_t i = 1;
|
||||||
|
|
||||||
|
/* create ascii table */
|
||||||
|
for (i = 1; i < 0x7F; i++)
|
||||||
|
{
|
||||||
|
ascii[i-1] = (char)i;
|
||||||
|
}
|
||||||
|
ascii[0x7F-1] = '\0';
|
||||||
|
|
||||||
|
assert_print_string("\"\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"",
|
||||||
|
ascii);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_string_should_print_utf8(void)
|
||||||
|
{
|
||||||
|
assert_print_string("\"ü猫慕\"", "ü猫慕");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
/* initialize cJSON item */
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(print_string_should_print_empty_strings);
|
||||||
|
RUN_TEST(print_string_should_print_ascii);
|
||||||
|
RUN_TEST(print_string_should_print_utf8);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
102
tests/print_value.c
Normal file
102
tests/print_value.c
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "unity/examples/unity_config.h"
|
||||||
|
#include "unity/src/unity.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
static void assert_print_value(const char *input)
|
||||||
|
{
|
||||||
|
unsigned char printed[1024];
|
||||||
|
const unsigned char *error_pointer = NULL;
|
||||||
|
cJSON item[1];
|
||||||
|
printbuffer buffer;
|
||||||
|
buffer.buffer = printed;
|
||||||
|
buffer.length = sizeof(printed);
|
||||||
|
buffer.offset = 0;
|
||||||
|
buffer.noalloc = true;
|
||||||
|
|
||||||
|
memset(item, 0, sizeof(item));
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL_MESSAGE(parse_value(item, (const unsigned char*)input, &error_pointer, &global_hooks), "Failed to parse value.");
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE_MESSAGE(print_value(item, 0, false, &buffer, &global_hooks), "Failed to print value.");
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(input, buffer.buffer, "Printed value is not as expected.");
|
||||||
|
|
||||||
|
reset(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_value_should_print_null(void)
|
||||||
|
{
|
||||||
|
assert_print_value("null");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_value_should_print_true(void)
|
||||||
|
{
|
||||||
|
assert_print_value("true");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_value_should_print_false(void)
|
||||||
|
{
|
||||||
|
assert_print_value("false");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_value_should_print_number(void)
|
||||||
|
{
|
||||||
|
assert_print_value("1.5");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_value_should_print_string(void)
|
||||||
|
{
|
||||||
|
assert_print_value("\"\"");
|
||||||
|
assert_print_value("\"hello\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_value_should_print_array(void)
|
||||||
|
{
|
||||||
|
assert_print_value("[]");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_value_should_print_object(void)
|
||||||
|
{
|
||||||
|
assert_print_value("{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
/* initialize cJSON item */
|
||||||
|
UNITY_BEGIN();
|
||||||
|
|
||||||
|
RUN_TEST(print_value_should_print_null);
|
||||||
|
RUN_TEST(print_value_should_print_true);
|
||||||
|
RUN_TEST(print_value_should_print_false);
|
||||||
|
RUN_TEST(print_value_should_print_number);
|
||||||
|
RUN_TEST(print_value_should_print_string);
|
||||||
|
RUN_TEST(print_value_should_print_array);
|
||||||
|
RUN_TEST(print_value_should_print_object);
|
||||||
|
|
||||||
|
return UNITY_END();
|
||||||
|
}
|
||||||
@@ -41,13 +41,13 @@ Example:
|
|||||||
|
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
if (TEST_PROTECT() == 0)
|
if (TEST_PROTECT())
|
||||||
{
|
{
|
||||||
MyTest();
|
MyTest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
If MyTest calls `TEST_ABORT`, program control will immediately return to `TEST_PROTECT` with a non-zero return value.
|
If MyTest calls `TEST_ABORT`, program control will immediately return to `TEST_PROTECT` with a return value of zero.
|
||||||
|
|
||||||
|
|
||||||
Unity Assertion Summary
|
Unity Assertion Summary
|
||||||
|
|||||||
@@ -65,6 +65,17 @@ class ParseOutput
|
|||||||
@arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>"
|
@arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Test was flagged as having passed so format the output.
|
||||||
|
# This is using the Unity fixture output and not the original Unity output.
|
||||||
|
def testPassedUnityFixture(array)
|
||||||
|
testSuite = array[0].sub("TEST(", "")
|
||||||
|
testSuite = testSuite.sub(",", "")
|
||||||
|
testName = array[1].sub(")", "")
|
||||||
|
if @xmlOut == true
|
||||||
|
@arrayList.push " <testcase classname=\"" + testSuite + "\" name=\"" + testName + "\"/>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Test was flagged as being ingored so format the output
|
# Test was flagged as being ingored so format the output
|
||||||
def testIgnored(array)
|
def testIgnored(array)
|
||||||
@@ -73,6 +84,14 @@ class ParseOutput
|
|||||||
reason = array[lastItem].chomp
|
reason = array[lastItem].chomp
|
||||||
testSuiteVerify(array[@className])
|
testSuiteVerify(array[@className])
|
||||||
printf "%-40s IGNORED\n", testName
|
printf "%-40s IGNORED\n", testName
|
||||||
|
|
||||||
|
if testName.start_with? "TEST("
|
||||||
|
array2 = testName.split(" ")
|
||||||
|
@testSuite = array2[0].sub("TEST(", "")
|
||||||
|
@testSuite = @testSuite.sub(",", "")
|
||||||
|
testName = array2[1].sub(")", "")
|
||||||
|
end
|
||||||
|
|
||||||
if @xmlOut == true
|
if @xmlOut == true
|
||||||
@arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
|
@arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
|
||||||
@arrayList.push " <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>"
|
@arrayList.push " <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>"
|
||||||
@@ -87,6 +106,14 @@ class ParseOutput
|
|||||||
reason = array[lastItem].chomp + " at line: " + array[lastItem - 3]
|
reason = array[lastItem].chomp + " at line: " + array[lastItem - 3]
|
||||||
testSuiteVerify(array[@className])
|
testSuiteVerify(array[@className])
|
||||||
printf "%-40s FAILED\n", testName
|
printf "%-40s FAILED\n", testName
|
||||||
|
|
||||||
|
if testName.start_with? "TEST("
|
||||||
|
array2 = testName.split(" ")
|
||||||
|
@testSuite = array2[0].sub("TEST(", "")
|
||||||
|
@testSuite = @testSuite.sub(",", "")
|
||||||
|
testName = array2[1].sub(")", "")
|
||||||
|
end
|
||||||
|
|
||||||
if @xmlOut == true
|
if @xmlOut == true
|
||||||
@arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
|
@arrayList.push " <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
|
||||||
@arrayList.push " <failure type=\"ASSERT FAILED\"> " + reason + " </failure>"
|
@arrayList.push " <failure type=\"ASSERT FAILED\"> " + reason + " </failure>"
|
||||||
@@ -138,7 +165,7 @@ class ParseOutput
|
|||||||
lineSize = lineArray.size
|
lineSize = lineArray.size
|
||||||
# If we were able to split the line then we can look to see if any of our target words
|
# If we were able to split the line then we can look to see if any of our target words
|
||||||
# were found. Case is important.
|
# were found. Case is important.
|
||||||
if lineSize >= 4
|
if ((lineSize >= 4) || (line.start_with? "TEST("))
|
||||||
# Determine if this test passed
|
# Determine if this test passed
|
||||||
if line.include? ":PASS"
|
if line.include? ":PASS"
|
||||||
testPassed(lineArray)
|
testPassed(lineArray)
|
||||||
@@ -149,6 +176,12 @@ class ParseOutput
|
|||||||
elsif line.include? ":IGNORE:"
|
elsif line.include? ":IGNORE:"
|
||||||
testIgnored(lineArray)
|
testIgnored(lineArray)
|
||||||
testIgnore += 1
|
testIgnore += 1
|
||||||
|
elsif line.start_with? "TEST("
|
||||||
|
if line.include? " PASS"
|
||||||
|
lineArray = line.split(" ")
|
||||||
|
testPassedUnityFixture(lineArray)
|
||||||
|
testPass += 1
|
||||||
|
end
|
||||||
# If none of the keywords are found there are no more tests for this suite so clear
|
# If none of the keywords are found there are no more tests for this suite so clear
|
||||||
# the test flag
|
# the test flag
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -669,7 +669,7 @@ void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected,
|
|||||||
UnityTestResultsFailBegin(lineNumber);
|
UnityTestResultsFailBegin(lineNumber);
|
||||||
UnityPrint(UnityStrElement);
|
UnityPrint(UnityStrElement);
|
||||||
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
UnityPrintNumberUnsigned(num_elements - elements - 1);
|
||||||
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual);
|
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual);
|
||||||
UnityAddMsgIfSpecified(msg);
|
UnityAddMsgIfSpecified(msg);
|
||||||
UNITY_FAIL_AND_BAIL;
|
UNITY_FAIL_AND_BAIL;
|
||||||
}
|
}
|
||||||
@@ -691,7 +691,7 @@ void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
|
|||||||
if (!UnityFloatsWithin(delta, expected, actual))
|
if (!UnityFloatsWithin(delta, expected, actual))
|
||||||
{
|
{
|
||||||
UnityTestResultsFailBegin(lineNumber);
|
UnityTestResultsFailBegin(lineNumber);
|
||||||
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual);
|
UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual);
|
||||||
UnityAddMsgIfSpecified(msg);
|
UnityAddMsgIfSpecified(msg);
|
||||||
UNITY_FAIL_AND_BAIL;
|
UNITY_FAIL_AND_BAIL;
|
||||||
}
|
}
|
||||||
@@ -746,7 +746,7 @@ void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
|
|||||||
UnityPrint(trait_names[trait_index]);
|
UnityPrint(trait_names[trait_index]);
|
||||||
UnityPrint(UnityStrWas);
|
UnityPrint(UnityStrWas);
|
||||||
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||||
UnityPrintFloat(actual);
|
UnityPrintFloat((UNITY_DOUBLE)actual);
|
||||||
#else
|
#else
|
||||||
if (should_be_trait)
|
if (should_be_trait)
|
||||||
UnityPrint(UnityStrNot);
|
UnityPrint(UnityStrNot);
|
||||||
|
|||||||
Reference in New Issue
Block a user