Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05f75e360b | ||
|
|
32626cc251 | ||
|
|
24cf9308de | ||
|
|
51d3df6c9f | ||
|
|
cea3fe4165 | ||
|
|
f11b5eadc8 | ||
|
|
075a06f40b | ||
|
|
3c18c83513 | ||
|
|
99db5db9a4 | ||
|
|
bb5ab5916f | ||
|
|
411c50f671 | ||
|
|
ec2db50b6f | ||
|
|
74d0525201 | ||
|
|
3efef58c32 | ||
|
|
65541b900c | ||
|
|
c08f7e1d29 | ||
|
|
71b96afc27 | ||
|
|
749fefc0c4 | ||
|
|
50b3c30dfa | ||
|
|
c784f76c77 | ||
|
|
84237ff48e | ||
|
|
ab8489a851 | ||
|
|
795c3acabe | ||
|
|
2683d4d987 | ||
|
|
3c1bfe125c | ||
|
|
5916f70640 | ||
|
|
29cfc7a767 | ||
|
|
b1e9a6c0da | ||
|
|
3a20692c18 | ||
|
|
2f65e80a34 | ||
|
|
ef34500693 | ||
|
|
b0dfcde04c | ||
|
|
1934059554 | ||
|
|
cc84a446be | ||
|
|
e58f7ec027 | ||
|
|
4bfb880093 | ||
|
|
b7ce06224b | ||
|
|
227d3398d6 | ||
|
|
466eb8e3f8 | ||
|
|
4ec6e76ea2 | ||
|
|
a1b37d0abe | ||
|
|
3d971db426 | ||
|
|
30e1e7af7c | ||
|
|
76e5296d0d | ||
|
|
c597601cf1 | ||
|
|
e3d5798896 | ||
|
|
cf1842dc6f |
177
CHANGELOG.md
Normal file
177
CHANGELOG.md
Normal file
@@ -0,0 +1,177 @@
|
||||
1.4.7
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix `cJSONUtils_ApplyPatches`, it was completely broken and apparently nobody noticed (or at least reported it) (075a06f40bdc4f836c7dd7cad690d253a57cfc50)
|
||||
* Fix inconsistent prototype for `cJSON_GetObjectItemCaseSensitive` (51d3df6c9f7b56b860c8fb24abe7bab255cd4fa9) thanks @PawelWMS
|
||||
|
||||
1.4.6
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Several corrections in the README
|
||||
* Making clear that `valueint` should not be written to
|
||||
* Fix overflow detection in `ensure` (2683d4d9873df87c4bdccc523903ddd78d1ad250)
|
||||
* Fix a potential null pointer dereference in cJSON_Utils (795c3acabed25c9672006b2c0f40be8845064827)
|
||||
* Replace incorrect `sizeof('\0')` with `sizeof("")` (84237ff48e69825c94261c624eb0376d0c328139)
|
||||
* Add caveats section to the README (50b3c30dfa89830f8f477ce33713500740ac3b79)
|
||||
* Make cJSON locale independent (#146) Thanks @peterh for reporting
|
||||
* Fix compiling without CMake with MSVC (#147) Thanks @dertuxmalwieder for reporting
|
||||
|
||||
1.4.5
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix bug in `cJSON_SetNumberHelper`, thanks @mmkeeper (#138 ef34500693e8c4a2849d41a4bd66fd19c9ec46c2)
|
||||
* Workaround for internal compiler error in GCC 5.4.0 and 6.3.1 on x86 (2f65e80a3471d053fdc3f8aed23d01dd1782a5cb [GCC bugreport](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80097))
|
||||
|
||||
1.4.4
|
||||
=====
|
||||
Fixes:
|
||||
--------
|
||||
* Fix a theoretical integer overflow, (not sure if it is possible on actual hardware) e58f7ec027d00b7cdcbf63e518c1b5268b29b3da
|
||||
* Fix an off by one error (cc84a446be20cc283bafdc4d94c050ba1111ac02), thanks @gatzka
|
||||
* Double check the offset of the print buffer in `ensure` (1934059554b9a0971e00f79e96900f422cfdd114)
|
||||
|
||||
Improvements:
|
||||
-------------
|
||||
* Add a note in the header about required buffer size when using `cJSON_PrintPreallocated` (4bfb88009342fb568295a7f6dc4b7fee74fbf022)
|
||||
|
||||
1.4.3
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix compilation of the tests on 32 bit PowerPC and potentially other systems (4ec6e76ea2eec16f54b58e8c95b4c734e59481e4)
|
||||
* Fix compilation with old GCC compilers (4.3+ were tested) (227d3398d6b967879761ebe02c1b63dbd6ea6e0d, 466eb8e3f8a65080f2b3ca4a79ab7b72bd539dba), see also #126
|
||||
|
||||
1.4.2
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix minimum required cmake version (30e1e7af7c63db9b55f5a3cda977a6c032f0b132)
|
||||
* Fix detection of supported compiler flags (76e5296d0d05ceb3018a9901639e0e171b44a557)
|
||||
* Run `cJSON_test` and `cJSON_test_utils` along with unity tests (c597601cf151a757dcf800548f18034d4ddfe2cb)
|
||||
|
||||
1.4.1
|
||||
=====
|
||||
Fix: Make `print_number` abort with a failure in out of memory situations (cf1842dc6f64c49451a022308b4415e4d468be0a)
|
||||
|
||||
1.4.0
|
||||
=====
|
||||
Features
|
||||
--------
|
||||
* Functions to check the type of an item (#120)
|
||||
* Use dllexport on windows and fvisibility on Unix systems for public functions (#116), thanks @mjerris
|
||||
* Remove trailing zeroes from printed numbers (#123)
|
||||
* Expose the internal boolean type `cJSON_bool` in the header (2d3520e0b9d0eb870e8886e8a21c571eeddbb310)
|
||||
|
||||
Fixes
|
||||
-----
|
||||
* Fix handling of NULL pointers in `cJSON_ArrayForEach` (b47d0e34caaef298edfb7bd09a72cfff21d231ff)
|
||||
* Make it compile with GCC 7 (fix -Wimplicit-fallthrough warning) (9d07917feb1b613544a7513d19233d4c851ad7ad)
|
||||
|
||||
Other Improvements
|
||||
------------------
|
||||
* internally use realloc if available (#110)
|
||||
* builtin support for fuzzing with [afl](http://lcamtuf.coredump.cx/afl/) (#111)
|
||||
* unit tests for the print functions (#112)
|
||||
* Always use buffered printing (#113)
|
||||
* simplify the print functions (#114)
|
||||
* Add the compiler flags `-Wdouble-conversion`, `-Wparentheses` and `-Wcomma` (#122)
|
||||
|
||||
1.3.2
|
||||
=====
|
||||
Fix:
|
||||
----
|
||||
- Don't build the unity library if testing is disabled ( #121 ). Thanks @ffontaine
|
||||
|
||||
1.3.1
|
||||
=====
|
||||
Bugfix release that fixes an out of bounds read #118. This shouldn't have any security implications.
|
||||
|
||||
1.3.0
|
||||
=====
|
||||
This release includes a lot of rework in the parser and includes the Cunity unit testing framework, as well as some fixes. I increased the minor version number because there were quite a lot of internal changes.
|
||||
|
||||
Features:
|
||||
---------
|
||||
- New type for cJSON structs: `cJSON_Invalid` (#108)
|
||||
|
||||
Fixes:
|
||||
------
|
||||
- runtime checks for a lot of potential integer overflows
|
||||
- fix incorrect return in cJSON_PrintBuffered (cf9d57d56cac21fc59465b8d26cf29bf6d2a87b3)
|
||||
- fix several potential issues found by [Coverity](https://scan.coverity.com/projects/cjson)
|
||||
- fix potentially undefined behavior when assigning big numbers to `valueint` (41e2837df1b1091643aff073f2313f6ff3cc10f4)
|
||||
- Numbers exceeding `INT_MAX` or lower than `INT_MIN` will be explicitly assigned to `valueint` as `INT_MAX` and `INT_MIN` respectively (saturation on overflow).
|
||||
- fix the `cJSON_SetNumberValue` macro (87f77274de6b3af00fb9b9a7f3b900ef382296c2), this slightly changes the behavior, see commit message
|
||||
|
||||
Introduce unit tests
|
||||
--------------------
|
||||
|
||||
Started writing unit tests with the [Cunity](https://github.com/ThrowTheSwitch/Unity) testing framework. Currently this covers the parser functions.
|
||||
|
||||
Also:
|
||||
- Support for running the tests with [Valgrind](http://valgrind.org)
|
||||
- Support for compiling the tests with [AddressSanitizer](https://github.com/google/sanitizers) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
|
||||
- `travis.yml` file for running unit tests on travis. (not enabled for the repository yet though #102)
|
||||
|
||||
Simplifications
|
||||
---------------
|
||||
|
||||
After having unit tests for the parser function in place, I started refactoring the parser functions (as well as others) and making them easier to read and maintain.
|
||||
- Use `strtod` from the standard library for parsing numbers (074766997246481dfc72bfa78f07898a2716473f)
|
||||
- Use goto-fail in several parser functions (#100)
|
||||
- Rewrite/restructure all of the parsing functions to be easier to understand and have less code paths doing the same as another. (#109)
|
||||
- Simplify the buffer allocation strategy to always doubling the needed amount (9f6fa94c91a87b71e4c6868dbf2ce431a48517b0)
|
||||
- Combined `cJSON_AddItemToObject` and `cJSON_AddItemToObjectCS` to one function (cf862d0fed7f9407e4b046d78d3d8050d2080d12)
|
||||
|
||||
Other changes
|
||||
-------------
|
||||
- Prevent the usage of incompatible C and header versions via preprocessor directive (123bb1af7bfae41d805337fef4b41045ef6c7d25)
|
||||
- Let CMake automatically detect compiler flags
|
||||
- Add new compiler flags (`-Wundef`, `-Wswitch-default`, `-Wconversion`, `-fstack-protector-strong`) (#98)
|
||||
- Change internal sizes from `int` to `size_t` (ecd5678527a6bc422da694e5be9e9979878fe6a0)
|
||||
- Change internal strings from `char*` to `unsigned char*` (28b9ba4334e0f7309e867e874a31f395c0ac2474)
|
||||
- Add `const` in more places
|
||||
|
||||
1.2.1
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
- Fixes a potential null pointer dereference in cJSON_Utils, discovered using clang's static analyzer by @bnason-nf (#96)
|
||||
|
||||
1.2.0
|
||||
=====
|
||||
Features:
|
||||
---------
|
||||
- Add a new type of cJSON item for raw JSON and support printing it. Thanks @loigu (#65, #90)
|
||||
|
||||
Fixes:
|
||||
------
|
||||
- Compiler warning if const is casted away, Thanks @gatzka (#83)
|
||||
- Fix compile error with strict-overflow on PowerPC, (#85)
|
||||
- Fix typo in the README, thanks @MicroJoe (#88)
|
||||
- Add compile flag for compatibility with C++ compilers
|
||||
|
||||
1.1.0
|
||||
=====
|
||||
- Add a function `cJSON_PrintPreallocated` to print to a preallocated buffer, thanks @ChisholmKyle (#72)
|
||||
- More compiler warnings when using Clang or GCC, thanks @gatzka (#75, #78)
|
||||
- fixed a memory leak in `cJSON_Duplicate`, thanks @alperakcan (#81)
|
||||
- fix the `ENABLE_CUSTOM_COMPILER_FLAGS` cmake option
|
||||
|
||||
1.0.2
|
||||
=====
|
||||
Rename internal boolean type, see #71.
|
||||
|
||||
1.0.1
|
||||
=====
|
||||
Small bugfix release.
|
||||
- Fixes a bug with the use of the cJSON structs type in cJSON_Utils, see d47339e2740360e6e0994527d5e4752007480f3a
|
||||
- improve code readability
|
||||
- initialize all variables
|
||||
|
||||
1.0.0
|
||||
=====
|
||||
This is the first official versioned release of cJSON. It provides an API version for the shared library and improved Makefile and CMake build files.
|
||||
@@ -1,7 +1,5 @@
|
||||
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
subdirs(tests fuzzing)
|
||||
cmake_minimum_required(VERSION 2.8.5)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
@@ -9,7 +7,7 @@ project(cJSON C)
|
||||
|
||||
set(PROJECT_VERSION_MAJOR 1)
|
||||
set(PROJECT_VERSION_MINOR 4)
|
||||
set(PROJECT_VERSION_PATCH 0)
|
||||
set(PROJECT_VERSION_PATCH 7)
|
||||
set(CJSON_VERSION_SO 1)
|
||||
set(CJSON_UTILS_VERSION_SO 1)
|
||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
@@ -78,10 +76,13 @@ foreach(compiler_flag ${custom_compiler_flags})
|
||||
|
||||
CHECK_C_COMPILER_FLAG(${compiler_flag} "FLAG_SUPPORTED_${current_variable}")
|
||||
if (FLAG_SUPPORTED_${current_variable})
|
||||
list(APPEND supported_compiler_flags)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_flag}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${supported_compiler_flags}")
|
||||
|
||||
#variables for pkg-config
|
||||
set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
set(libdir "${CMAKE_INSTALL_LIBDIR}")
|
||||
@@ -167,9 +168,30 @@ if(ENABLE_CJSON_TEST)
|
||||
add_executable("${TEST_CJSON}" test.c)
|
||||
target_link_libraries("${TEST_CJSON}" "${CJSON_LIB}")
|
||||
|
||||
add_test(NAME ${TEST_CJSON} COMMAND "${CMAKE_CURRENT_BINARY_DIR}/${TEST_CJSON}")
|
||||
|
||||
# Disable -fsanitize=float-divide-by-zero for cJSON_test
|
||||
if (FLAG_SUPPORTED_fsanitizefloatdividebyzero)
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=float-divide-by-zero")
|
||||
else()
|
||||
target_compile_options(${TEST_CJSON} PRIVATE "-fno-sanitize=float-divide-by-zero")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_CJSON_UTILS)
|
||||
set(TEST_CJSON_UTILS cJSON_test_utils)
|
||||
add_executable("${TEST_CJSON_UTILS}" test_utils.c)
|
||||
target_link_libraries("${TEST_CJSON_UTILS}" "${CJSON_UTILS_LIB}")
|
||||
|
||||
add_test(NAME ${TEST_CJSON_UTILS} COMMAND "${CMAKE_CURRENT_BINARY_DIR}/${TEST_CJSON_UTILS}")
|
||||
endif()
|
||||
|
||||
#"check" target that automatically builds everything and runs the tests
|
||||
add_custom_target(check
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
|
||||
DEPENDS ${TEST_CJSON} ${TEST_CJSON_UTILS})
|
||||
endif()
|
||||
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(fuzzing)
|
||||
|
||||
2
Makefile
2
Makefile
@@ -10,7 +10,7 @@ UTILS_TEST_SRC = cJSON.c cJSON_Utils.c test_utils.c
|
||||
|
||||
LDLIBS = -lm
|
||||
|
||||
LIBVERSION = 1.4.0
|
||||
LIBVERSION = 1.4.7
|
||||
CJSON_SOVERSION = 1
|
||||
UTILS_SOVERSION = 1
|
||||
|
||||
|
||||
67
README.md
67
README.md
@@ -9,6 +9,7 @@ Ultralightweight JSON parser in ANSI C.
|
||||
* [Building](#building)
|
||||
* [Some JSON](#some-json)
|
||||
* [Here's the structure](#heres-the-structure)
|
||||
* [Caveats](#caveats)
|
||||
* [Enjoy cJSON!](#enjoy-cjson)
|
||||
|
||||
## License
|
||||
@@ -62,7 +63,7 @@ Because the entire library is only one C file and one header file, you can just
|
||||
cJSON is written in ANSI C (C89) in order to support as many platforms and compilers as possible.
|
||||
|
||||
#### CMake
|
||||
With CMake, cJSON supports a full blown build system. This way you get the most features. With CMake it is recommended to do an out of tree build, meaning the compiled files are put in a directory separate from the source files. So in order to build cJSON with CMake on a Unix platform, make a `build` directory and run CMake inside it.
|
||||
With CMake, cJSON supports a full blown build system. This way you get the most features. CMake with an equal or higher version than 2.8.5 is supported. With CMake it is recommended to do an out of tree build, meaning the compiled files are put in a directory separate from the source files. So in order to build cJSON with CMake on a Unix platform, make a `build` directory and run CMake inside it.
|
||||
|
||||
```
|
||||
mkdir build
|
||||
@@ -97,10 +98,8 @@ make
|
||||
make DESTDIR=$pkgdir install
|
||||
```
|
||||
|
||||
CMake supports a lot of different platforms, not only UNIX Makefiles, but only UNIX Makefiles have been tested. It works on GNU/Linux and has been confirmed to compile on some versions of macOS, Cygwin, FreeBSD, Solaris and OpenIndiana.
|
||||
|
||||
#### Makefile
|
||||
If you don't have CMake available, but still have make. You can use the makefile to build cJSON:
|
||||
If you don't have CMake available, but still have GNU make. You can use the makefile to build cJSON:
|
||||
|
||||
Run this command in the directory with the source code and it will automatically compile static and shared libraries and a little test program.
|
||||
|
||||
@@ -138,13 +137,19 @@ What's the framerate?
|
||||
|
||||
```c
|
||||
cJSON *format = cJSON_GetObjectItem(root, "format");
|
||||
int framerate = cJSON_GetObjectItem(format, "frame rate")->valueint;
|
||||
cJSON *framerate_item = cJSON_GetObjectItem(format, "frame rate");
|
||||
double framerate = 0;
|
||||
if (cJSON_IsNumber(framerate_item))
|
||||
{
|
||||
framerate = framerate_item->valuedouble;
|
||||
}
|
||||
```
|
||||
|
||||
Want to change the framerate?
|
||||
|
||||
```c
|
||||
cJSON_GetObjectItem(format, "frame rate")->valueint = 25;
|
||||
cJSON *framerate_item = cJSON_GetObjectItem(format, "frame rate");
|
||||
cJSON_SetNumberValue(framerate_item, 25);
|
||||
```
|
||||
|
||||
Back to disk?
|
||||
@@ -203,7 +208,7 @@ typedef struct cJSON {
|
||||
int type;
|
||||
|
||||
char *valuestring;
|
||||
int valueint;
|
||||
int valueint; /* writing to valueint is DEPRECATED, please use cJSON_SetNumberValue instead */
|
||||
double valuedouble;
|
||||
|
||||
char *string;
|
||||
@@ -219,8 +224,7 @@ A `child` entry will have `prev == 0`, but next potentially points on. The last
|
||||
The type expresses *Null*/*True*/*False*/*Number*/*String*/*Array*/*Object*, all of which are `#defined` in
|
||||
`cJSON.h`.
|
||||
|
||||
A *Number* has `valueint` and `valuedouble`. If you're expecting an `int`, read `valueint`, if not read
|
||||
`valuedouble`.
|
||||
A *Number* has `valueint` and `valuedouble`. `valueint` is a relict of the past, so always use `valuedouble`.
|
||||
|
||||
Any entry which is in the linked list which is the child of an object will have a `string`
|
||||
which is the "name" of the entry. When I said "name" in the above example, that's `string`.
|
||||
@@ -237,8 +241,8 @@ void parse_and_callback(cJSON *item, const char *prefix)
|
||||
{
|
||||
while (item)
|
||||
{
|
||||
char *newprefix = malloc(strlen(prefix) + strlen(item->name) + 2);
|
||||
sprintf(newprefix, "%s/%s", prefix, item->name);
|
||||
char *newprefix = malloc(strlen(prefix) + strlen(item->string) + 2);
|
||||
sprintf(newprefix, "%s/%s", prefix, item->string);
|
||||
int dorecurse = callback(newprefix, item->type, item);
|
||||
if (item->child && dorecurse)
|
||||
{
|
||||
@@ -261,22 +265,22 @@ int callback(const char *name, int type, cJSON *item)
|
||||
{
|
||||
/* populate name */
|
||||
}
|
||||
else if (!strcmp(name, "format/type")
|
||||
else if (!strcmp(name, "format/type"))
|
||||
{
|
||||
/* handle "rect" */ }
|
||||
else if (!strcmp(name, "format/width")
|
||||
else if (!strcmp(name, "format/width"))
|
||||
{
|
||||
/* 800 */
|
||||
}
|
||||
else if (!strcmp(name, "format/height")
|
||||
else if (!strcmp(name, "format/height"))
|
||||
{
|
||||
/* 600 */
|
||||
}
|
||||
else if (!strcmp(name, "format/interlace")
|
||||
else if (!strcmp(name, "format/interlace"))
|
||||
{
|
||||
/* false */
|
||||
}
|
||||
else if (!strcmp(name, "format/frame rate")
|
||||
else if (!strcmp(name, "format/frame rate"))
|
||||
{
|
||||
/* 24 */
|
||||
}
|
||||
@@ -369,6 +373,37 @@ The `test.c` code shows how to handle a bunch of typical cases. If you uncomment
|
||||
the code, it'll load, parse and print a bunch of test files, also from [json.org](http://json.org),
|
||||
which are more complex than I'd care to try and stash into a `const char array[]`.
|
||||
|
||||
### Caveats
|
||||
|
||||
#### Zero Character
|
||||
|
||||
cJSON doesn't support strings that contain the zero character `'\0'` or `\u0000`. This is impossible with the current API because strings are zero terminated.
|
||||
|
||||
#### Character Encoding
|
||||
|
||||
cJSON only supports UTF-8 encoded input and will always produce UTF-8 as output (If the input contained invalid UTF-8, it will most likely propagate it through to the output, thereby making the output non-valid UTF-8).
|
||||
|
||||
#### C Standard
|
||||
|
||||
cJSON is written in ANSI C (or C89, C90). If your compiler or C library doesn't follow this standard, correct behavior is not guaranteed.
|
||||
|
||||
NOTE: ANSI C is not C++ therefore it shouldn't be compiled by a C++ compiler. You can compile it with a C compiler and link it with your C++ code however. Although compiling with a C++ compiler might work, correct behavior is not guaranteed.
|
||||
|
||||
#### Floating Point Numbers
|
||||
|
||||
cJSON does not officially support any `double` implementations other than IEE754 double precision floating point numbers. It might still work with other implementations but bugs with these will be considered invalid.
|
||||
|
||||
The maximum length of a floating point literal that cJSON supports is currently 63 characters.
|
||||
|
||||
#### Thread Safety
|
||||
|
||||
In general cJSON is **not thread safe**.
|
||||
|
||||
However it is thread safe under the following conditions:
|
||||
* `cJSON_GetErrorPtr` is never used (the `return_parse_end` parameter of `cJSON_ParseWithOpts` can be used instead)
|
||||
* `cJSON_InitHooks` is only ever called before using cJSON in any threads.
|
||||
* `setlocale` is never called before all calls to cJSON functions have returned.
|
||||
|
||||
# Enjoy cJSON!
|
||||
|
||||
- Dave Gamble, Aug 2009
|
||||
|
||||
203
cJSON.c
203
cJSON.c
@@ -31,6 +31,7 @@
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <locale.h>
|
||||
#pragma GCC visibility pop
|
||||
|
||||
#include "cJSON.h"
|
||||
@@ -47,7 +48,7 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
|
||||
}
|
||||
|
||||
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
|
||||
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 4) || (CJSON_VERSION_PATCH != 0)
|
||||
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 4) || (CJSON_VERSION_PATCH != 7)
|
||||
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
|
||||
#endif
|
||||
|
||||
@@ -100,7 +101,7 @@ static unsigned char* cJSON_strdup(const unsigned char* str, const internal_hook
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen((const char*)str) + 1;
|
||||
len = strlen((const char*)str) + sizeof("");
|
||||
if (!(copy = (unsigned char*)hooks->allocate(len)))
|
||||
{
|
||||
return NULL;
|
||||
@@ -177,19 +178,63 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *c)
|
||||
}
|
||||
}
|
||||
|
||||
/* get the decimal point character of the current locale */
|
||||
static unsigned char get_decimal_point(void)
|
||||
{
|
||||
struct lconv *lconv = localeconv();
|
||||
return (unsigned char) lconv->decimal_point[0];
|
||||
}
|
||||
|
||||
/* Parse the input text to generate a number, and populate the result into item. */
|
||||
static const unsigned char *parse_number(cJSON * const item, const unsigned char * const input)
|
||||
{
|
||||
double number = 0;
|
||||
unsigned char *after_end = NULL;
|
||||
unsigned char number_c_string[64];
|
||||
unsigned char decimal_point = get_decimal_point();
|
||||
size_t i = 0;
|
||||
|
||||
if (input == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
number = strtod((const char*)input, (char**)&after_end);
|
||||
if (input == after_end)
|
||||
/* copy the number into a temporary buffer and replace '.' with the decimal point
|
||||
* of the current locale (for strtod) */
|
||||
for (i = 0; (i < (sizeof(number_c_string) - 1)) && (input[i] != '\0'); i++)
|
||||
{
|
||||
switch (input[i])
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '+':
|
||||
case '-':
|
||||
case 'e':
|
||||
case 'E':
|
||||
number_c_string[i] = input[i];
|
||||
break;
|
||||
|
||||
case '.':
|
||||
number_c_string[i] = decimal_point;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto loop_end;
|
||||
}
|
||||
}
|
||||
loop_end:
|
||||
number_c_string[i] = '\0';
|
||||
|
||||
number = strtod((const char*)number_c_string, (char**)&after_end);
|
||||
if (number_c_string == after_end)
|
||||
{
|
||||
return NULL; /* parse_error */
|
||||
}
|
||||
@@ -212,7 +257,7 @@ static const unsigned char *parse_number(cJSON * const item, const unsigned char
|
||||
|
||||
item->type = cJSON_Number;
|
||||
|
||||
return after_end;
|
||||
return input + (after_end - number_c_string);
|
||||
}
|
||||
|
||||
/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
|
||||
@@ -228,7 +273,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
|
||||
}
|
||||
else
|
||||
{
|
||||
object->valueint = cJSON_Number;
|
||||
object->valueint = (int)number;
|
||||
}
|
||||
|
||||
return object->valuedouble = number;
|
||||
@@ -253,13 +298,19 @@ static unsigned char* ensure(printbuffer * const p, size_t needed, const interna
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((p->length > 0) && (p->offset >= p->length))
|
||||
{
|
||||
/* make sure that offset is valid */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (needed > INT_MAX)
|
||||
{
|
||||
/* sizes bigger than INT_MAX are currently not supported */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
needed += p->offset;
|
||||
needed += p->offset + 1;
|
||||
if (needed <= p->length)
|
||||
{
|
||||
return p->buffer + p->offset;
|
||||
@@ -270,8 +321,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed, const interna
|
||||
}
|
||||
|
||||
/* calculate new buffer size */
|
||||
newsize = needed * 2;
|
||||
if (newsize > INT_MAX)
|
||||
if (needed > (INT_MAX / 2))
|
||||
{
|
||||
/* overflow of int, use INT_MAX if possible */
|
||||
if (needed <= INT_MAX)
|
||||
@@ -283,6 +333,10 @@ static unsigned char* ensure(printbuffer * const p, size_t needed, const interna
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newsize = needed * 2;
|
||||
}
|
||||
|
||||
if (hooks->reallocate != NULL)
|
||||
{
|
||||
@@ -327,34 +381,24 @@ static void update_offset(printbuffer * const buffer)
|
||||
}
|
||||
|
||||
/* Removes trailing zeroes from the end of a printed number */
|
||||
static cJSON_bool trim_trailing_zeroes(printbuffer * const buffer)
|
||||
static int trim_trailing_zeroes(const unsigned char * const number, int length, const unsigned char decimal_point)
|
||||
{
|
||||
size_t offset = 0;
|
||||
unsigned char *content = NULL;
|
||||
|
||||
if ((buffer == NULL) || (buffer->buffer == NULL) || (buffer->offset < 1))
|
||||
if ((number == NULL) || (length <= 0))
|
||||
{
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = buffer->offset - 1;
|
||||
content = buffer->buffer;
|
||||
|
||||
while ((offset > 0) && (content[offset] == '0'))
|
||||
while ((length > 0) && (number[length - 1] == '0'))
|
||||
{
|
||||
offset--;
|
||||
length--;
|
||||
}
|
||||
if ((offset > 0) && (content[offset] == '.'))
|
||||
if ((length > 0) && (number[length - 1] == decimal_point))
|
||||
{
|
||||
offset--;
|
||||
/* remove trailing decimal_point */
|
||||
length--;
|
||||
}
|
||||
|
||||
offset++;
|
||||
content[offset] = '\0';
|
||||
|
||||
buffer->offset = offset;
|
||||
|
||||
return true;
|
||||
return length;
|
||||
}
|
||||
|
||||
/* Render the number nicely from the given item into a string. */
|
||||
@@ -363,52 +407,75 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
|
||||
unsigned char *output_pointer = NULL;
|
||||
double d = item->valuedouble;
|
||||
int length = 0;
|
||||
cJSON_bool trim_zeroes = true; /* should at the end be removed? */
|
||||
size_t i = 0;
|
||||
cJSON_bool trim_zeroes = true; /* should zeroes at the end be removed? */
|
||||
unsigned char number_buffer[64]; /* temporary buffer to print the number into */
|
||||
unsigned char decimal_point = get_decimal_point();
|
||||
|
||||
if (output_buffer == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This is a nice tradeoff. */
|
||||
output_pointer = ensure(output_buffer, 64, hooks);
|
||||
if (output_pointer != NULL)
|
||||
/* This checks for NaN and Infinity */
|
||||
if ((d * 0) != 0)
|
||||
{
|
||||
/* This checks for NaN and Infinity */
|
||||
if ((d * 0) != 0)
|
||||
{
|
||||
length = sprintf((char*)output_pointer, "null");
|
||||
}
|
||||
else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60))
|
||||
{
|
||||
/* integer */
|
||||
length = sprintf((char*)output_pointer, "%.0f", d);
|
||||
trim_zeroes = false; /* don't remove zeroes for "big integers" */
|
||||
}
|
||||
else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9))
|
||||
{
|
||||
length = sprintf((char*)output_pointer, "%e", d);
|
||||
trim_zeroes = false; /* don't remove zeroes in engineering notation */
|
||||
}
|
||||
else
|
||||
{
|
||||
length = sprintf((char*)output_pointer, "%f", d);
|
||||
}
|
||||
length = sprintf((char*)number_buffer, "null");
|
||||
}
|
||||
else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60))
|
||||
{
|
||||
/* integer */
|
||||
length = sprintf((char*)number_buffer, "%.0f", d);
|
||||
trim_zeroes = false; /* don't remove zeroes for "big integers" */
|
||||
}
|
||||
else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9))
|
||||
{
|
||||
length = sprintf((char*)number_buffer, "%e", d);
|
||||
trim_zeroes = false; /* don't remove zeroes in engineering notation */
|
||||
}
|
||||
else
|
||||
{
|
||||
length = sprintf((char*)number_buffer, "%f", d);
|
||||
}
|
||||
|
||||
/* sprintf failed */
|
||||
if (length < 0)
|
||||
/* sprintf failed or buffer overrun occured */
|
||||
if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
output_buffer->offset += (size_t)length;
|
||||
|
||||
if (trim_zeroes)
|
||||
{
|
||||
return trim_trailing_zeroes(output_buffer);
|
||||
length = trim_trailing_zeroes(number_buffer, length, decimal_point);
|
||||
if (length <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* reserve appropriate space in the output */
|
||||
output_pointer = ensure(output_buffer, (size_t)length, hooks);
|
||||
if (output_pointer == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* copy the printed number to the output and replace locale
|
||||
* dependent decimal point with '.' */
|
||||
for (i = 0; i < ((size_t)length); i++)
|
||||
{
|
||||
if (number_buffer[i] == decimal_point)
|
||||
{
|
||||
output_pointer[i] = '.';
|
||||
continue;
|
||||
}
|
||||
|
||||
output_pointer[i] = number_buffer[i];
|
||||
}
|
||||
output_pointer[i] = '\0';
|
||||
|
||||
output_buffer->offset += (size_t)length;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -617,7 +684,7 @@ static const unsigned char *parse_string(cJSON * const item, const unsigned char
|
||||
|
||||
/* This is at most how much we need for the output */
|
||||
allocation_length = (size_t) (input_end - input) - skipped_bytes;
|
||||
output = (unsigned char*)hooks->allocate(allocation_length + sizeof('\0'));
|
||||
output = (unsigned char*)hooks->allocate(allocation_length + sizeof(""));
|
||||
if (output == NULL)
|
||||
{
|
||||
goto fail; /* allocation failure */
|
||||
@@ -1090,7 +1157,7 @@ static cJSON_bool print_value(const cJSON * const item, const size_t depth, cons
|
||||
return false;
|
||||
}
|
||||
|
||||
raw_length = strlen(item->valuestring) + sizeof('\0');
|
||||
raw_length = strlen(item->valuestring) + sizeof("");
|
||||
output = ensure(output_buffer, raw_length, hooks);
|
||||
if (output == NULL)
|
||||
{
|
||||
@@ -1224,7 +1291,7 @@ static cJSON_bool print_array(const cJSON * const item, const size_t depth, cons
|
||||
update_offset(output_buffer);
|
||||
if (current_element->next)
|
||||
{
|
||||
length = format ? 2 : 1;
|
||||
length = (size_t) (format ? 2 : 1);
|
||||
output_pointer = ensure(output_buffer, length + 1, hooks);
|
||||
if (output_pointer == NULL)
|
||||
{
|
||||
@@ -1360,7 +1427,7 @@ static cJSON_bool print_object(const cJSON * const item, const size_t depth, con
|
||||
}
|
||||
|
||||
/* Compose the output: */
|
||||
length = format ? 2 : 1; /* fmt: {\n */
|
||||
length = (size_t) (format ? 2 : 1); /* fmt: {\n */
|
||||
output_pointer = ensure(output_buffer, length + 1, hooks);
|
||||
if (output_pointer == NULL)
|
||||
{
|
||||
@@ -1398,7 +1465,7 @@ static cJSON_bool print_object(const cJSON * const item, const size_t depth, con
|
||||
}
|
||||
update_offset(output_buffer);
|
||||
|
||||
length = format ? 2 : 1;
|
||||
length = (size_t) (format ? 2 : 1);
|
||||
output_pointer = ensure(output_buffer, length, hooks);
|
||||
if (output_pointer == NULL)
|
||||
{
|
||||
@@ -1419,7 +1486,7 @@ static cJSON_bool print_object(const cJSON * const item, const size_t depth, con
|
||||
update_offset(output_buffer);
|
||||
|
||||
/* print comma if not last */
|
||||
length = (size_t) (format ? 1 : 0) + (current_item->next ? 1 : 0);
|
||||
length = (size_t) ((format ? 1 : 0) + (current_item->next ? 1 : 0));
|
||||
output_pointer = ensure(output_buffer, length + 1, hooks);
|
||||
if (output_pointer == NULL)
|
||||
{
|
||||
@@ -1578,6 +1645,10 @@ CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSO
|
||||
item->type &= ~cJSON_StringIsConst;
|
||||
}
|
||||
|
||||
#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
/* Add an item to an object with constant string as key */
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
|
||||
{
|
||||
@@ -1589,13 +1660,13 @@ CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJ
|
||||
{
|
||||
global_hooks.deallocate(item->string);
|
||||
}
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
item->string = (char*)string;
|
||||
#pragma GCC diagnostic pop
|
||||
item->type |= cJSON_StringIsConst;
|
||||
cJSON_AddItemToArray(object, item);
|
||||
}
|
||||
#if defined (__clang__) || ((__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
|
||||
{
|
||||
|
||||
21
cJSON.h
21
cJSON.h
@@ -31,7 +31,7 @@ extern "C"
|
||||
/* project version */
|
||||
#define CJSON_VERSION_MAJOR 1
|
||||
#define CJSON_VERSION_MINOR 4
|
||||
#define CJSON_VERSION_PATCH 0
|
||||
#define CJSON_VERSION_PATCH 7
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -63,7 +63,7 @@ typedef struct cJSON
|
||||
|
||||
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
|
||||
char *valuestring;
|
||||
/* The item's number, if type==cJSON_Number */
|
||||
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
|
||||
int valueint;
|
||||
/* The item's number, if type==cJSON_Number */
|
||||
double valuedouble;
|
||||
@@ -88,7 +88,8 @@ typedef int cJSON_bool;
|
||||
/* 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
|
||||
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
|
||||
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
|
||||
|
||||
For *nix builds that support visibility attribute, you can define similar behavior by
|
||||
|
||||
@@ -102,11 +103,16 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
|
||||
|
||||
*/
|
||||
|
||||
/* export symbols by default, this is necessary for copy pasting the C and header file */
|
||||
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
|
||||
#define CJSON_EXPORT_SYMBOLS
|
||||
#endif
|
||||
|
||||
#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
|
||||
#elif defined(CJSON_IMPORT_SYMBOLS)
|
||||
#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall
|
||||
#endif
|
||||
#else /* !WIN32 */
|
||||
@@ -132,8 +138,9 @@ CJSON_PUBLIC(char *) cJSON_Print(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 */
|
||||
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. */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt);
|
||||
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
|
||||
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
|
||||
|
||||
@@ -142,7 +149,7 @@ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const 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. */
|
||||
|
||||
@@ -230,11 +230,11 @@ static void cJSONUtils_InplaceDecodePointerString(unsigned char *string)
|
||||
|
||||
for (; *string; (void)s2++, string++)
|
||||
{
|
||||
*s2 = (*string != '~')
|
||||
*s2 = (unsigned char) ((*string != '~')
|
||||
? (*string)
|
||||
: ((*(++string) == '0')
|
||||
? '~'
|
||||
: '/');
|
||||
: '/'));
|
||||
}
|
||||
|
||||
*s2 = '\0';
|
||||
@@ -468,7 +468,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
||||
cJSONUtils_InplaceDecodePointerString(childptr);
|
||||
|
||||
/* add, remove, replace, move, copy, test. */
|
||||
if (!parent)
|
||||
if ((parent == NULL) || (childptr == NULL))
|
||||
{
|
||||
/* Couldn't find object to add to. */
|
||||
free(parentptr);
|
||||
@@ -504,12 +504,7 @@ CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (patches == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cJSON_IsArray(patches))
|
||||
if (!cJSON_IsArray(patches))
|
||||
{
|
||||
/* malformed patches. */
|
||||
return 1;
|
||||
|
||||
@@ -56,7 +56,7 @@ static char *read_file(const char *filename)
|
||||
}
|
||||
|
||||
/* allocate content buffer */
|
||||
content = (char*)malloc((size_t)length + sizeof('\0'));
|
||||
content = (char*)malloc((size_t)length + sizeof(""));
|
||||
if (content == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
|
||||
4
test.c
4
test.c
@@ -53,8 +53,8 @@ static int print_preallocated(cJSON *root)
|
||||
out = cJSON_Print(root);
|
||||
|
||||
/* create buffer to succeed */
|
||||
/* the extra 64 bytes are in case a floating point value is printed */
|
||||
len = strlen(out) + 64;
|
||||
/* the extra 5 bytes are because of inaccuracies when reserving memory */
|
||||
len = strlen(out) + 5;
|
||||
buf = (char*)malloc(len);
|
||||
if (buf == NULL)
|
||||
{
|
||||
|
||||
@@ -2,14 +2,28 @@ if(ENABLE_CJSON_TEST)
|
||||
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")
|
||||
if (FLAG_SUPPORTED_Werror)
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error")
|
||||
else()
|
||||
target_compile_options(unity PRIVATE "-Wno-error")
|
||||
endif()
|
||||
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")
|
||||
if (FLAG_SUPPORTED_fvisibilityhidden)
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=default")
|
||||
else()
|
||||
target_compile_options(unity PRIVATE "-fvisibility=default")
|
||||
endif()
|
||||
endif()
|
||||
# Disable -fsanitize=float-divide-by-zero for Unity (GCC bug on x86 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80097)
|
||||
if (FLAG_SUPPORTED_fsanitizefloatdividebyzero AND (CMAKE_C_COMPILER_ID STREQUAL "GNU"))
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=float-divide-by-zero")
|
||||
else()
|
||||
target_compile_options(unity PRIVATE "-fno-sanitize=float-divide-by-zero")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#copy test files
|
||||
@@ -46,20 +60,17 @@ if(ENABLE_CJSON_TEST)
|
||||
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})
|
||||
add_executable("${unity_test}" "${unity_test}.c")
|
||||
target_link_libraries("${unity_test}" "${CJSON_LIB}" unity test-common)
|
||||
if(MEMORYCHECK_COMMAND)
|
||||
add_test(NAME "${unity_test}"
|
||||
COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "./${unity_test}")
|
||||
COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${unity_test}")
|
||||
else()
|
||||
add_test(NAME "${unity_test}"
|
||||
COMMAND "./${unity_test}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_dependencies(check ${unity_tests})
|
||||
endif()
|
||||
|
||||
@@ -70,7 +70,7 @@ CJSON_PUBLIC(char*) read_file(const char *filename)
|
||||
}
|
||||
|
||||
/* allocate content buffer */
|
||||
content = (char*)malloc((size_t)length + sizeof('\0'));
|
||||
content = (char*)malloc((size_t)length + sizeof(""));
|
||||
if (content == NULL)
|
||||
{
|
||||
goto cleanup;
|
||||
|
||||
@@ -50,7 +50,7 @@ static void print_number_should_print_negative_integers(void)
|
||||
{
|
||||
assert_print_number("-1", -1);
|
||||
assert_print_number("-32768", -32768);
|
||||
assert_print_number("-2147483648", -2147483648);
|
||||
assert_print_number("-2147483648", -2147483648.0);
|
||||
}
|
||||
|
||||
static void print_number_should_print_positive_integers(void)
|
||||
@@ -89,17 +89,11 @@ static void print_number_should_print_non_number(void)
|
||||
|
||||
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);
|
||||
TEST_ASSERT_EQUAL_INT(2, trim_trailing_zeroes((const unsigned char*)"10.00", (int)(sizeof("10.00") - 1), '.'));
|
||||
TEST_ASSERT_EQUAL_INT(0, trim_trailing_zeroes((const unsigned char*)".00", (int)(sizeof(".00") - 1), '.'));
|
||||
TEST_ASSERT_EQUAL_INT(0, trim_trailing_zeroes((const unsigned char*)"00", (int)(sizeof("00") - 1), '.'));
|
||||
TEST_ASSERT_EQUAL_INT(-1, trim_trailing_zeroes(NULL, 10, '.'));
|
||||
TEST_ASSERT_EQUAL_INT(-1, trim_trailing_zeroes((const unsigned char*)"", 0, '.'));
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
||||
Reference in New Issue
Block a user