Compare commits
205 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d348621ca9 | ||
|
|
744e47353a | ||
|
|
7795249dd4 | ||
|
|
324a6ac9a9 | ||
|
|
6ea4c01e4e | ||
|
|
9226e4ed8c | ||
|
|
7b6645794d | ||
|
|
4100379a04 | ||
|
|
2f6fc7f0f2 | ||
|
|
a1e1c208ff | ||
|
|
9bf4960cd5 | ||
|
|
488169faca | ||
|
|
9931900768 | ||
|
|
d2735278ed | ||
|
|
8e84db4c4e | ||
|
|
8e357f825b | ||
|
|
2e5171d8d6 | ||
|
|
c8ca78a3cc | ||
|
|
0b13220419 | ||
|
|
23f027139e | ||
|
|
60c3b0a571 | ||
|
|
857c037ccc | ||
|
|
3fb9d929e1 | ||
|
|
cf97c6f066 | ||
|
|
1ef4deec06 | ||
|
|
4578d3a9e1 | ||
|
|
b95a4c56b0 | ||
|
|
7db005e028 | ||
|
|
1fc755ac09 | ||
|
|
a82449fa3e | ||
|
|
2a6299d904 | ||
|
|
43f471bff1 | ||
|
|
7103844037 | ||
|
|
3442b36672 | ||
|
|
cb4661cd91 | ||
|
|
a65abf2f4f | ||
|
|
3999b12848 | ||
|
|
39853e5148 | ||
|
|
ff0dabc72e | ||
|
|
5d55c6c2ee | ||
|
|
23e4fbc639 | ||
|
|
65578af8cc | ||
|
|
f12cd7b701 | ||
|
|
97cf1d84e4 | ||
|
|
983bb2b4d6 | ||
|
|
4e114c1f31 | ||
|
|
8943c73345 | ||
|
|
af56a146fd | ||
|
|
131966f748 | ||
|
|
bd7cbe9776 | ||
|
|
54d6b8016e | ||
|
|
31c7880fab | ||
|
|
34e102d0dc | ||
|
|
4790c3c8f5 | ||
|
|
6b35f1c5bc | ||
|
|
3ece4c893c | ||
|
|
fa28d82f2e | ||
|
|
1be85ff26d | ||
|
|
d92c0de7e8 | ||
|
|
ae7a7a1d0c | ||
|
|
0586a6c437 | ||
|
|
9034a9cd0b | ||
|
|
b0e7195a74 | ||
|
|
e8077d0150 | ||
|
|
2955fe5ec4 | ||
|
|
895b9ad344 | ||
|
|
f790e17b6c | ||
|
|
2c97086b97 | ||
|
|
ada2169183 | ||
|
|
cc78050ff4 | ||
|
|
74b2f03837 | ||
|
|
fa8b454552 | ||
|
|
2d4ad84192 | ||
|
|
ea532cdd61 | ||
|
|
4e3335618f | ||
|
|
69bc9ccc20 | ||
|
|
ea3a6dcd69 | ||
|
|
c06d8264d0 | ||
|
|
1f970e7db3 | ||
|
|
98ecc0245a | ||
|
|
6434d8643e | ||
|
|
51f6b4c07e | ||
|
|
d31fdefa38 | ||
|
|
8badd19b64 | ||
|
|
500a9db81b | ||
|
|
95368da1a1 | ||
|
|
f3b6ad15f0 | ||
|
|
446ff0d6cc | ||
|
|
6a848fce32 | ||
|
|
c64854b26e | ||
|
|
533ff8a783 | ||
|
|
4755aea837 | ||
|
|
4454731775 | ||
|
|
326f1f5ed5 | ||
|
|
bb059dc2e1 | ||
|
|
de99175cd0 | ||
|
|
a417b183c6 | ||
|
|
f589f81a42 | ||
|
|
49a0ede475 | ||
|
|
73b0e739d0 | ||
|
|
a0fdf115be | ||
|
|
6b728982f2 | ||
|
|
f00060af44 | ||
|
|
ec8d2f9c2e | ||
|
|
18b7113b49 | ||
|
|
18dad60035 | ||
|
|
66d0a1793f | ||
|
|
a8dbf6d878 | ||
|
|
60fb788aa5 | ||
|
|
bcc91ecbc3 | ||
|
|
26772a8ef7 | ||
|
|
dc56e24f7f | ||
|
|
f31ff795bd | ||
|
|
e52b212dbf | ||
|
|
2de7d04aaf | ||
|
|
ae49da2b61 | ||
|
|
a3154a36f1 | ||
|
|
189b51c5da | ||
|
|
709c3dcf32 | ||
|
|
c61573f1af | ||
|
|
20cffa37a8 | ||
|
|
cf0d87a095 | ||
|
|
e750194cb1 | ||
|
|
e13f11ba79 | ||
|
|
8872b1429a | ||
|
|
bd1a375028 | ||
|
|
b6da0d6565 | ||
|
|
166c814cda | ||
|
|
c680faea56 | ||
|
|
2d6db59c7b | ||
|
|
e6bc5d16e6 | ||
|
|
2691e142f4 | ||
|
|
f7f175fdf2 | ||
|
|
9d766f07a7 | ||
|
|
85ceadb4b4 | ||
|
|
110f184d18 | ||
|
|
c9e8a68b00 | ||
|
|
16f56300e4 | ||
|
|
5fe80a94b6 | ||
|
|
3c8935676a | ||
|
|
b93fd34044 | ||
|
|
687b1a2fe1 | ||
|
|
08d2bc766a | ||
|
|
465352fb99 | ||
|
|
19ff92da79 | ||
|
|
3a4cfa84c3 | ||
|
|
62bc2e3432 | ||
|
|
359567fdde | ||
|
|
0b5a7abf48 | ||
|
|
93688cbe72 | ||
|
|
6b249213dd | ||
|
|
09ebae8149 | ||
|
|
a43fa56a63 | ||
|
|
9a970b9ff6 | ||
|
|
5a52eaddfd | ||
|
|
add86a6be8 | ||
|
|
c69134d017 | ||
|
|
563d861f92 | ||
|
|
6820448db5 | ||
|
|
d44b594ab3 | ||
|
|
f110bd2e58 | ||
|
|
5cd1dabb30 | ||
|
|
d606cbbc64 | ||
|
|
be749d7efa | ||
|
|
eaec82c3c5 | ||
|
|
cb1df2f88c | ||
|
|
2c914c073d | ||
|
|
4917024741 | ||
|
|
a3fadd44d1 | ||
|
|
feb05fb2fd | ||
|
|
26f38f4782 | ||
|
|
8e742e4869 | ||
|
|
543ab5d08a | ||
|
|
e2162adeed | ||
|
|
08103f048e | ||
|
|
ace800e444 | ||
|
|
00544a4a74 | ||
|
|
3550a5553d | ||
|
|
d9fe34bade | ||
|
|
f25b8448e4 | ||
|
|
ad2cb5b7ea | ||
|
|
f32703a7a1 | ||
|
|
86234db095 | ||
|
|
af5b4911de | ||
|
|
787d651e81 | ||
|
|
1571a3ebe4 | ||
|
|
0d5ecc11b6 | ||
|
|
529ec06abb | ||
|
|
3349978268 | ||
|
|
cbc05de76f | ||
|
|
7996a4a2ee | ||
|
|
ed8fefc9ca | ||
|
|
e6869c2e03 | ||
|
|
0e0c463491 | ||
|
|
2336a0348d | ||
|
|
5d50f4efe1 | ||
|
|
8abf110750 | ||
|
|
d26a42af8d | ||
|
|
6f264b5d0c | ||
|
|
5da9edc8b1 | ||
|
|
22a7d04fa0 | ||
|
|
a559eac472 | ||
|
|
d514bb866e | ||
|
|
27caa364b0 | ||
|
|
f47271f455 |
23
.editorconfig
Normal file
23
.editorconfig
Normal file
@@ -0,0 +1,23 @@
|
||||
root = true
|
||||
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
indent_size = unset
|
||||
|
||||
# ignore external repositories and test inputs
|
||||
[tests/{unity,json-patch-tests,inputs}/*]
|
||||
indent_style = unset
|
||||
indent_size = unset
|
||||
end_of_line = unset
|
||||
charset = unset
|
||||
trim_trailing_whitespace = unset
|
||||
insert_final_newline = unset
|
||||
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
* text=auto
|
||||
/tests/inputs/* text eol=lf
|
||||
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.github export-ignore
|
||||
.editorconfig export-ignore
|
||||
.travis.yml export-ignore
|
||||
|
||||
# Linguist incorrectly identified the headers as C++, manually override this.
|
||||
*.h linguist-language=C
|
||||
102
.github/workflows/CI.yml
vendored
Normal file
102
.github/workflows/CI.yml
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'LICENSE'
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'LICENSE'
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, 'ci skip')"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mem_check:
|
||||
- ENABLE_VALGRIND
|
||||
- ENABLE_SANITIZERS
|
||||
- NONE_MEM_CHECK
|
||||
compiler:
|
||||
- GCC
|
||||
- CLANG
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install clang-8 valgrind
|
||||
- name: build and test
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ matrix.mem_check }}" == "ENABLE_VALGRIND" ]; then
|
||||
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=ON -DENABLE_SAFE_STACK=ON -DENABLE_SANITIZERS=OFF"
|
||||
elif [ "${{ matrix.mem_check }}" == "ENABLE_SANITIZERS" ]; then
|
||||
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=ON"
|
||||
else
|
||||
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=OFF"
|
||||
fi
|
||||
if [ "${{ matrix.compiler }}" == "GCC" ]; then
|
||||
export CC=gcc
|
||||
else
|
||||
export CC=clang
|
||||
fi
|
||||
#run build and test
|
||||
JOBS=20
|
||||
export CTEST_PARALLEL_LEVEL=$JOBS
|
||||
export CTEST_OUTPUT_ON_FAILURE=1
|
||||
mkdir -p build
|
||||
cd build
|
||||
echo [cmake]: cmake .. $EVENT_CMAKE_OPTIONS
|
||||
cmake .. $EVENT_CMAKE_OPTIONS || (rm -rf * && cmake .. $EVENT_CMAKE_OPTIONS)
|
||||
cmake --build .
|
||||
make
|
||||
make test
|
||||
|
||||
macos:
|
||||
runs-on: macos-latest
|
||||
if: "!contains(github.event.head_commit.message, 'ci skip')"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mem_check:
|
||||
- ENABLE_VALGRIND
|
||||
- ENABLE_SANITIZERS
|
||||
- NONE_MEM_CHECK
|
||||
compiler:
|
||||
- GCC
|
||||
- CLANG
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: build and test
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ matrix.mem_check }}" == "ENABLE_VALGRIND" ]; then
|
||||
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=ON -DENABLE_SAFE_STACK=ON -DENABLE_SANITIZERS=OFF"
|
||||
elif [ "${{ matrix.mem_check }}" == "ENABLE_SANITIZERS" ]; then
|
||||
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=ON"
|
||||
else
|
||||
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=OFF"
|
||||
fi
|
||||
if [ "${{ matrix.compiler }}" == "GCC" ]; then
|
||||
export CC=gcc
|
||||
else
|
||||
export CC=clang
|
||||
fi
|
||||
#run build and test
|
||||
JOBS=20
|
||||
export CTEST_PARALLEL_LEVEL=$JOBS
|
||||
export CTEST_OUTPUT_ON_FAILURE=1
|
||||
mkdir -p build
|
||||
cd build
|
||||
echo [cmake]: cmake .. $EVENT_CMAKE_OPTIONS
|
||||
cmake .. $EVENT_CMAKE_OPTIONS || (rm -rf * && cmake .. $EVENT_CMAKE_OPTIONS)
|
||||
cmake --build .
|
||||
make
|
||||
make test
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -14,3 +14,5 @@ libcjson.so.*
|
||||
libcjson_utils.so.*
|
||||
*.orig
|
||||
.vscode
|
||||
.idea
|
||||
cmake-build-debug
|
||||
|
||||
402
CHANGELOG.md
402
CHANGELOG.md
@@ -1,40 +1,153 @@
|
||||
1.7.1
|
||||
1.7.15 (Aug 25, 2021)
|
||||
======
|
||||
Fixes:
|
||||
------
|
||||
* Fix potential core dumped for strrchr, see [#546](https://github.com/DaveGamble/cJSON/pull/546)
|
||||
* Fix null pointer crash in cJSON_CreateXxArray, see [#538](https://github.com/DaveGamble/cJSON/pull/538)
|
||||
* Fix several null pointer problems on allocation failure, see [#526](https://github.com/DaveGamble/cJSON/pull/526)
|
||||
* Fix a possible dereference of null pointer, see [#519](https://github.com/DaveGamble/cJSON/pull/519)
|
||||
* Fix windows build failure about defining nan, see [#518](https://github.com/DaveGamble/cJSON/pull/518)
|
||||
|
||||
1.7.14 (Sep 3, 2020)
|
||||
======
|
||||
Fixes:
|
||||
------
|
||||
* optimize the way to find tail node, see [#503](https://github.com/DaveGamble/cJSON/pull/503)
|
||||
* Fix WError error on macosx because NAN is a float. Thanks @sappo, see [#484](https://github.com/DaveGamble/cJSON/pull/484)
|
||||
* Fix some bugs in detach and replace. Thanks @miaoerduo, see [#456](https://github.com/DaveGamble/cJSON/pull/456)
|
||||
|
||||
1.7.13 (Apr 2, 2020)
|
||||
======
|
||||
Features:
|
||||
---------
|
||||
* add new API of cJSON_ParseWithLength without breaking changes. Thanks @caglarivriz, see [#358](https://github.com/DaveGamble/cJSON/pull/358)
|
||||
* add new API of cJSON_GetNumberValue. Thanks @Intuition, see[#385](https://github.com/DaveGamble/cJSON/pull/385)
|
||||
* add uninstall target function for CMake. See [#402](https://github.com/DaveGamble/cJSON/pull/402)
|
||||
* Improve performance of adding item to array. Thanks @xiaomianhehe, see [#430](https://github.com/DaveGamble/cJSON/pull/430), [#448](https://github.com/DaveGamble/cJSON/pull/448)
|
||||
* add new API of cJSON_SetValuestring, for changing the valuestring safely. See [#451](https://github.com/DaveGamble/cJSON/pull/451)
|
||||
* add return value for cJSON_AddItemTo... and cJSON_ReplaceItem... (check if the operation successful). See [#453](https://github.com/DaveGamble/cJSON/pull/453)
|
||||
|
||||
Fixes:
|
||||
------
|
||||
* Fix clang -Wfloat-equal warning. Thanks @paulmalovanyi, see [#368](https://github.com/DaveGamble/cJSON/pull/368)
|
||||
* Fix make failed in mac os. See [#405](https://github.com/DaveGamble/cJSON/pull/405)
|
||||
* Fix memory leak in cJSONUtils_FindPointerFromObjectTo. Thanks @andywolk for reporting, see [#414](https://github.com/DaveGamble/cJSON/issues/414)
|
||||
* Fix bug in encode_string_as_pointer. Thanks @AIChangJiang for reporting, see [#439](https://github.com/DaveGamble/cJSON/issues/439)
|
||||
|
||||
1.7.12 (May 17, 2019)
|
||||
======
|
||||
Fixes:
|
||||
------
|
||||
* Fix infinite loop in `cJSON_Minify` (potential Denial of Service). Thanks @Alanscut for reporting, see [#354](https://github.com/DaveGamble/cJSON/issues/354)
|
||||
* Fix link error for Visual Studio. Thanks @tan-wei, see [#352](https://github.com/DaveGamble/cJSON/pull/352).
|
||||
* Undefine `true` and `false` for `cJSON_Utils` before redefining them. Thanks @raiden00pl, see [#347](https://github.com/DaveGamble/cJSON/pull/347).
|
||||
|
||||
1.7.11 (Apr 15, 2019)
|
||||
======
|
||||
Fixes:
|
||||
------
|
||||
* Fix a bug where cJSON_Minify could overflow it's buffer, both reading and writing. This is a security issue, see [#338](https://github.com/DaveGamble/cJSON/issues/338). Big thanks @bigric3 for reporting.
|
||||
* Unset `true` and `false` macros before setting them if they exist. See [#339](https://github.com/DaveGamble/cJSON/issues/339), thanks @raiden00pl for reporting
|
||||
|
||||
1.7.10 (Dec 21, 2018)
|
||||
======
|
||||
Fixes:
|
||||
------
|
||||
* Fix package config file for `libcjson`. Thanks @shiluotang for reporting [#321](https://github.com/DaveGamble/cJSON/issues/321)
|
||||
* Correctly split lists in `cJSON_Utils`'s merge sort. Thanks @andysCaplin for the fix [#322](https://github.com/DaveGamble/cJSON/issues/322)
|
||||
|
||||
1.7.9 (Dec 16, 2018)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fixed an Off-By-One error that could lead to an out of bounds write. Thanks @liuyunbin for reporting (see #230)
|
||||
* Fixed two errors with buffered printing. Thanks @liuyunbin for reporting (see #230)
|
||||
* Fix a bug where `cJSON_GetObjectItemCaseSensitive` would pass a nullpointer to `strcmp` when called on an array, see [#315](https://github.com/DaveGamble/cJSON/issues/315). Thanks @yuweol for reporting.
|
||||
* Fix error in `cJSON_Utils` where the case sensitivity was not respected, see [#317](https://github.com/DaveGamble/cJSON/pull/317). Thanks @yuta-oxo for fixing.
|
||||
* Fix some warnings detected by the Visual Studio Static Analyzer, see [#307](https://github.com/DaveGamble/cJSON/pull/307). Thanks @bnason-nf
|
||||
|
||||
1.7.0
|
||||
1.7.8 (Sep 22, 2018)
|
||||
======
|
||||
Fixes:
|
||||
------
|
||||
* cJSON now works with the `__stdcall` calling convention on Windows, see [#295](https://github.com/DaveGamble/cJSON/pull/295), thanks @zhindes for contributing
|
||||
|
||||
1.7.7 (May 22, 2018)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix a memory leak when realloc fails, see [#267](https://github.com/DaveGamble/cJSON/issues/267), thanks @AlfieDeng for reporting
|
||||
* Fix a typo in the header file, see [#266](https://github.com/DaveGamble/cJSON/pull/266), thanks @zhaozhixu
|
||||
|
||||
1.7.6 (Apr 13, 2018)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Add `SONAME` to the ELF files built by the Makefile, see [#252](https://github.com/DaveGamble/cJSON/issues/252), thanks @YanhaoMo for reporting
|
||||
* Add include guards and `extern "C"` to `cJSON_Utils.h`, see [#256](https://github.com/DaveGamble/cJSON/issues/256), thanks @daschfg for reporting
|
||||
|
||||
Other changes:
|
||||
* Mark the Makefile as deprecated in the README.
|
||||
|
||||
1.7.5 (Mar 23, 2018)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix a bug in the JSON Patch implementation of `cJSON Utils`, see [#251](https://github.com/DaveGamble/cJSON/pull/251), thanks @bobkocisko.
|
||||
|
||||
1.7.4 (Mar 3, 2018)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix potential use after free if the `string` parameter to `cJSON_AddItemToObject` is an alias of the `string` property of the object that is added,see [#248](https://github.com/DaveGamble/cJSON/issues/248). Thanks @hhallen for reporting.
|
||||
|
||||
1.7.3 (Feb 8, 2018)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix potential double free, thanks @projectgus for reporting [#241](https://github.com/DaveGamble/cJSON/issues/241)
|
||||
|
||||
1.7.2 (Feb 6, 2018)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix the use of GNUInstallDirs variables and the pkgconfig file. Thanks @zeerd for reporting [#240](https://github.com/DaveGamble/cJSON/pull/240)
|
||||
|
||||
1.7.1 (Jan 10, 2018)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fixed an Off-By-One error that could lead to an out of bounds write. Thanks @liuyunbin for reporting [#230](https://github.com/DaveGamble/cJSON/issues/230)
|
||||
* Fixed two errors with buffered printing. Thanks @liuyunbin for reporting [#230](https://github.com/DaveGamble/cJSON/issues/230)
|
||||
|
||||
1.7.0 (Dec 31, 2017)
|
||||
=====
|
||||
Features:
|
||||
---------
|
||||
* Large rewrite of the documentation, see #215
|
||||
* Large rewrite of the documentation, see [#215](https://github.com/DaveGamble/cJSON/pull/215)
|
||||
* Added the `cJSON_GetStringValue` function
|
||||
* Added the `cJSON_CreateStringReference` function
|
||||
* Added the `cJSON_CreateArrayReference` function
|
||||
* Added the `cJSON_CreateObjectReference` function
|
||||
* The `cJSON_Add...ToObject` macros are now functions that return a pointer to the added item, see #226
|
||||
* The `cJSON_Add...ToObject` macros are now functions that return a pointer to the added item, see [#226](https://github.com/DaveGamble/cJSON/pull/226)
|
||||
|
||||
Fixes:
|
||||
------
|
||||
* Fix a problem with `GNUInstallDirs` in the CMakeLists.txt, thanks @yangfl, see #210
|
||||
* Fix linking the tests when building as static library, see #213
|
||||
* New overrides for the CMake option `BUILD_SHARED_LIBS`, see #207
|
||||
* Fix a problem with `GNUInstallDirs` in the CMakeLists.txt, thanks @yangfl, see [#210](https://github.com/DaveGamble/cJSON/pull/210)
|
||||
* Fix linking the tests when building as static library, see [#213](https://github.com/DaveGamble/cJSON/issues/213)
|
||||
* New overrides for the CMake option `BUILD_SHARED_LIBS`, see [#207](https://github.com/DaveGamble/cJSON/issues/207)
|
||||
|
||||
Other Changes:
|
||||
--------------
|
||||
* Readme: Explain how to include cJSON, see #211
|
||||
* Removed some trailing spaces in the code, thanks @yangfl, see#212
|
||||
* Readme: Explain how to include cJSON, see [#211](https://github.com/DaveGamble/cJSON/pull/211)
|
||||
* Removed some trailing spaces in the code, thanks @yangfl, see [#212](https://github.com/DaveGamble/cJSON/pull/212)
|
||||
* Updated [Unity](https://github.com/ThrowTheSwitch/Unity) and [json-patch-tests](https://github.com/json-patch/json-patch-tests)
|
||||
|
||||
1.6.0
|
||||
1.6.0 (Oct 9, 2017)
|
||||
=====
|
||||
Features:
|
||||
---------
|
||||
* You can now build cJSON as both shared and static library at once with CMake using `-DBUILD_SHARED_AND_STATIC_LIBS=On`, see #178
|
||||
* UTF-8 byte order marks are now ignored, see #184
|
||||
* Locales can now be disabled with the option `-DENABLE_LOCALES=Off`, see #202, thanks @Casperinous
|
||||
* You can now build cJSON as both shared and static library at once with CMake using `-DBUILD_SHARED_AND_STATIC_LIBS=On`, see [#178](https://github.com/DaveGamble/cJSON/issues/178)
|
||||
* UTF-8 byte order marks are now ignored, see [#184](https://github.com/DaveGamble/cJSON/issues/184)
|
||||
* Locales can now be disabled with the option `-DENABLE_LOCALES=Off`, see [#202](https://github.com/DaveGamble/cJSON/issues/202), thanks @Casperinous
|
||||
* Better support for MSVC and Visual Studio
|
||||
|
||||
Other Changes:
|
||||
@@ -43,75 +156,78 @@ Other Changes:
|
||||
* More number printing tests.
|
||||
* Continuous integration testing with AppVeyor (semi automatic at this point), thanks @simon-p-r
|
||||
|
||||
1.5.9
|
||||
=====
|
||||
* Set the global error pointer even if `return_parse_end` is passed to `cJSON_ParseWithOpts`. See #200, thanks @rmallins
|
||||
|
||||
1.5.8
|
||||
=====
|
||||
* Fix `make test` in the Makefile, thanks @YanhaoMo for reporting this (#195)
|
||||
|
||||
1.5.7
|
||||
1.5.9 (Sep 8, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix a bug where realloc failing would return a pointer to an invalid memory address. This is a security issue as it could potentially be used by an attacker to write to arbitrary memory addresses. (see #189), fixed in (954d61e5e7cb9dc6c480fc28ac1cdceca07dd5bd), big thanks @timothyjohncarney for reporting this issue
|
||||
* Fix a spelling mistake in the AFL fuzzer dictionary (#185), thanks @jwilk
|
||||
* Set the global error pointer even if `return_parse_end` is passed to `cJSON_ParseWithOpts`, see [#200](https://github.com/DaveGamble/cJSON/pull/200), thanks @rmallins
|
||||
|
||||
1.5.6
|
||||
1.5.8 (Aug 21, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Make cJSON a lot more tolerant about passing NULL pointers to its functions, it should now fail safely instead of dereferencing the pointer. (#183) Thanks @msichal for reporting #182
|
||||
* Fix `make test` in the Makefile, thanks @YanhaoMo for reporting this [#195](https://github.com/DaveGamble/cJSON/issues/195)
|
||||
|
||||
1.5.5
|
||||
1.5.7 (Jul 13, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix pointers to nested arrays in cJSON_Utils (9abe75e072050f34732a7169740989a082b65134)
|
||||
* Fix an error with case sensitivity handling in cJSON_Utils (b9cc911831b0b3e1bb72f142389428e59f882b38)
|
||||
* Fix cJSON_Compare for arrays that are prefixes of the other and objects that are a subset of the other (03ba72faec115160d1f3aea5582d9b6af5d3e473) See #180, thanks @zhengqb for reporting
|
||||
* Fix a bug where realloc failing would return a pointer to an invalid memory address. This is a security issue as it could potentially be used by an attacker to write to arbitrary memory addresses, see [#189](https://github.com/DaveGamble/cJSON/issues/189), fixed in [954d61e](https://github.com/DaveGamble/cJSON/commit/954d61e5e7cb9dc6c480fc28ac1cdceca07dd5bd), big thanks @timothyjohncarney for reporting this issue
|
||||
* Fix a spelling mistake in the AFL fuzzer dictionary, see [#185](https://github.com/DaveGamble/cJSON/pull/185), thanks @jwilk
|
||||
|
||||
1.5.4
|
||||
1.5.6 (Jun 28, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix build with GCC 7.1.1 and optimization level `-O2` (bfbd8fe0d85f1dd21e508748fc10fc4c27cc51be)
|
||||
* Make cJSON a lot more tolerant about passing NULL pointers to its functions, it should now fail safely instead of dereferencing the pointer, see [#183](https://github.com/DaveGamble/cJSON/pull/183). Thanks @msichal for reporting [#182](https://github.com/DaveGamble/cJSON/issues/182)
|
||||
|
||||
1.5.5 (Jun 15, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix pointers to nested arrays in cJSON_Utils, see [9abe](https://github.com/DaveGamble/cJSON/commit/9abe75e072050f34732a7169740989a082b65134)
|
||||
* Fix an error with case sensitivity handling in cJSON_Utils, see [b9cc911](https://github.com/DaveGamble/cJSON/commit/b9cc911831b0b3e1bb72f142389428e59f882b38)
|
||||
* Fix cJSON_Compare for arrays that are prefixes of the other and objects that are a subset of the other, see [03ba72f](https://github.com/DaveGamble/cJSON/commit/03ba72faec115160d1f3aea5582d9b6af5d3e473) and [#180](https://github.com/DaveGamble/cJSON/issues/180), thanks @zhengqb for reporting
|
||||
|
||||
1.5.4 (Jun 5, 2017)
|
||||
======
|
||||
Fixes:
|
||||
------
|
||||
* Fix build with GCC 7.1.1 and optimization level `-O2`, see [bfbd8fe](https://github.com/DaveGamble/cJSON/commit/bfbd8fe0d85f1dd21e508748fc10fc4c27cc51be)
|
||||
|
||||
Other Changes:
|
||||
--------------
|
||||
* Update [Unity](https://github.com/ThrowTheSwitch/Unity) to 3b69beaa58efc41bbbef70a32a46893cae02719d
|
||||
|
||||
1.5.3
|
||||
1.5.3 (May 23, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix `cJSON_ReplaceItemInObject` not keeping the name of an item (#174)
|
||||
* Fix `cJSON_ReplaceItemInObject` not keeping the name of an item, see [#174](https://github.com/DaveGamble/cJSON/issues/174)
|
||||
|
||||
1.5.2
|
||||
1.5.2 (May 10, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix a reading buffer overflow in `parse_string` (a167d9e381e5c84bc03de4e261757b031c0c690d)
|
||||
* Fix compiling with -Wcomma (186cce3ece6ce6dfcb58ac8b2a63f7846c3493ad)
|
||||
* Remove leftover attribute from tests (b537ca70a35680db66f1f5b8b437f7114daa699a)
|
||||
* Fix a reading buffer overflow in `parse_string`, see [a167d9e](https://github.com/DaveGamble/cJSON/commit/a167d9e381e5c84bc03de4e261757b031c0c690d)
|
||||
* Fix compiling with -Wcomma, see [186cce3](https://github.com/DaveGamble/cJSON/commit/186cce3ece6ce6dfcb58ac8b2a63f7846c3493ad)
|
||||
* Remove leftover attribute from tests, see [b537ca7](https://github.com/DaveGamble/cJSON/commit/b537ca70a35680db66f1f5b8b437f7114daa699a)
|
||||
|
||||
1.5.1
|
||||
1.5.1 (May 6, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Add gcc version guard to the Makefile (#164), thanks @juvasquezg
|
||||
* Fix incorrect free in `cJSON_Utils` if custom memory allocator is used (#166), thanks @prefetchnta
|
||||
* Add gcc version guard to the Makefile, see [#164](https://github.com/DaveGamble/cJSON/pull/164), thanks @juvasquezg
|
||||
* Fix incorrect free in `cJSON_Utils` if custom memory allocator is used, see [#166](https://github.com/DaveGamble/cJSON/pull/166), thanks @prefetchnta
|
||||
|
||||
1.5.0
|
||||
1.5.0 (May 2, 2017)
|
||||
=====
|
||||
Features:
|
||||
---------
|
||||
* cJSON finally prints numbers without losing precision (#153) thanks @DeboraG
|
||||
* `cJSON_Compare` recursively checks if two cJSON items contain the same values (#148)
|
||||
* Provide case sensitive versions of every function where it matters (#158, #159)
|
||||
* cJSON finally prints numbers without losing precision, see [#153](https://github.com/DaveGamble/cJSON/pull/153), thanks @DeboraG
|
||||
* `cJSON_Compare` recursively checks if two cJSON items contain the same values, see [#148](https://github.com/DaveGamble/cJSON/pull/148)
|
||||
* Provide case sensitive versions of every function where it matters, see [#158](https://github.com/DaveGamble/cJSON/pull/158) and [#159](https://github.com/DaveGamble/cJSON/pull/159)
|
||||
* Added `cJSON_ReplaceItemViaPointer` and `cJSON_DetachItemViaPointer`
|
||||
* Added `cJSON_free` and `cJSON_malloc` that expose the internal configured memory allocators. (02a05eea4e6ba41811f130b322660bea8918e1a0)
|
||||
* Added `cJSON_free` and `cJSON_malloc` that expose the internal configured memory allocators. see [02a05ee](https://github.com/DaveGamble/cJSON/commit/02a05eea4e6ba41811f130b322660bea8918e1a0)
|
||||
|
||||
|
||||
Enhancements:
|
||||
@@ -125,7 +241,7 @@ Enhancements:
|
||||
|
||||
Fixes:
|
||||
------
|
||||
* Fix some warnings with the Microsoft compiler (#139) thanks @PawelWMS
|
||||
* Fix some warnings with the Microsoft compiler, see [#139](https://github.com/DaveGamble/cJSON/pull/139), thanks @PawelWMS
|
||||
* Fix several bugs in cJSON_Utils, mostly found with [json-patch-tests](https://github.com/json-patch/json-patch-tests)
|
||||
* Prevent a stack overflow by specifying a maximum nesting depth `CJSON_NESTING_LIMIT`
|
||||
|
||||
@@ -133,180 +249,180 @@ Other Changes:
|
||||
--------------
|
||||
* Move generated files in the `library_config` subdirectory.
|
||||
|
||||
1.4.7
|
||||
1.4.7 (Apr 19, 2017)
|
||||
=====
|
||||
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
|
||||
* Fix `cJSONUtils_ApplyPatches`, it was completely broken and apparently nobody noticed (or at least reported it), see [075a06f](https://github.com/DaveGamble/cJSON/commit/075a06f40bdc4f836c7dd7cad690d253a57cfc50)
|
||||
* Fix inconsistent prototype for `cJSON_GetObjectItemCaseSensitive`, see [51d3df6](https://github.com/DaveGamble/cJSON/commit/51d3df6c9f7b56b860c8fb24abe7bab255cd4fa9), thanks @PawelWMS
|
||||
|
||||
1.4.6
|
||||
1.4.6 (Apr 9, 2017)
|
||||
=====
|
||||
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
|
||||
* Fix overflow detection in `ensure`, see [2683d4d](https://github.com/DaveGamble/cJSON/commit/2683d4d9873df87c4bdccc523903ddd78d1ad250)
|
||||
* Fix a potential null pointer dereference in cJSON_Utils, see [795c3ac](https://github.com/DaveGamble/cJSON/commit/795c3acabed25c9672006b2c0f40be8845064827)
|
||||
* Replace incorrect `sizeof('\0')` with `sizeof("")`, see [84237ff](https://github.com/DaveGamble/cJSON/commit/84237ff48e69825c94261c624eb0376d0c328139)
|
||||
* Add caveats section to the README, see [50b3c30](https://github.com/DaveGamble/cJSON/commit/50b3c30dfa89830f8f477ce33713500740ac3b79)
|
||||
* Make cJSON locale independent, see [#146](https://github.com/DaveGamble/cJSON/pull/146), Thanks @peterh for reporting
|
||||
* Fix compiling without CMake with MSVC, see [#147](https://github.com/DaveGamble/cJSON/pull/147), Thanks @dertuxmalwieder for reporting
|
||||
|
||||
1.4.5
|
||||
1.4.5 (Mar 28, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
* Fix bug in `cJSON_SetNumberHelper`, thanks @mmkeeper (#138 ef34500693e8c4a2849d41a4bd66fd19c9ec46c2)
|
||||
* Fix bug in `cJSON_SetNumberHelper`, thanks @mmkeeper, see [#138](https://github.com/DaveGamble/cJSON/issues/138) and [ef34500](https://github.com/DaveGamble/cJSON/commit/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
|
||||
1.4.4 (Mar 24, 2017)
|
||||
=====
|
||||
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)
|
||||
------
|
||||
* Fix a theoretical integer overflow, (not sure if it is possible on actual hardware), see [e58f7ec](https://github.com/DaveGamble/cJSON/commit/e58f7ec027d00b7cdcbf63e518c1b5268b29b3da)
|
||||
* Fix an off by one error, see [cc84a44](https://github.com/DaveGamble/cJSON/commit/cc84a446be20cc283bafdc4d94c050ba1111ac02), thanks @gatzka
|
||||
* Double check the offset of the print buffer in `ensure`, see [1934059](https://github.com/DaveGamble/cJSON/commit/1934059554b9a0971e00f79e96900f422cfdd114)
|
||||
|
||||
Improvements:
|
||||
-------------
|
||||
* Add a note in the header about required buffer size when using `cJSON_PrintPreallocated` (4bfb88009342fb568295a7f6dc4b7fee74fbf022)
|
||||
* Add a note in the header about required buffer size when using `cJSON_PrintPreallocated`, see [4bfb8800](https://github.com/DaveGamble/cJSON/commit/4bfb88009342fb568295a7f6dc4b7fee74fbf022)
|
||||
|
||||
1.4.3
|
||||
1.4.3 (Mar 19, 2017)
|
||||
=====
|
||||
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
|
||||
* Fix compilation of the tests on 32 bit PowerPC and potentially other systems, see [4ec6e76](https://github.com/DaveGamble/cJSON/commit/4ec6e76ea2eec16f54b58e8c95b4c734e59481e4)
|
||||
* Fix compilation with old GCC compilers (4.3+ were tested), see [227d33](https://github.com/DaveGamble/cJSON/commit/227d3398d6b967879761ebe02c1b63dbd6ea6e0d), [466eb8e](https://github.com/DaveGamble/cJSON/commit/466eb8e3f8a65080f2b3ca4a79ab7b72bd539dba), see also [#126](https://github.com/DaveGamble/cJSON/issues/126)
|
||||
|
||||
1.4.2
|
||||
1.4.2 (Mar 16, 2017)
|
||||
=====
|
||||
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)
|
||||
* Fix minimum required cmake version, see [30e1e7a](https://github.com/DaveGamble/cJSON/commit/30e1e7af7c63db9b55f5a3cda977a6c032f0b132)
|
||||
* Fix detection of supported compiler flags, see [76e5296](https://github.com/DaveGamble/cJSON/commit/76e5296d0d05ceb3018a9901639e0e171b44a557)
|
||||
* Run `cJSON_test` and `cJSON_test_utils` along with unity tests, see [c597601](https://github.com/DaveGamble/cJSON/commit/c597601cf151a757dcf800548f18034d4ddfe2cb)
|
||||
|
||||
1.4.1
|
||||
1.4.1 (Mar 16, 2017)
|
||||
=====
|
||||
Fix: Make `print_number` abort with a failure in out of memory situations (cf1842dc6f64c49451a022308b4415e4d468be0a)
|
||||
Fixes:
|
||||
------
|
||||
* Make `print_number` abort with a failure in out of memory situations, see [cf1842](https://github.com/DaveGamble/cJSON/commit/cf1842dc6f64c49451a022308b4415e4d468be0a)
|
||||
|
||||
1.4.0
|
||||
1.4.0 (Mar 4, 2017)
|
||||
=====
|
||||
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)
|
||||
* Functions to check the type of an item, see [#120](https://github.com/DaveGamble/cJSON/pull/120)
|
||||
* Use dllexport on windows and fvisibility on Unix systems for public functions, see [#116](https://github.com/DaveGamble/cJSON/pull/116), thanks @mjerris
|
||||
* Remove trailing zeroes from printed numbers, see [#123](https://github.com/DaveGamble/cJSON/pull/123)
|
||||
* Expose the internal boolean type `cJSON_bool` in the header, see [2d3520e](https://github.com/DaveGamble/cJSON/commit/2d3520e0b9d0eb870e8886e8a21c571eeddbb310)
|
||||
|
||||
Fixes
|
||||
-----
|
||||
* Fix handling of NULL pointers in `cJSON_ArrayForEach` (b47d0e34caaef298edfb7bd09a72cfff21d231ff)
|
||||
* Make it compile with GCC 7 (fix -Wimplicit-fallthrough warning) (9d07917feb1b613544a7513d19233d4c851ad7ad)
|
||||
* Fix handling of NULL pointers in `cJSON_ArrayForEach`, see [b47d0e3](https://github.com/DaveGamble/cJSON/commit/b47d0e34caaef298edfb7bd09a72cfff21d231ff)
|
||||
* Make it compile with GCC 7 (fix -Wimplicit-fallthrough warning), see [9d07917](https://github.com/DaveGamble/cJSON/commit/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)
|
||||
* internally use realloc if available ([#110](https://github.com/DaveGamble/cJSON/pull/110))
|
||||
* builtin support for fuzzing with [afl](http://lcamtuf.coredump.cx/afl/) ([#111](https://github.com/DaveGamble/cJSON/pull/111))
|
||||
* unit tests for the print functions ([#112](https://github.com/DaveGamble/cJSON/pull/112))
|
||||
* Always use buffered printing ([#113](https://github.com/DaveGamble/cJSON/pull/113))
|
||||
* simplify the print functions ([#114](https://github.com/DaveGamble/cJSON/pull/114))
|
||||
* Add the compiler flags `-Wdouble-conversion`, `-Wparentheses` and `-Wcomma` ([#122](https://github.com/DaveGamble/cJSON/pull/122))
|
||||
|
||||
1.3.2
|
||||
1.3.2 (Mar 1, 2017)
|
||||
=====
|
||||
Fix:
|
||||
----
|
||||
- Don't build the unity library if testing is disabled ( #121 ). Thanks @ffontaine
|
||||
Fixes:
|
||||
------
|
||||
* Don't build the unity library if testing is disabled, see [#121](https://github.com/DaveGamble/cJSON/pull/121). Thanks @ffontaine
|
||||
|
||||
1.3.1
|
||||
1.3.1 (Feb 27, 2017)
|
||||
=====
|
||||
Bugfix release that fixes an out of bounds read #118. This shouldn't have any security implications.
|
||||
Fixes:
|
||||
------
|
||||
* Bugfix release that fixes an out of bounds read, see [#118](https://github.com/DaveGamble/cJSON/pull/118). This shouldn't have any security implications.
|
||||
|
||||
1.3.0
|
||||
1.3.0 (Feb 17, 2017)
|
||||
=====
|
||||
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)
|
||||
* New type for cJSON structs: `cJSON_Invalid`, see [#108](https://github.com/DaveGamble/cJSON/pull/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
|
||||
* runtime checks for a lot of potential integer overflows
|
||||
* fix incorrect return in cJSON_PrintBuffered [cf9d57d](https://github.com/DaveGamble/cJSON/commit/cf9d57d56cac21fc59465b8d26cf29bf6d2a87b3)
|
||||
* fix several potential issues found by [Coverity](https://scan.coverity.com/projects/cjson)
|
||||
* fix potentially undefined behavior when assigning big numbers to `valueint` ([41e2837](https://github.com/DaveGamble/cJSON/commit/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 ([87f7727](https://github.com/DaveGamble/cJSON/commit/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.
|
||||
* 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)
|
||||
* 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](https://github.com/DaveGamble/cJSON/issues/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)
|
||||
* Use `strtod` from the standard library for parsing numbers ([0747669](https://github.com/DaveGamble/cJSON/commit/074766997246481dfc72bfa78f07898a2716473f))
|
||||
* Use goto-fail in several parser functions ([#100](https://github.com/DaveGamble/cJSON/pull/100))
|
||||
* Rewrite/restructure all of the parsing functions to be easier to understand and have less code paths doing the same as another. ([#109](https://github.com/DaveGamble/cJSON/pull/109))
|
||||
* Simplify the buffer allocation strategy to always doubling the needed amount ([9f6fa94](https://github.com/DaveGamble/cJSON/commit/9f6fa94c91a87b71e4c6868dbf2ce431a48517b0))
|
||||
* Combined `cJSON_AddItemToObject` and `cJSON_AddItemToObjectCS` to one function ([cf862d](https://github.com/DaveGamble/cJSON/commit/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
|
||||
* Prevent the usage of incompatible C and header versions via preprocessor directive ([123bb1](https://github.com/DaveGamble/cJSON/commit/123bb1af7bfae41d805337fef4b41045ef6c7d25))
|
||||
* Let CMake automatically detect compiler flags
|
||||
* Add new compiler flags (`-Wundef`, `-Wswitch-default`, `-Wconversion`, `-fstack-protector-strong`) ([#98](https://github.com/DaveGamble/cJSON/pull/98))
|
||||
* Change internal sizes from `int` to `size_t` ([ecd5678](https://github.com/DaveGamble/cJSON/commit/ecd5678527a6bc422da694e5be9e9979878fe6a0))
|
||||
* Change internal strings from `char*` to `unsigned char*` ([28b9ba4](https://github.com/DaveGamble/cJSON/commit/28b9ba4334e0f7309e867e874a31f395c0ac2474))
|
||||
* Add `const` in more places
|
||||
|
||||
1.2.1
|
||||
1.2.1 (Jan 31, 2017)
|
||||
=====
|
||||
Fixes:
|
||||
------
|
||||
- Fixes a potential null pointer dereference in cJSON_Utils, discovered using clang's static analyzer by @bnason-nf (#96)
|
||||
* Fixes a potential null pointer dereference in cJSON_Utils, discovered using clang's static analyzer by @bnason-nf, see [#96](https://github.com/DaveGamble/cJSON/issues/96)
|
||||
|
||||
1.2.0
|
||||
1.2.0 (Jan 9, 2017)
|
||||
=====
|
||||
Features:
|
||||
---------
|
||||
- Add a new type of cJSON item for raw JSON and support printing it. Thanks @loigu (#65, #90)
|
||||
* Add a new type of cJSON item for raw JSON and support printing it. Thanks @loigu, see [#65](https://github.com/DaveGamble/cJSON/pull/65), [#90](https://github.com/DaveGamble/cJSON/pull/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
|
||||
* Compiler warning if const is casted away, Thanks @gatzka, see [#83](https://github.com/DaveGamble/cJSON/pull/83)
|
||||
* Fix compile error with strict-overflow on PowerPC, see [#85](https://github.com/DaveGamble/cJSON/issues/85)
|
||||
* Fix typo in the README, thanks @MicroJoe, see [#88](https://github.com/DaveGamble/cJSON/pull/88)
|
||||
* Add compile flag for compatibility with C++ compilers
|
||||
|
||||
1.1.0
|
||||
1.1.0 (Dec 6, 2016)
|
||||
=====
|
||||
- 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
|
||||
* Add a function `cJSON_PrintPreallocated` to print to a preallocated buffer, thanks @ChisholmKyle, see [#72](https://github.com/DaveGamble/cJSON/pull/72)
|
||||
* More compiler warnings when using Clang or GCC, thanks @gatzka, see [#75](https://github.com/DaveGamble/cJSON/pull/75), [#78](https://github.com/DaveGamble/cJSON/pull/78)
|
||||
* fixed a memory leak in `cJSON_Duplicate`, thanks @alperakcan, see [#81](https://github.com/DaveGamble/cJSON/pull/81)
|
||||
* fix the `ENABLE_CUSTOM_COMPILER_FLAGS` cmake option
|
||||
|
||||
1.0.2
|
||||
1.0.2 (Nov 25, 2016)
|
||||
=====
|
||||
Rename internal boolean type, see #71.
|
||||
* Rename internal boolean type, see [#71](https://github.com/DaveGamble/cJSON/issues/71).
|
||||
|
||||
1.0.1
|
||||
1.0.1 (Nov 20, 2016)
|
||||
=====
|
||||
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
|
||||
* Fixes a bug with the use of the cJSON structs type in cJSON_Utils, see [d47339e](https://github.com/DaveGamble/cJSON/commit/d47339e2740360e6e0994527d5e4752007480f3a)
|
||||
* improve code readability
|
||||
* initialize all variables
|
||||
|
||||
1.0.0
|
||||
1.0.0 (Nov 17, 2016)
|
||||
=====
|
||||
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.
|
||||
|
||||
@@ -7,7 +7,7 @@ include(GNUInstallDirs)
|
||||
|
||||
set(PROJECT_VERSION_MAJOR 1)
|
||||
set(PROJECT_VERSION_MINOR 7)
|
||||
set(PROJECT_VERSION_PATCH 1)
|
||||
set(PROJECT_VERSION_PATCH 15)
|
||||
set(CJSON_VERSION_SO 1)
|
||||
set(CJSON_UTILS_VERSION_SO 1)
|
||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
@@ -49,11 +49,15 @@ if (ENABLE_CUSTOM_COMPILER_FLAGS)
|
||||
-Wswitch-enum
|
||||
)
|
||||
elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# Disable warning c4001 - nonstandard extension 'single line comment' was used
|
||||
# Define _CRT_SECURE_NO_WARNINGS to disable deprecation warnings for "insecure" C library functions
|
||||
list(APPEND custom_compiler_flags
|
||||
/GS
|
||||
/Za
|
||||
/sdl
|
||||
/W4
|
||||
/wd4001
|
||||
/D_CRT_SECURE_NO_WARNINGS
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
@@ -64,7 +68,6 @@ if (ENABLE_SANITIZERS)
|
||||
-fno-omit-frame-pointer
|
||||
-fsanitize=address
|
||||
-fsanitize=undefined
|
||||
-fsanitize=float-divide-by-zero
|
||||
-fsanitize=float-cast-overflow
|
||||
-fsanitize-address-use-after-scope
|
||||
-fsanitize=integer
|
||||
@@ -107,12 +110,6 @@ 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}")
|
||||
set(version "${PROJECT_VERSION}")
|
||||
set(includedir "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
option(ENABLE_TARGET_EXPORT "Enable exporting of CMake targets. Disable when it causes problems!" ON)
|
||||
|
||||
@@ -149,15 +146,21 @@ endif()
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson.pc.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" @ONLY)
|
||||
|
||||
install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/cjson")
|
||||
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
install(TARGETS "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}" EXPORT "${CJSON_LIB}")
|
||||
install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
|
||||
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
|
||||
install(TARGETS "${CJSON_LIB}"
|
||||
EXPORT "${CJSON_LIB}"
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
|
||||
)
|
||||
if (BUILD_SHARED_AND_STATIC_LIBS)
|
||||
install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
|
||||
endif()
|
||||
if(ENABLE_TARGET_EXPORT)
|
||||
# export library information for CMake projects
|
||||
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON")
|
||||
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
|
||||
endif()
|
||||
|
||||
set_target_properties("${CJSON_LIB}"
|
||||
@@ -188,15 +191,21 @@ if(ENABLE_CJSON_UTILS)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson_utils.pc.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" @ONLY)
|
||||
|
||||
install(TARGETS "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}" EXPORT "${CJSON_UTILS_LIB}")
|
||||
install(TARGETS "${CJSON_UTILS_LIB}"
|
||||
EXPORT "${CJSON_UTILS_LIB}"
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
|
||||
)
|
||||
if (BUILD_SHARED_AND_STATIC_LIBS)
|
||||
install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
|
||||
endif()
|
||||
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/cjson")
|
||||
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
|
||||
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
|
||||
if(ENABLE_TARGET_EXPORT)
|
||||
# export library information for CMake projects
|
||||
install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON")
|
||||
install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
|
||||
endif()
|
||||
|
||||
set_target_properties("${CJSON_UTILS_LIB}"
|
||||
@@ -213,10 +222,12 @@ configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfigVersion.cmake.in"
|
||||
${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake @ONLY)
|
||||
|
||||
# Install package config files
|
||||
install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake
|
||||
${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cJSON")
|
||||
if(ENABLE_TARGET_EXPORT)
|
||||
# Install package config files
|
||||
install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake
|
||||
${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake
|
||||
DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
|
||||
endif()
|
||||
|
||||
option(ENABLE_CJSON_TEST "Enable building cJSON test" ON)
|
||||
if(ENABLE_CJSON_TEST)
|
||||
@@ -243,6 +254,9 @@ if(ENABLE_CJSON_TEST)
|
||||
DEPENDS ${TEST_CJSON})
|
||||
endif()
|
||||
|
||||
#Create the uninstall target
|
||||
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${PROJECT_SOURCE_DIR}/library_config/uninstall.cmake")
|
||||
|
||||
# Enable the use of locales
|
||||
option(ENABLE_LOCALES "Enable the use of locales" ON)
|
||||
if(ENABLE_LOCALES)
|
||||
|
||||
@@ -1,44 +1,79 @@
|
||||
Contributors
|
||||
============
|
||||
|
||||
Original Author: [Dave Gamble](https://github.com/DaveGamble)
|
||||
Current Maintainer: [Max Bruckner](https://github.com/FSMaxB)
|
||||
Original Author:
|
||||
- [Dave Gamble](https://github.com/DaveGamble)
|
||||
|
||||
Current Maintainer:
|
||||
- [Max Bruckner](https://github.com/FSMaxB)
|
||||
- [Alan Wang](https://github.com/Alanscut)
|
||||
|
||||
Contributors:
|
||||
* [Ajay Bhargav](https://github.com/ajaybhargav)
|
||||
* [Alper Akcan](https://github.com/alperakcan)
|
||||
* [Andrew Tang](https://github.com/singku)
|
||||
* [Anton Sergeev](https://github.com/anton-sergeev)
|
||||
* [Benbuck Nason](https://github.com/bnason-nf)
|
||||
* [Bernt Johan Damslora](https://github.com/bjda)
|
||||
* [Bob Kocisko](https://github.com/bobkocisko)
|
||||
* [Christian Schulze](https://github.com/ChristianSch)
|
||||
* [Casperinous](https://github.com/Casperinous)
|
||||
* [ChenYuan](https://github.com/zjuchenyuan)
|
||||
* [Debora Grosse](https://github.com/DeboraG)
|
||||
* [dieyushi](https://github.com/dieyushi)
|
||||
* [Dōngwén Huáng (黄东文)](https://github.com/DongwenHuang)
|
||||
* [Donough Liu](https://github.com/ldm0)
|
||||
* [Erez Oxman](https://github.com/erez-o)
|
||||
* Eswar Yaganti
|
||||
* [Evan Todd](https://github.com/etodd)
|
||||
* [Fabrice Fontaine](https://github.com/ffontaine)
|
||||
* Ian Mobley
|
||||
* Irwan Djadjadi
|
||||
* [HuKeping](https://github.com/HuKeping)
|
||||
* [IvanVoid](https://github.com/npi3pak)
|
||||
* [Jakub Wilk](https://github.com/jwilk)
|
||||
* [Jiri Zouhar](https://github.com/loigu)
|
||||
* [Jonathan Fether](https://github.com/jfether)
|
||||
* [Julian Ste](https://github.com/julian-st)
|
||||
* [Julián Vásquez](https://github.com/juvasquezg)
|
||||
* [Kevin Branigan](https://github.com/kbranigan)
|
||||
* [Kevin Sapper](https://github.com/sappo)
|
||||
* [Kyle Chisholm](https://github.com/ChisholmKyle)
|
||||
* [Linus Wallgren](https://github.com/ecksun)
|
||||
* [Mateusz Szafoni](https://github.com/raiden00pl)
|
||||
* Mike Pontillo
|
||||
* [miaoerduo](https://github.com/miaoerduo)
|
||||
* [Mike Jerris](https://github.com/mjerris)
|
||||
* [Mike Robinson](https://github.com/mhrobinson)
|
||||
* [Moorthy](https://github.com/moorthy-bs)
|
||||
* [myd7349](https://github.com/myd7349)
|
||||
* [NancyLi1013](https://github.com/NancyLi1013)
|
||||
* Paulo Antonio Alvarez
|
||||
* [Paweł Malowany](https://github.com/PawelMalowany)
|
||||
* [Pawel Winogrodzki](https://github.com/PawelWMS)
|
||||
* [prefetchnta](https://github.com/prefetchnta)
|
||||
* [Rafael Leal Dias](https://github.com/rafaeldias)
|
||||
* [Randy](https://github.com/randy408)
|
||||
* [raiden00pl](https://github.com/raiden00pl)
|
||||
* [Robin Mallinson](https://github.com/rmallins)
|
||||
* [Rod Vagg](https://github.com/rvagg)
|
||||
* [Roland Meertens](https://github.com/rmeertens)
|
||||
* [Romain Porte](https://github.com/MicroJoe)
|
||||
* [SANJEEV BA](https://github.com/basanjeev)
|
||||
* [Sang-Heon Jeon](https://github.com/lntuition)
|
||||
* [Simon Sobisch](https://github.com/GitMensch)
|
||||
* [Simon Ricaldone](https://github.com/simon-p-r)
|
||||
* [Square789](https://github.com/Square789)
|
||||
* [Stephan Gatzka](https://github.com/gatzka)
|
||||
* [Vemake](https://github.com/vemakereporter)
|
||||
* [Wei Tan](https://github.com/tan-wei)
|
||||
* [Weston Schmidt](https://github.com/schmidtw)
|
||||
* [xiaomianhehe](https://github.com/xiaomianhehe)
|
||||
* [yangfl](https://github.com/yangfl)
|
||||
* [yuta-oxo](https://github.com/yuta-oxo)
|
||||
* [Zach Hindes](https://github.com/zhindes)
|
||||
* [Zhao Zhixu](https://github.com/zhaozhixu)
|
||||
|
||||
And probably more people on [SourceForge](https://sourceforge.net/p/cjson/bugs/search/?q=status%3Aclosed-rejected+or+status%3Aclosed-out-of-date+or+status%3Awont-fix+or+status%3Aclosed-fixed+or+status%3Aclosed&page=0)
|
||||
|
||||
Also thanks to all the people who reported bugs and suggested new features.
|
||||
|
||||
29
Makefile
29
Makefile
@@ -8,10 +8,13 @@ CJSON_TEST_SRC = cJSON.c test.c
|
||||
|
||||
LDLIBS = -lm
|
||||
|
||||
LIBVERSION = 1.7.1
|
||||
LIBVERSION = 1.7.15
|
||||
CJSON_SOVERSION = 1
|
||||
UTILS_SOVERSION = 1
|
||||
|
||||
CJSON_SO_LDFLAG=-Wl,-soname=$(CJSON_LIBNAME).so.$(CJSON_SOVERSION)
|
||||
UTILS_SO_LDFLAG=-Wl,-soname=$(UTILS_LIBNAME).so.$(UTILS_SOVERSION)
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
INCLUDE_PATH ?= include/cjson
|
||||
LIBRARY_PATH ?= lib
|
||||
@@ -21,9 +24,11 @@ INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH)
|
||||
|
||||
INSTALL ?= cp -a
|
||||
|
||||
CC = gcc -std=c89
|
||||
|
||||
# validate gcc version for use fstack-protector-strong
|
||||
MIN_GCC_VERSION = "4.9"
|
||||
GCC_VERSION := "`gcc -dumpversion`"
|
||||
GCC_VERSION := "`$(CC) -dumpversion`"
|
||||
IS_GCC_ABOVE_MIN_VERSION := $(shell expr "$(GCC_VERSION)" ">=" "$(MIN_GCC_VERSION)")
|
||||
ifeq "$(IS_GCC_ABOVE_MIN_VERSION)" "1"
|
||||
CFLAGS += -fstack-protector-strong
|
||||
@@ -31,7 +36,8 @@ else
|
||||
CFLAGS += -fstack-protector
|
||||
endif
|
||||
|
||||
R_CFLAGS = -fPIC -std=c89 -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS)
|
||||
PIC_FLAGS = -fPIC
|
||||
R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS)
|
||||
|
||||
uname := $(shell sh -c 'uname -s 2>/dev/null || echo false')
|
||||
|
||||
@@ -42,6 +48,8 @@ STATIC = a
|
||||
## create dynamic (shared) library on Darwin (base OS for MacOSX and IOS)
|
||||
ifeq (Darwin, $(uname))
|
||||
SHARED = dylib
|
||||
CJSON_SO_LDFLAG = ""
|
||||
UTILS_SO_LDFLAG = ""
|
||||
endif
|
||||
|
||||
#cJSON library names
|
||||
@@ -90,16 +98,16 @@ $(UTILS_STATIC): $(UTILS_OBJ)
|
||||
#shared libraries .so.1.0.0
|
||||
#cJSON
|
||||
$(CJSON_SHARED_VERSION): $(CJSON_OBJ)
|
||||
$(CC) -shared -o $@ $< $(LDFLAGS)
|
||||
$(CC) -shared -o $@ $< $(CJSON_SO_LDFLAG) $(LDFLAGS)
|
||||
#cJSON_Utils
|
||||
$(UTILS_SHARED_VERSION): $(UTILS_OBJ)
|
||||
$(CC) -shared -o $@ $< $(LDFLAGS)
|
||||
$(CC) -shared -o $@ $< $(CJSON_OBJ) $(UTILS_SO_LDFLAG) $(LDFLAGS)
|
||||
|
||||
#objects
|
||||
#cJSON
|
||||
$(CJSON_OBJ): cJSON.c cJSON.h
|
||||
#cJSON_Utils
|
||||
$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h
|
||||
$(UTILS_OBJ): cJSON_Utils.c cJSON_Utils.h cJSON.h
|
||||
|
||||
|
||||
#links .so -> .so.1 -> .so.1.0.0
|
||||
@@ -133,9 +141,8 @@ uninstall-cjson: uninstall-utils
|
||||
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED)
|
||||
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_VERSION)
|
||||
$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_SO)
|
||||
rmdir $(INSTALL_LIBRARY_PATH)
|
||||
$(RM) $(INSTALL_INCLUDE_PATH)/cJSON.h
|
||||
rmdir $(INSTALL_INCLUDE_PATH)
|
||||
|
||||
#cJSON_Utils
|
||||
uninstall-utils:
|
||||
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED)
|
||||
@@ -143,7 +150,11 @@ uninstall-utils:
|
||||
$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_SO)
|
||||
$(RM) $(INSTALL_INCLUDE_PATH)/cJSON_Utils.h
|
||||
|
||||
uninstall: uninstall-utils uninstall-cjson
|
||||
remove-dir:
|
||||
$(if $(wildcard $(INSTALL_LIBRARY_PATH)/*.*),,rmdir $(INSTALL_LIBRARY_PATH))
|
||||
$(if $(wildcard $(INSTALL_INCLUDE_PATH)/*.*),,rmdir $(INSTALL_INCLUDE_PATH))
|
||||
|
||||
uninstall: uninstall-utils uninstall-cjson remove-dir
|
||||
|
||||
clean:
|
||||
$(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files
|
||||
|
||||
74
README.md
74
README.md
@@ -10,6 +10,7 @@ Ultralightweight JSON parser in ANSI C.
|
||||
* [Copying the source](#copying-the-source)
|
||||
* [CMake](#cmake)
|
||||
* [Makefile](#makefile)
|
||||
* [Vcpkg](#Vcpkg)
|
||||
* [Including cJSON](#including-cjson)
|
||||
* [Data Structure](#data-structure)
|
||||
* [Working with the data structure](#working-with-the-data-structure)
|
||||
@@ -80,11 +81,13 @@ philosophy as JSON itself. Simple, dumb, out of the way.
|
||||
There are several ways to incorporate cJSON into your project.
|
||||
|
||||
#### copying the source
|
||||
|
||||
Because the entire library is only one C file and one header file, you can just copy `cJSON.h` and `cJSON.c` to your projects source and start using it.
|
||||
|
||||
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. 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.
|
||||
|
||||
```
|
||||
@@ -102,6 +105,7 @@ make
|
||||
And install it with `make install` if you want. By default it installs the headers `/usr/local/include/cjson` and the libraries to `/usr/local/lib`. It also installs files for pkg-config to make it easier to detect and use an existing installation of CMake. And it installs CMake config files, that can be used by other CMake based projects to discover the library.
|
||||
|
||||
You can change the build process with a list of different options that you can pass to CMake. Turn them on with `On` and off with `Off`:
|
||||
|
||||
* `-DENABLE_CJSON_TEST=On`: Enable building the tests. (on by default)
|
||||
* `-DENABLE_CJSON_UTILS=On`: Enable building cJSON_Utils. (off by default)
|
||||
* `-DENABLE_TARGET_EXPORT=On`: Enable the export of CMake targets. Turn off if it makes problems. (on by default)
|
||||
@@ -127,17 +131,34 @@ make DESTDIR=$pkgdir install
|
||||
On Windows CMake is usually used to create a Visual Studio solution file by running it inside the Developer Command Prompt for Visual Studio, for exact steps follow the official documentation from CMake and Microsoft and use the online search engine of your choice. The descriptions of the the options above still generally apply, although not all of them work on Windows.
|
||||
|
||||
#### Makefile
|
||||
|
||||
**NOTE:** This Method is deprecated. Use CMake if at all possible. Makefile support is limited to fixing bugs.
|
||||
|
||||
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.
|
||||
Run this command in the directory with the source code and it will automatically compile static and shared libraries and a little test program (not the full test suite).
|
||||
|
||||
```
|
||||
make all
|
||||
```
|
||||
|
||||
If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`.
|
||||
If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`. And uninstall them with: `make PREFIX=/usr DESTDIR=temp uninstall`.
|
||||
|
||||
#### Vcpkg
|
||||
|
||||
You can download and install cJSON using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
```
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
vcpkg install cjson
|
||||
```
|
||||
|
||||
The cJSON port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
### Including cJSON
|
||||
|
||||
If you installed it via CMake or the Makefile, you can include cJSON like this:
|
||||
|
||||
```c
|
||||
@@ -169,39 +190,43 @@ An item of this type represents a JSON value. The type is stored in `type` as a
|
||||
To check the type of an item, use the corresponding `cJSON_Is...` function. It does a `NULL` check followed by a type check and returns a boolean value if the item is of this type.
|
||||
|
||||
The type can be one of the following:
|
||||
|
||||
* `cJSON_Invalid` (check with `cJSON_IsInvalid`): Represents an invalid item that doesn't contain any value. You automatically have this type if you set the item to all zero bytes.
|
||||
* `cJSON_False` (check with `cJSON_IsFalse`): Represents a `false` boolean value. You can also check for boolean values in general with `cJSON_IsBool`.
|
||||
* `cJSON_True` (check with `cJSON_IsTrue`): Represents a `true` boolean value. You can also check for boolean values in general with `cJSON_IsBool`.
|
||||
* `cJSON_NULL` (check with `cJSON_IsNull`): Represents a `null` value.
|
||||
* `cJSON_Number` (check with `cJSON_IsNumber`): Represents a number value. The value is stored as a double in `valuedouble` and also in `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint`.
|
||||
* `cJSON_String` (check with `cJSON_IsString`): Represents a string value. It is stored in the form of a zero terminated string in `valuestring`.
|
||||
* `cJSON_Array` (check with `cJSON_IsArray`): Represent an array value. This is implemented by pointing `child` to a linked list of `cJSON` items that represent the values in the array. The elements are linked together using `next` and `prev`, where the first element has `prev == NULL` and the last element `next == NULL`.
|
||||
* `cJSON_Array` (check with `cJSON_IsArray`): Represent an array value. This is implemented by pointing `child` to a linked list of `cJSON` items that represent the values in the array. The elements are linked together using `next` and `prev`, where the first element has `prev.next == NULL` and the last element `next == NULL`.
|
||||
* `cJSON_Object` (check with `cJSON_IsObject`): Represents an object value. Objects are stored same way as an array, the only difference is that the items in the object store their keys in `string`.
|
||||
* `cJSON_Raw` (check with `cJSON_IsRaw`): Represents any kind of JSON that is stored as a zero terminated array of characters in `valuestring`. This can be used, for example, to avoid printing the same static JSON over and over again to save performance. cJSON will never create this type when parsing. Also note that cJSON doesn't check if it is valid JSON.
|
||||
|
||||
Additionally there are the following two flags:
|
||||
* `cJSON_IsReference`: Specifies that the item that `child` points to and/or `valuestring` is not owned by this item, it is only a reference. So `cJSON_Delete` and other functions will only deallocate this item, not it's children/valuestring.
|
||||
|
||||
* `cJSON_IsReference`: Specifies that the item that `child` points to and/or `valuestring` is not owned by this item, it is only a reference. So `cJSON_Delete` and other functions will only deallocate this item, not its `child`/`valuestring`.
|
||||
* `cJSON_StringIsConst`: This means that `string` points to a constant string. This means that `cJSON_Delete` and other functions will not try to deallocate `string`.
|
||||
|
||||
### Working with the data structure
|
||||
|
||||
For every value type there is a `cJSON_Create...` function that can be used to create an item of that type.
|
||||
All of these will allocate a `cJSON` struct that can later be deleted with `cJSON_Delete`.
|
||||
Note that you have to delete them at some point, otherwise you will get a memory leak.
|
||||
**Important**: If you have added an item to an array or an object already, you **mustn't** delete it with `cJSON_Delete`. Adding it to an array or object transfers its ownership so that when that array or object is deleted, it gets deleted as well.
|
||||
Note that you have to delete them at some point, otherwise you will get a memory leak.
|
||||
**Important**: If you have added an item to an array or an object already, you **mustn't** delete it with `cJSON_Delete`. Adding it to an array or object transfers its ownership so that when that array or object is deleted,
|
||||
it gets deleted as well. You also could use `cJSON_SetValuestring` to change a `cJSON_String`'s `valuestring`, and you needn't to free the previous `valuestring` manually.
|
||||
|
||||
#### Basic types
|
||||
|
||||
* **null** is created with `cJSON_CreateNull`
|
||||
* **booleans** are created with `cJSON_CreateTrue`, `cJSON_CreateFalse` or `cJSON_CreateBool`
|
||||
* **numbers** are created with `cJSON_CreateNumber`. This will set both `valuedouble` and `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint`
|
||||
* **strings** are created with `cJSON_CreateString` (copies the string) or with `cJSON_CreateStringReference` (directly points to the string. This means that `valuestring` won't be deleted by `cJSON_Delete` and you are responsible for it's lifetime, useful for constants)
|
||||
* **strings** are created with `cJSON_CreateString` (copies the string) or with `cJSON_CreateStringReference` (directly points to the string. This means that `valuestring` won't be deleted by `cJSON_Delete` and you are responsible for its lifetime, useful for constants)
|
||||
|
||||
#### Arrays
|
||||
|
||||
You can create an empty array with `cJSON_CreateArray`. `cJSON_CreateArrayReference` can be used to create an array that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`.
|
||||
|
||||
To add items to an array, use `cJSON_AddItemToArray` to append items to the end.
|
||||
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another item, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere.
|
||||
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another item, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occurring if they are already used elsewhere.
|
||||
To insert items in the middle, use `cJSON_InsertItemInArray`. It will insert an item at the given 0 based index and shift all the existing items to the right.
|
||||
|
||||
If you want to take an item out of an array at a given index and continue using it, use `cJSON_DetachItemFromArray`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.
|
||||
@@ -219,7 +244,7 @@ Because an array is stored as a linked list, iterating it via index is inefficie
|
||||
You can create an empty object with `cJSON_CreateObject`. `cJSON_CreateObjectReference` can be used to create an object that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`.
|
||||
|
||||
To add items to an object, use `cJSON_AddItemToObject`. Use `cJSON_AddItemToObjectCS` to add an item to an object with a name that is a constant or reference (key of the item, `string` in the `cJSON` struct), so that it doesn't get freed by `cJSON_Delete`.
|
||||
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another object, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occuring if they are already used elsewhere.
|
||||
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another object, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occurring if they are already used elsewhere.
|
||||
|
||||
If you want to take an item out of an object, use `cJSON_DetachItemFromObjectCaseSensitive`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.
|
||||
|
||||
@@ -243,6 +268,12 @@ Given some JSON in a zero terminated string, you can parse it with `cJSON_Parse`
|
||||
cJSON *json = cJSON_Parse(string);
|
||||
```
|
||||
|
||||
Given some JSON in a string (whether zero terminated or not), you can parse it with `cJSON_ParseWithLength`.
|
||||
|
||||
```c
|
||||
cJSON *json = cJSON_ParseWithLength(string, buffer_length);
|
||||
```
|
||||
|
||||
It will parse the JSON and allocate a tree of `cJSON` items that represents it. Once it returns, you are fully responsible for deallocating it after use with `cJSON_Delete`.
|
||||
|
||||
The allocator used by `cJSON_Parse` is `malloc` and `free` by default but can be changed (globally) with `cJSON_InitHooks`.
|
||||
@@ -253,6 +284,8 @@ By default, characters in the input string that follow the parsed JSON will not
|
||||
If you want more options, use `cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)`.
|
||||
`return_parse_end` returns a pointer to the end of the JSON in the input string or the position that an error occurs at (thereby replacing `cJSON_GetErrorPtr` in a thread safe way). `require_null_terminated`, if set to `1` will make it an error if the input string contains data after the JSON.
|
||||
|
||||
If you want more options giving buffer length, use `cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)`.
|
||||
|
||||
### Printing JSON
|
||||
|
||||
Given a tree of `cJSON` items, you can print them as a string using `cJSON_Print`.
|
||||
@@ -265,11 +298,12 @@ It will allocate a string and print a JSON representation of the tree into it. O
|
||||
|
||||
`cJSON_Print` will print with whitespace for formatting. If you want to print without formatting, use `cJSON_PrintUnformatted`.
|
||||
|
||||
If you have a rough idea of how big your resulting string will be, you can use `cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)`. `fmt` is a boolean to turn formatting with whitespace on and off. `prebuffer` specifies the first buffer size to use for printing. `cJSON_Print` currently uses 256 bytes for it's first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued.
|
||||
If you have a rough idea of how big your resulting string will be, you can use `cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)`. `fmt` is a boolean to turn formatting with whitespace on and off. `prebuffer` specifies the first buffer size to use for printing. `cJSON_Print` currently uses 256 bytes for its first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued.
|
||||
|
||||
These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and it's length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough.
|
||||
These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and its length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough.
|
||||
|
||||
### Example
|
||||
|
||||
In this example we want to build and parse the following JSON:
|
||||
|
||||
```json
|
||||
@@ -293,10 +327,13 @@ In this example we want to build and parse the following JSON:
|
||||
```
|
||||
|
||||
#### Printing
|
||||
|
||||
Let's build the above JSON and print it to a string:
|
||||
|
||||
```c
|
||||
//create a monitor with a list of supported resolutions
|
||||
char* create_monitor(void)
|
||||
//NOTE: Returns a heap allocated string, you are required to free it after use.
|
||||
char *create_monitor(void)
|
||||
{
|
||||
const unsigned int resolution_numbers[3][2] = {
|
||||
{1280, 720},
|
||||
@@ -323,7 +360,7 @@ char* create_monitor(void)
|
||||
goto end;
|
||||
}
|
||||
/* after creation was successful, immediately add it to the monitor,
|
||||
* thereby transfering ownership of the pointer to it */
|
||||
* thereby transferring ownership of the pointer to it */
|
||||
cJSON_AddItemToObject(monitor, "name", name);
|
||||
|
||||
resolutions = cJSON_CreateArray();
|
||||
@@ -370,7 +407,9 @@ end:
|
||||
```
|
||||
|
||||
Alternatively we can use the `cJSON_Add...ToObject` helper functions to make our lifes a little easier:
|
||||
|
||||
```c
|
||||
//NOTE: Returns a heap allocated string, you are required to free it after use.
|
||||
char *create_monitor_with_helpers(void)
|
||||
{
|
||||
const unsigned int resolution_numbers[3][2] = {
|
||||
@@ -404,7 +443,7 @@ char *create_monitor_with_helpers(void)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
|
||||
if (cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
@@ -413,7 +452,8 @@ char *create_monitor_with_helpers(void)
|
||||
}
|
||||
|
||||
string = cJSON_Print(monitor);
|
||||
if (string == NULL) {
|
||||
if (string == NULL)
|
||||
{
|
||||
fprintf(stderr, "Failed to print monitor.\n");
|
||||
}
|
||||
|
||||
@@ -424,6 +464,7 @@ end:
|
||||
```
|
||||
|
||||
#### Parsing
|
||||
|
||||
In this example we will parse a JSON in the above format and check if the monitor supports a Full HD resolution while printing some diagnostic output:
|
||||
|
||||
```c
|
||||
@@ -510,6 +551,7 @@ cJSON doesn't support arrays and objects that are nested too deeply because this
|
||||
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.
|
||||
@@ -525,5 +567,5 @@ cJSON supports parsing and printing JSON that contains objects that have multipl
|
||||
# Enjoy cJSON!
|
||||
|
||||
- Dave Gamble (original author)
|
||||
- Max Bruckner (current maintainer)
|
||||
- Max Bruckner and Alan Wang (current maintainer)
|
||||
- and the other [cJSON contributors](CONTRIBUTORS.md)
|
||||
|
||||
476
cJSON.c
476
cJSON.c
@@ -41,9 +41,9 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifdef ENABLE_LOCALES
|
||||
#include <locale.h>
|
||||
@@ -59,9 +59,32 @@
|
||||
#include "cJSON.h"
|
||||
|
||||
/* define our own boolean type */
|
||||
#ifdef true
|
||||
#undef true
|
||||
#endif
|
||||
#define true ((cJSON_bool)1)
|
||||
|
||||
#ifdef false
|
||||
#undef false
|
||||
#endif
|
||||
#define false ((cJSON_bool)0)
|
||||
|
||||
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
|
||||
#ifndef isinf
|
||||
#define isinf(d) (isnan((d - d)) && !isnan(d))
|
||||
#endif
|
||||
#ifndef isnan
|
||||
#define isnan(d) (d != d)
|
||||
#endif
|
||||
|
||||
#ifndef NAN
|
||||
#ifdef _WIN32
|
||||
#define NAN sqrt(-1.0)
|
||||
#else
|
||||
#define NAN 0.0/0.0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const unsigned char *json;
|
||||
size_t position;
|
||||
@@ -73,16 +96,28 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
|
||||
return (const char*) (global_error.json + global_error.position);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) {
|
||||
if (!cJSON_IsString(item)) {
|
||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
|
||||
{
|
||||
if (!cJSON_IsString(item))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return item->valuestring;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
|
||||
{
|
||||
if (!cJSON_IsNumber(item))
|
||||
{
|
||||
return (double) NAN;
|
||||
}
|
||||
|
||||
return item->valuedouble;
|
||||
}
|
||||
|
||||
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
|
||||
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 1)
|
||||
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15)
|
||||
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
|
||||
#endif
|
||||
|
||||
@@ -120,22 +155,22 @@ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned
|
||||
|
||||
typedef struct internal_hooks
|
||||
{
|
||||
void *(*allocate)(size_t size);
|
||||
void (*deallocate)(void *pointer);
|
||||
void *(*reallocate)(void *pointer, size_t size);
|
||||
void *(CJSON_CDECL *allocate)(size_t size);
|
||||
void (CJSON_CDECL *deallocate)(void *pointer);
|
||||
void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
|
||||
} internal_hooks;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* work around MSVC error C2322: '...' address of dillimport '...' is not static */
|
||||
static void *internal_malloc(size_t size)
|
||||
/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
|
||||
static void * CJSON_CDECL internal_malloc(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
static void internal_free(void *pointer)
|
||||
static void CJSON_CDECL internal_free(void *pointer)
|
||||
{
|
||||
free(pointer);
|
||||
}
|
||||
static void *internal_realloc(void *pointer, size_t size)
|
||||
static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
|
||||
{
|
||||
return realloc(pointer, size);
|
||||
}
|
||||
@@ -145,6 +180,9 @@ static void *internal_realloc(void *pointer, size_t size)
|
||||
#define internal_realloc realloc
|
||||
#endif
|
||||
|
||||
/* strlen of character literals resolved at compile time */
|
||||
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
|
||||
|
||||
static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
|
||||
|
||||
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
|
||||
@@ -325,7 +363,7 @@ loop_end:
|
||||
{
|
||||
item->valueint = INT_MAX;
|
||||
}
|
||||
else if (number <= INT_MIN)
|
||||
else if (number <= (double)INT_MIN)
|
||||
{
|
||||
item->valueint = INT_MIN;
|
||||
}
|
||||
@@ -347,7 +385,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
|
||||
{
|
||||
object->valueint = INT_MAX;
|
||||
}
|
||||
else if (number <= INT_MIN)
|
||||
else if (number <= (double)INT_MIN)
|
||||
{
|
||||
object->valueint = INT_MIN;
|
||||
}
|
||||
@@ -359,6 +397,33 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
|
||||
return object->valuedouble = number;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
|
||||
{
|
||||
char *copy = NULL;
|
||||
/* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
|
||||
if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (strlen(valuestring) <= strlen(object->valuestring))
|
||||
{
|
||||
strcpy(object->valuestring, valuestring);
|
||||
return object->valuestring;
|
||||
}
|
||||
copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
|
||||
if (copy == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (object->valuestring != NULL)
|
||||
{
|
||||
cJSON_free(object->valuestring);
|
||||
}
|
||||
object->valuestring = copy;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *buffer;
|
||||
@@ -446,10 +511,8 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
if (newbuffer)
|
||||
{
|
||||
memcpy(newbuffer, p->buffer, p->offset + 1);
|
||||
}
|
||||
|
||||
memcpy(newbuffer, p->buffer, p->offset + 1);
|
||||
p->hooks.deallocate(p->buffer);
|
||||
}
|
||||
p->length = newsize;
|
||||
@@ -471,6 +534,13 @@ static void update_offset(printbuffer * const buffer)
|
||||
buffer->offset += strlen((const char*)buffer_pointer);
|
||||
}
|
||||
|
||||
/* securely comparison of floating-point variables */
|
||||
static cJSON_bool compare_double(double a, double b)
|
||||
{
|
||||
double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
|
||||
return (fabs(a - b) <= maxVal * DBL_EPSILON);
|
||||
}
|
||||
|
||||
/* Render the number nicely from the given item into a string. */
|
||||
static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
|
||||
{
|
||||
@@ -478,9 +548,9 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
|
||||
double d = item->valuedouble;
|
||||
int length = 0;
|
||||
size_t i = 0;
|
||||
unsigned char number_buffer[26]; /* temporary buffer to print the number into */
|
||||
unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
|
||||
unsigned char decimal_point = get_decimal_point();
|
||||
double test;
|
||||
double test = 0.0;
|
||||
|
||||
if (output_buffer == NULL)
|
||||
{
|
||||
@@ -488,7 +558,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
|
||||
}
|
||||
|
||||
/* This checks for NaN and Infinity */
|
||||
if ((d * 0) != 0)
|
||||
if (isnan(d) || isinf(d))
|
||||
{
|
||||
length = sprintf((char*)number_buffer, "null");
|
||||
}
|
||||
@@ -498,14 +568,14 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
|
||||
length = sprintf((char*)number_buffer, "%1.15g", d);
|
||||
|
||||
/* Check whether the original double can be recovered */
|
||||
if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d))
|
||||
if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
|
||||
{
|
||||
/* If not, print with 17 decimal places of precision */
|
||||
length = sprintf((char*)number_buffer, "%1.17g", d);
|
||||
}
|
||||
}
|
||||
|
||||
/* sprintf failed or buffer overrun occured */
|
||||
/* sprintf failed or buffer overrun occurred */
|
||||
if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
|
||||
{
|
||||
return false;
|
||||
@@ -968,6 +1038,11 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cannot_access_at_index(buffer, 0))
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
|
||||
{
|
||||
buffer->offset++;
|
||||
@@ -997,8 +1072,23 @@ static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Parse an object - create a new root, and populate. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
|
||||
{
|
||||
size_t buffer_length;
|
||||
|
||||
if (NULL == value)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Adding null character size due to require_null_terminated. */
|
||||
buffer_length = strlen(value) + sizeof("");
|
||||
|
||||
return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
|
||||
}
|
||||
|
||||
/* Parse an object - create a new root, and populate. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
|
||||
{
|
||||
parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
cJSON *item = NULL;
|
||||
@@ -1007,13 +1097,13 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
|
||||
global_error.json = NULL;
|
||||
global_error.position = 0;
|
||||
|
||||
if (value == NULL)
|
||||
if (value == NULL || 0 == buffer_length)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
buffer.content = (const unsigned char*)value;
|
||||
buffer.length = strlen((const char*)value) + sizeof("");
|
||||
buffer.length = buffer_length;
|
||||
buffer.offset = 0;
|
||||
buffer.hooks = global_hooks;
|
||||
|
||||
@@ -1083,7 +1173,12 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
|
||||
return cJSON_ParseWithOpts(value, 0, 0);
|
||||
}
|
||||
|
||||
#define cjson_min(a, b) ((a < b) ? a : b)
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
|
||||
{
|
||||
return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
|
||||
}
|
||||
|
||||
#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
|
||||
{
|
||||
@@ -1114,10 +1209,10 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
|
||||
if (hooks->reallocate != NULL)
|
||||
{
|
||||
printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
|
||||
buffer->buffer = NULL;
|
||||
if (printed == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
buffer->buffer = NULL;
|
||||
}
|
||||
else /* otherwise copy the JSON over to a new buffer */
|
||||
{
|
||||
@@ -1190,20 +1285,20 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
|
||||
return (char*)p.buffer;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
|
||||
{
|
||||
printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
|
||||
if ((len < 0) || (buf == NULL))
|
||||
if ((length < 0) || (buffer == NULL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
p.buffer = (unsigned char*)buf;
|
||||
p.length = (size_t)len;
|
||||
p.buffer = (unsigned char*)buffer;
|
||||
p.length = (size_t)length;
|
||||
p.offset = 0;
|
||||
p.noalloc = true;
|
||||
p.format = fmt;
|
||||
p.format = format;
|
||||
p.hooks = global_hooks;
|
||||
|
||||
return print_value(item, &p);
|
||||
@@ -1311,10 +1406,6 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp
|
||||
size_t raw_length = 0;
|
||||
if (item->valuestring == NULL)
|
||||
{
|
||||
if (!output_buffer->noalloc)
|
||||
{
|
||||
output_buffer->hooks.deallocate(output_buffer->buffer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1420,6 +1511,10 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
|
||||
success:
|
||||
input_buffer->depth--;
|
||||
|
||||
if (head != NULL) {
|
||||
head->prev = current_item;
|
||||
}
|
||||
|
||||
item->type = cJSON_Array;
|
||||
item->child = head;
|
||||
|
||||
@@ -1560,7 +1655,7 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
|
||||
buffer_skip_whitespace(input_buffer);
|
||||
if (!parse_string(current_item, input_buffer))
|
||||
{
|
||||
goto fail; /* faile to parse name */
|
||||
goto fail; /* failed to parse name */
|
||||
}
|
||||
buffer_skip_whitespace(input_buffer);
|
||||
|
||||
@@ -1592,6 +1687,10 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
|
||||
success:
|
||||
input_buffer->depth--;
|
||||
|
||||
if (head != NULL) {
|
||||
head->prev = current_item;
|
||||
}
|
||||
|
||||
item->type = cJSON_Object;
|
||||
item->child = head;
|
||||
|
||||
@@ -1680,7 +1779,7 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out
|
||||
update_offset(output_buffer);
|
||||
|
||||
/* print comma if not last */
|
||||
length = (size_t) ((output_buffer->format ? 1 : 0) + (current_item->next ? 1 : 0));
|
||||
length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
|
||||
output_pointer = ensure(output_buffer, length + 1);
|
||||
if (output_pointer == NULL)
|
||||
{
|
||||
@@ -1786,7 +1885,7 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
|
||||
current_element = object->child;
|
||||
if (case_sensitive)
|
||||
{
|
||||
while ((current_element != NULL) && (strcmp(name, current_element->string) != 0))
|
||||
while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
|
||||
{
|
||||
current_element = current_element->next;
|
||||
}
|
||||
@@ -1799,6 +1898,10 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
|
||||
}
|
||||
}
|
||||
|
||||
if ((current_element == NULL) || (current_element->string == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return current_element;
|
||||
}
|
||||
|
||||
@@ -1850,35 +1953,39 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
|
||||
{
|
||||
cJSON *child = NULL;
|
||||
|
||||
if ((item == NULL) || (array == NULL))
|
||||
if ((item == NULL) || (array == NULL) || (array == item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
child = array->child;
|
||||
|
||||
/*
|
||||
* To find the last item in array quickly, we use prev in array
|
||||
*/
|
||||
if (child == NULL)
|
||||
{
|
||||
/* list is empty, start new one */
|
||||
array->child = item;
|
||||
item->prev = item;
|
||||
item->next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append to the end */
|
||||
while (child->next)
|
||||
if (child->prev)
|
||||
{
|
||||
child = child->next;
|
||||
suffix_object(child->prev, item);
|
||||
array->child->prev = item;
|
||||
}
|
||||
suffix_object(child, item);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Add item to array/object. */
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
|
||||
{
|
||||
add_item_to_array(array, item);
|
||||
return add_item_to_array(array, item);
|
||||
}
|
||||
|
||||
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
|
||||
@@ -1899,65 +2006,70 @@ static void* cast_away_const(const void* string)
|
||||
|
||||
static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
|
||||
{
|
||||
if ((object == NULL) || (string == NULL) || (item == NULL))
|
||||
char *new_key = NULL;
|
||||
int new_type = cJSON_Invalid;
|
||||
|
||||
if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (constant_key)
|
||||
{
|
||||
new_key = (char*)cast_away_const(string);
|
||||
new_type = item->type | cJSON_StringIsConst;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
|
||||
if (new_key == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
new_type = item->type & ~cJSON_StringIsConst;
|
||||
}
|
||||
|
||||
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
|
||||
{
|
||||
hooks->deallocate(item->string);
|
||||
}
|
||||
|
||||
if (constant_key)
|
||||
{
|
||||
item->string = (char*)cast_away_const(string);
|
||||
item->type |= cJSON_StringIsConst;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
|
||||
if (key == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
item->string = key;
|
||||
item->type &= ~cJSON_StringIsConst;
|
||||
}
|
||||
item->string = new_key;
|
||||
item->type = new_type;
|
||||
|
||||
return add_item_to_array(object, item);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
|
||||
{
|
||||
add_item_to_object(object, string, item, &global_hooks, false);
|
||||
return add_item_to_object(object, string, item, &global_hooks, false);
|
||||
}
|
||||
|
||||
/* Add an item to an object with constant string as key */
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
|
||||
{
|
||||
add_item_to_object(object, string, item, &global_hooks, true);
|
||||
return add_item_to_object(object, string, item, &global_hooks, true);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
|
||||
{
|
||||
if (array == NULL)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
add_item_to_array(array, create_reference(item, &global_hooks));
|
||||
return add_item_to_array(array, create_reference(item, &global_hooks));
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
|
||||
{
|
||||
if ((object == NULL) || (string == NULL))
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
|
||||
return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
|
||||
@@ -2075,7 +2187,7 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (item->prev != NULL)
|
||||
if (item != parent->child)
|
||||
{
|
||||
/* not the first element */
|
||||
item->prev->next = item->next;
|
||||
@@ -2091,6 +2203,12 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it
|
||||
/* first element */
|
||||
parent->child = item->next;
|
||||
}
|
||||
else if (item->next == NULL)
|
||||
{
|
||||
/* last element */
|
||||
parent->child->prev = item->prev;
|
||||
}
|
||||
|
||||
/* make sure the detached item doesn't point anywhere anymore */
|
||||
item->prev = NULL;
|
||||
item->next = NULL;
|
||||
@@ -2138,20 +2256,19 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const
|
||||
}
|
||||
|
||||
/* Replace array/object items with new ones. */
|
||||
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
|
||||
{
|
||||
cJSON *after_inserted = NULL;
|
||||
|
||||
if (which < 0)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
after_inserted = get_array_item(array, (size_t)which);
|
||||
if (after_inserted == NULL)
|
||||
{
|
||||
add_item_to_array(array, newitem);
|
||||
return;
|
||||
return add_item_to_array(array, newitem);
|
||||
}
|
||||
|
||||
newitem->next = after_inserted;
|
||||
@@ -2165,6 +2282,7 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit
|
||||
{
|
||||
newitem->prev->next = newitem;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
|
||||
@@ -2186,14 +2304,28 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
|
||||
{
|
||||
replacement->next->prev = replacement;
|
||||
}
|
||||
if (replacement->prev != NULL)
|
||||
{
|
||||
replacement->prev->next = replacement;
|
||||
}
|
||||
if (parent->child == item)
|
||||
{
|
||||
if (parent->child->prev == parent->child)
|
||||
{
|
||||
replacement->prev = replacement;
|
||||
}
|
||||
parent->child = replacement;
|
||||
}
|
||||
else
|
||||
{ /*
|
||||
* To find the last item in array quickly, we use prev in array.
|
||||
* We can't modify the last item's next pointer where this item was the parent's child
|
||||
*/
|
||||
if (replacement->prev != NULL)
|
||||
{
|
||||
replacement->prev->next = replacement;
|
||||
}
|
||||
if (replacement->next == NULL)
|
||||
{
|
||||
parent->child->prev = replacement;
|
||||
}
|
||||
}
|
||||
|
||||
item->next = NULL;
|
||||
item->prev = NULL;
|
||||
@@ -2202,14 +2334,14 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
|
||||
return true;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
|
||||
{
|
||||
if (which < 0)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
|
||||
return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
|
||||
}
|
||||
|
||||
static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
|
||||
@@ -2227,19 +2359,17 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO
|
||||
replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
|
||||
replacement->type &= ~cJSON_StringIsConst;
|
||||
|
||||
cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
|
||||
|
||||
return true;
|
||||
return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
|
||||
{
|
||||
replace_item_in_object(object, string, newitem, false);
|
||||
return replace_item_in_object(object, string, newitem, false);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
|
||||
{
|
||||
replace_item_in_object(object, string, newitem, true);
|
||||
return replace_item_in_object(object, string, newitem, true);
|
||||
}
|
||||
|
||||
/* Create basic types: */
|
||||
@@ -2276,12 +2406,12 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
|
||||
return item;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
|
||||
{
|
||||
cJSON *item = cJSON_New_Item(&global_hooks);
|
||||
if(item)
|
||||
{
|
||||
item->type = b ? cJSON_True : cJSON_False;
|
||||
item->type = boolean ? cJSON_True : cJSON_False;
|
||||
}
|
||||
|
||||
return item;
|
||||
@@ -2300,7 +2430,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
|
||||
{
|
||||
item->valueint = INT_MAX;
|
||||
}
|
||||
else if (num <= INT_MIN)
|
||||
else if (num <= (double)INT_MIN)
|
||||
{
|
||||
item->valueint = INT_MIN;
|
||||
}
|
||||
@@ -2416,6 +2546,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
|
||||
}
|
||||
|
||||
a = cJSON_CreateArray();
|
||||
|
||||
for(i = 0; a && (i < (size_t)count); i++)
|
||||
{
|
||||
n = cJSON_CreateNumber(numbers[i]);
|
||||
@@ -2435,6 +2566,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
|
||||
p = n;
|
||||
}
|
||||
|
||||
if (a && a->child) {
|
||||
a->child->prev = n;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -2471,6 +2606,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
|
||||
p = n;
|
||||
}
|
||||
|
||||
if (a && a->child) {
|
||||
a->child->prev = n;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -2488,7 +2627,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
|
||||
|
||||
a = cJSON_CreateArray();
|
||||
|
||||
for(i = 0;a && (i < (size_t)count); i++)
|
||||
for(i = 0; a && (i < (size_t)count); i++)
|
||||
{
|
||||
n = cJSON_CreateNumber(numbers[i]);
|
||||
if(!n)
|
||||
@@ -2507,10 +2646,14 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
|
||||
p = n;
|
||||
}
|
||||
|
||||
if (a && a->child) {
|
||||
a->child->prev = n;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
|
||||
{
|
||||
size_t i = 0;
|
||||
cJSON *n = NULL;
|
||||
@@ -2543,6 +2686,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
|
||||
p = n;
|
||||
}
|
||||
|
||||
if (a && a->child) {
|
||||
a->child->prev = n;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -2614,6 +2761,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
if (newitem && newitem->child)
|
||||
{
|
||||
newitem->child->prev = newchild;
|
||||
}
|
||||
|
||||
return newitem;
|
||||
|
||||
@@ -2626,69 +2777,96 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void skip_oneline_comment(char **input)
|
||||
{
|
||||
*input += static_strlen("//");
|
||||
|
||||
for (; (*input)[0] != '\0'; ++(*input))
|
||||
{
|
||||
if ((*input)[0] == '\n') {
|
||||
*input += static_strlen("\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void skip_multiline_comment(char **input)
|
||||
{
|
||||
*input += static_strlen("/*");
|
||||
|
||||
for (; (*input)[0] != '\0'; ++(*input))
|
||||
{
|
||||
if (((*input)[0] == '*') && ((*input)[1] == '/'))
|
||||
{
|
||||
*input += static_strlen("*/");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void minify_string(char **input, char **output) {
|
||||
(*output)[0] = (*input)[0];
|
||||
*input += static_strlen("\"");
|
||||
*output += static_strlen("\"");
|
||||
|
||||
|
||||
for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
|
||||
(*output)[0] = (*input)[0];
|
||||
|
||||
if ((*input)[0] == '\"') {
|
||||
(*output)[0] = '\"';
|
||||
*input += static_strlen("\"");
|
||||
*output += static_strlen("\"");
|
||||
return;
|
||||
} else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
|
||||
(*output)[1] = (*input)[1];
|
||||
*input += static_strlen("\"");
|
||||
*output += static_strlen("\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_Minify(char *json)
|
||||
{
|
||||
unsigned char *into = (unsigned char*)json;
|
||||
char *into = json;
|
||||
|
||||
if (json == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (*json)
|
||||
while (json[0] != '\0')
|
||||
{
|
||||
if (*json == ' ')
|
||||
switch (json[0])
|
||||
{
|
||||
json++;
|
||||
}
|
||||
else if (*json == '\t')
|
||||
{
|
||||
/* Whitespace characters. */
|
||||
json++;
|
||||
}
|
||||
else if (*json == '\r')
|
||||
{
|
||||
json++;
|
||||
}
|
||||
else if (*json=='\n')
|
||||
{
|
||||
json++;
|
||||
}
|
||||
else if ((*json == '/') && (json[1] == '/'))
|
||||
{
|
||||
/* double-slash comments, to end of line. */
|
||||
while (*json && (*json != '\n'))
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
json++;
|
||||
}
|
||||
}
|
||||
else if ((*json == '/') && (json[1] == '*'))
|
||||
{
|
||||
/* multiline comments. */
|
||||
while (*json && !((*json == '*') && (json[1] == '/')))
|
||||
{
|
||||
json++;
|
||||
}
|
||||
json += 2;
|
||||
}
|
||||
else if (*json == '\"')
|
||||
{
|
||||
/* string literals, which are \" sensitive. */
|
||||
*into++ = (unsigned char)*json++;
|
||||
while (*json && (*json != '\"'))
|
||||
{
|
||||
if (*json == '\\')
|
||||
break;
|
||||
|
||||
case '/':
|
||||
if (json[1] == '/')
|
||||
{
|
||||
*into++ = (unsigned char)*json++;
|
||||
skip_oneline_comment(&json);
|
||||
}
|
||||
*into++ = (unsigned char)*json++;
|
||||
}
|
||||
*into++ = (unsigned char)*json++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All other characters. */
|
||||
*into++ = (unsigned char)*json++;
|
||||
else if (json[1] == '*')
|
||||
{
|
||||
skip_multiline_comment(&json);
|
||||
} else {
|
||||
json++;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\"':
|
||||
minify_string(&json, (char**)&into);
|
||||
break;
|
||||
|
||||
default:
|
||||
into[0] = json[0];
|
||||
json++;
|
||||
into++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2798,7 +2976,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
|
||||
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
|
||||
{
|
||||
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
|
||||
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -2835,7 +3013,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
|
||||
return true;
|
||||
|
||||
case cJSON_Number:
|
||||
if (a->valuedouble == b->valuedouble)
|
||||
if (compare_double(a->valuedouble, b->valuedouble))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
148
cJSON.h
148
cJSON.h
@@ -28,10 +28,60 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#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 3 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 (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
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#define CJSON_CDECL __cdecl
|
||||
#define CJSON_STDCALL __stdcall
|
||||
|
||||
/* 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 CJSON_STDCALL
|
||||
#elif defined(CJSON_EXPORT_SYMBOLS)
|
||||
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
|
||||
#elif defined(CJSON_IMPORT_SYMBOLS)
|
||||
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
|
||||
#endif
|
||||
#else /* !__WINDOWS__ */
|
||||
#define CJSON_CDECL
|
||||
#define CJSON_STDCALL
|
||||
|
||||
#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
|
||||
|
||||
/* project version */
|
||||
#define CJSON_VERSION_MAJOR 1
|
||||
#define CJSON_VERSION_MINOR 7
|
||||
#define CJSON_VERSION_PATCH 1
|
||||
#define CJSON_VERSION_PATCH 15
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -74,55 +124,13 @@ typedef struct cJSON
|
||||
|
||||
typedef struct cJSON_Hooks
|
||||
{
|
||||
void *(*malloc_fn)(size_t sz);
|
||||
void (*free_fn)(void *ptr);
|
||||
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
|
||||
void *(CJSON_CDECL *malloc_fn)(size_t sz);
|
||||
void (CJSON_CDECL *free_fn)(void *ptr);
|
||||
} 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 (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
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
/* 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
|
||||
#elif defined(CJSON_IMPORT_SYMBOLS)
|
||||
#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
|
||||
|
||||
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
|
||||
* This is to prevent stack overflows. */
|
||||
#ifndef CJSON_NESTING_LIMIT
|
||||
@@ -138,9 +146,11 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
|
||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
|
||||
/* 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 so will match cJSON_GetErrorPtr(). */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
|
||||
|
||||
/* Render a cJSON entity to text for transfer/storage. */
|
||||
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
|
||||
@@ -152,11 +162,11 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON
|
||||
/* 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);
|
||||
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
|
||||
@@ -165,8 +175,9 @@ CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *st
|
||||
/* 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. */
|
||||
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
|
||||
|
||||
/* Check if the item is a string and return its valuestring */
|
||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
|
||||
/* Check item type and return its value */
|
||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
|
||||
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
|
||||
|
||||
/* These functions check the type of an item */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
|
||||
@@ -195,29 +206,30 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
|
||||
/* Create a string where valuestring references a string so
|
||||
* it will not be freed by cJSON_Delete */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
|
||||
/* Create an object/arrray that only references it's elements so
|
||||
/* Create an object/array that only references it's elements so
|
||||
* they will not be freed by cJSON_Delete */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
|
||||
|
||||
/* These utilities create an Array of count items. */
|
||||
/* These utilities create an Array of count items.
|
||||
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
|
||||
|
||||
/* Append item to the specified array/object. */
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
CJSON_PUBLIC(cJSON_bool) 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.
|
||||
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
|
||||
* writing to `item->string` */
|
||||
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
|
||||
CJSON_PUBLIC(cJSON_bool) 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. */
|
||||
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||
|
||||
/* Remove/Detatch items from Arrays/Objects. */
|
||||
/* Remove/Detach items from Arrays/Objects. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
|
||||
@@ -227,22 +239,24 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
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
|
||||
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. */
|
||||
* 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. */
|
||||
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
|
||||
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
|
||||
|
||||
|
||||
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
|
||||
* The input pointer json cannot point to a read-only address area, such as a string constant,
|
||||
* but should point to a readable and writable address area. */
|
||||
CJSON_PUBLIC(void) cJSON_Minify(char *json);
|
||||
|
||||
/* Helper functions for creating and adding items to an object at the same time.
|
||||
@@ -262,6 +276,8 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c
|
||||
/* helper for the cJSON_SetNumberValue macro */
|
||||
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
|
||||
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
|
||||
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
|
||||
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
|
||||
|
||||
/* Macro for iterating over an array or object */
|
||||
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning (pop)
|
||||
@@ -50,7 +53,14 @@
|
||||
#include "cJSON_Utils.h"
|
||||
|
||||
/* define our own boolean type */
|
||||
#ifdef true
|
||||
#undef true
|
||||
#endif
|
||||
#define true ((cJSON_bool)1)
|
||||
|
||||
#ifdef false
|
||||
#undef false
|
||||
#endif
|
||||
#define false ((cJSON_bool)0)
|
||||
|
||||
static unsigned char* cJSONUtils_strdup(const unsigned char* const string)
|
||||
@@ -98,6 +108,14 @@ static int compare_strings(const unsigned char *string1, const unsigned char *st
|
||||
return tolower(*string1) - tolower(*string2);
|
||||
}
|
||||
|
||||
/* securely comparison of floating-point variables */
|
||||
static cJSON_bool compare_double(double a, double b)
|
||||
{
|
||||
double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
|
||||
return (fabs(a - b) <= maxVal * DBL_EPSILON);
|
||||
}
|
||||
|
||||
|
||||
/* Compare the next path element of two JSON pointers, two NULL pointers are considered unequal: */
|
||||
static cJSON_bool compare_pointers(const unsigned char *name, const unsigned char *pointer, const cJSON_bool case_sensitive)
|
||||
{
|
||||
@@ -158,13 +176,14 @@ static void encode_string_as_pointer(unsigned char *destination, const unsigned
|
||||
{
|
||||
if (source[0] == '/')
|
||||
{
|
||||
destination[0] = '~';
|
||||
destination[1] = '1';
|
||||
destination++;
|
||||
}
|
||||
else if (source[0] == '~')
|
||||
{
|
||||
destination[0] = '~';
|
||||
destination[1] = '1';
|
||||
destination[1] = '0';
|
||||
destination++;
|
||||
}
|
||||
else
|
||||
@@ -209,6 +228,7 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje
|
||||
if (child_index > ULONG_MAX)
|
||||
{
|
||||
cJSON_free(target_pointer);
|
||||
cJSON_free(full_pointer);
|
||||
return NULL;
|
||||
}
|
||||
sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* /<array_index><path> */
|
||||
@@ -383,7 +403,7 @@ static cJSON *detach_item_from_array(cJSON *array, size_t which)
|
||||
/* item doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
if (c->prev)
|
||||
if (c != array->child)
|
||||
{
|
||||
/* not the first element */
|
||||
c->prev->next = c->next;
|
||||
@@ -392,10 +412,14 @@ static cJSON *detach_item_from_array(cJSON *array, size_t which)
|
||||
{
|
||||
c->next->prev = c->prev;
|
||||
}
|
||||
if (c==array->child)
|
||||
if (c == array->child)
|
||||
{
|
||||
array->child = c->next;
|
||||
}
|
||||
else if (c->next == NULL)
|
||||
{
|
||||
array->child->prev = c->prev;
|
||||
}
|
||||
/* make sure the detached item doesn't point anywhere anymore */
|
||||
c->prev = c->next = NULL;
|
||||
|
||||
@@ -499,6 +523,7 @@ static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
|
||||
{
|
||||
/* Split the lists */
|
||||
second->prev->next = NULL;
|
||||
second->prev = NULL;
|
||||
}
|
||||
|
||||
/* Recursively sort the sub-lists. */
|
||||
@@ -510,7 +535,7 @@ static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
|
||||
while ((first != NULL) && (second != NULL))
|
||||
{
|
||||
cJSON *smaller = NULL;
|
||||
if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, false) < 0)
|
||||
if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, case_sensitive) < 0)
|
||||
{
|
||||
smaller = first;
|
||||
}
|
||||
@@ -587,7 +612,7 @@ static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case_sensiti
|
||||
{
|
||||
case cJSON_Number:
|
||||
/* numeric mismatch. */
|
||||
if ((a->valueint != b->valueint) || (a->valuedouble != b->valuedouble))
|
||||
if ((a->valueint != b->valueint) || (!compare_double(a->valuedouble, b->valuedouble)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -935,7 +960,9 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_
|
||||
|
||||
/* split pointer in parent and child */
|
||||
parent_pointer = cJSONUtils_strdup((unsigned char*)path->valuestring);
|
||||
child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/');
|
||||
if (parent_pointer) {
|
||||
child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/');
|
||||
}
|
||||
if (child_pointer != NULL)
|
||||
{
|
||||
child_pointer[0] = '\0';
|
||||
@@ -988,6 +1015,12 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_
|
||||
cJSON_AddItemToObject(parent, (char*)child_pointer, value);
|
||||
value = NULL;
|
||||
}
|
||||
else /* parent is not an object */
|
||||
{
|
||||
/* Couldn't find object to add to. */
|
||||
status = 9;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (value != NULL)
|
||||
@@ -1121,7 +1154,7 @@ static void create_patches(cJSON * const patches, const unsigned char * const pa
|
||||
switch (from->type & 0xFF)
|
||||
{
|
||||
case cJSON_Number:
|
||||
if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble))
|
||||
if ((from->valueint != to->valueint) || !compare_double(from->valuedouble, to->valuedouble))
|
||||
{
|
||||
compose_patch(patches, (const unsigned char*)"replace", path, NULL, to);
|
||||
}
|
||||
@@ -1375,6 +1408,10 @@ static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const c
|
||||
from_child = from->child;
|
||||
to_child = to->child;
|
||||
patch = cJSON_CreateObject();
|
||||
if (patch == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
while (from_child || to_child)
|
||||
{
|
||||
int diff;
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef cJSON_Utils__h
|
||||
#define cJSON_Utils__h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "cJSON.h"
|
||||
|
||||
/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
|
||||
@@ -72,3 +80,9 @@ CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const obje
|
||||
/* Sorts the members of the object into alphabetical order. */
|
||||
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object);
|
||||
CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,3 +26,9 @@ if (ENABLE_FUZZING)
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
if(ENABLE_CJSON_TEST)
|
||||
ADD_EXECUTABLE(fuzz_main fuzz_main.c cjson_read_fuzzer.c)
|
||||
TARGET_LINK_LIBRARIES(fuzz_main cjson)
|
||||
endif()
|
||||
|
||||
|
||||
77
fuzzing/cjson_read_fuzzer.c
Normal file
77
fuzzing/cjson_read_fuzzer.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../cJSON.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
cJSON *json;
|
||||
size_t offset = 4;
|
||||
unsigned char *copied;
|
||||
char *printed_json = NULL;
|
||||
int minify, require_termination, formatted, buffered;
|
||||
|
||||
|
||||
if(size <= offset) return 0;
|
||||
if(data[size-1] != '\0') return 0;
|
||||
if(data[0] != '1' && data[0] != '0') return 0;
|
||||
if(data[1] != '1' && data[1] != '0') return 0;
|
||||
if(data[2] != '1' && data[2] != '0') return 0;
|
||||
if(data[3] != '1' && data[3] != '0') return 0;
|
||||
|
||||
minify = data[0] == '1' ? 1 : 0;
|
||||
require_termination = data[1] == '1' ? 1 : 0;
|
||||
formatted = data[2] == '1' ? 1 : 0;
|
||||
buffered = data[3] == '1' ? 1 : 0;
|
||||
|
||||
json = cJSON_ParseWithOpts((const char*)data + offset, NULL, require_termination);
|
||||
|
||||
if(json == NULL) return 0;
|
||||
|
||||
if(buffered)
|
||||
{
|
||||
printed_json = cJSON_PrintBuffered(json, 1, formatted);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unbuffered printing */
|
||||
if(formatted)
|
||||
{
|
||||
printed_json = cJSON_Print(json);
|
||||
}
|
||||
else
|
||||
{
|
||||
printed_json = cJSON_PrintUnformatted(json);
|
||||
}
|
||||
}
|
||||
|
||||
if(printed_json != NULL) free(printed_json);
|
||||
|
||||
if(minify)
|
||||
{
|
||||
copied = (unsigned char*)malloc(size);
|
||||
if(copied == NULL) return 0;
|
||||
|
||||
memcpy(copied, data, size);
|
||||
|
||||
cJSON_Minify((char*)copied + offset);
|
||||
|
||||
free(copied);
|
||||
}
|
||||
|
||||
cJSON_Delete(json);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
54
fuzzing/fuzz_main.c
Normal file
54
fuzzing/fuzz_main.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */
|
||||
|
||||
/* fuzz target entry point, works without libFuzzer */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
char *buf = NULL;
|
||||
long siz_buf;
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
fprintf(stderr, "no input file\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
f = fopen(argv[1], "rb");
|
||||
if(f == NULL)
|
||||
{
|
||||
fprintf(stderr, "error opening input file %s\n", argv[1]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
|
||||
siz_buf = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
if(siz_buf < 1) goto err;
|
||||
|
||||
buf = (char*)malloc((size_t)siz_buf);
|
||||
if(buf == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc() failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(fread(buf, (size_t)siz_buf, 1, f) != 1)
|
||||
{
|
||||
fprintf(stderr, "fread() failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
(void)LLVMFuzzerTestOneInput((uint8_t*)buf, (size_t)siz_buf);
|
||||
|
||||
err:
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
18
fuzzing/ossfuzz.sh
Executable file
18
fuzzing/ossfuzz.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
# This script is meant to be run by
|
||||
# https://github.com/google/oss-fuzz/blob/master/projects/cjson/Dockerfile
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_CJSON_TEST=OFF ..
|
||||
make -j$(nproc)
|
||||
|
||||
$CXX $CXXFLAGS $SRC/cjson/fuzzing/cjson_read_fuzzer.c -I. \
|
||||
-o $OUT/cjson_read_fuzzer \
|
||||
$LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a
|
||||
|
||||
find $SRC/cjson/fuzzing/inputs -name "*" | \
|
||||
xargs zip $OUT/cjson_read_fuzzer_seed_corpus.zip
|
||||
|
||||
cp $SRC/cjson/fuzzing/json.dict $OUT/cjson_read_fuzzer.dict
|
||||
@@ -2,8 +2,8 @@
|
||||
set(CJSON_UTILS_FOUND @ENABLE_CJSON_UTILS@)
|
||||
|
||||
# The include directories used by cJSON
|
||||
set(CJSON_INCLUDE_DIRS "@prefix@/@includedir@")
|
||||
set(CJSON_INCLUDE_DIR "@prefix@/@includedir@")
|
||||
set(CJSON_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
|
||||
set(CJSON_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
|
||||
|
||||
get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
prefix=@prefix@
|
||||
libdir=${prefix}/@libdir@
|
||||
includedir=${prefix}/@includedir@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
|
||||
Name: libcjson
|
||||
Version: @version@
|
||||
Version: @PROJECT_VERSION@
|
||||
Description: Ultralightweight JSON parser in ANSI C
|
||||
URL: https://github.com/DaveGamble/cJSON
|
||||
Libs: -L${libdir} -lcjson
|
||||
Libs.Private: -lm
|
||||
Cflags: -I${includedir}
|
||||
Libs.private: -lm
|
||||
Cflags: -I${includedir} -I${includedir}/cjson
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
prefix=@prefix@
|
||||
libdir=${prefix}/@libdir@
|
||||
includedir=${prefix}/@includedir@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
|
||||
Name: libcjson_utils
|
||||
Version: @version@
|
||||
Version: @PROJECT_VERSION@
|
||||
Description: An implementation of JSON Pointer, Patch and Merge Patch based on cJSON.
|
||||
URL: https://github.com/DaveGamble/cJSON
|
||||
Libs: -L${libdir} -lcjson_utils
|
||||
Cflags: -I${includedir}
|
||||
Cflags: -I${includedir} -I${includedir}/cjson
|
||||
Requires: libcjson
|
||||
|
||||
27
library_config/uninstall.cmake
Normal file
27
library_config/uninstall.cmake
Normal file
@@ -0,0 +1,27 @@
|
||||
cmake_minimum_required(VERSION 2.8.5)
|
||||
|
||||
set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt")
|
||||
|
||||
if(NOT EXISTS ${MANIFEST})
|
||||
message(FATAL_ERROR "Cannot find install mainfest: ${MANIFEST}")
|
||||
endif()
|
||||
|
||||
file(STRINGS ${MANIFEST} files)
|
||||
foreach(file ${files})
|
||||
if(EXISTS ${file} OR IS_SYMLINK ${file})
|
||||
message(STATUS "Removing: ${file}")
|
||||
|
||||
execute_process(COMMAND rm -f ${file}
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_QUIET
|
||||
ERROR_VARIABLE stderr
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(NOT ${result} EQUAL 0)
|
||||
message(FATAL_ERROR "${stderr}")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Does-not-exist: ${file}")
|
||||
endif()
|
||||
endforeach(file)
|
||||
2
test.c
2
test.c
@@ -256,7 +256,7 @@ static void create_objects(void)
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* print the version */
|
||||
printf("Version: %s\n", cJSON_Version());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
if(ENABLE_CJSON_TEST)
|
||||
add_library(unity "${CJSON_LIBRARY_TYPE}" unity/src/unity.c)
|
||||
add_library(unity STATIC unity/src/unity.c)
|
||||
|
||||
# Disable -Werror for Unity
|
||||
if (FLAG_SUPPORTED_Werror)
|
||||
@@ -57,6 +57,7 @@ if(ENABLE_CJSON_TEST)
|
||||
compare_tests
|
||||
cjson_add
|
||||
readme_examples
|
||||
minify_tests
|
||||
)
|
||||
|
||||
option(ENABLE_VALGRIND OFF "Enable the valgrind memory checker for the tests.")
|
||||
@@ -72,6 +73,9 @@ if(ENABLE_CJSON_TEST)
|
||||
|
||||
foreach(unity_test ${unity_tests})
|
||||
add_executable("${unity_test}" "${unity_test}.c")
|
||||
if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
|
||||
target_sources(${unity_test} PRIVATE unity_setup.c)
|
||||
endif()
|
||||
target_link_libraries("${unity_test}" "${CJSON_LIB}" unity)
|
||||
if(MEMORYCHECK_COMMAND)
|
||||
add_test(NAME "${unity_test}"
|
||||
@@ -98,6 +102,9 @@ if(ENABLE_CJSON_TEST)
|
||||
foreach (cjson_utils_test ${cjson_utils_tests})
|
||||
add_executable("${cjson_utils_test}" "${cjson_utils_test}.c")
|
||||
target_link_libraries("${cjson_utils_test}" "${CJSON_LIB}" "${CJSON_UTILS_LIB}" unity)
|
||||
if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
|
||||
target_sources(${cjson_utils_test} PRIVATE unity_setup.c)
|
||||
endif()
|
||||
if(MEMORYCHECK_COMMAND)
|
||||
add_test(NAME "${cjson_utils_test}"
|
||||
COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${cjson_utils_test}")
|
||||
|
||||
@@ -28,15 +28,21 @@
|
||||
#include "unity/src/unity.h"
|
||||
#include "common.h"
|
||||
|
||||
static void *failing_malloc(size_t size)
|
||||
static void * CJSON_CDECL failing_malloc(size_t size)
|
||||
{
|
||||
(void)size;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* work around MSVC error C2322: '...' address of dillimport '...' is not static */
|
||||
static void CJSON_CDECL normal_free(void *pointer)
|
||||
{
|
||||
free(pointer);
|
||||
}
|
||||
|
||||
static cJSON_Hooks failing_hooks = {
|
||||
failing_malloc,
|
||||
free
|
||||
normal_free
|
||||
};
|
||||
|
||||
static void cjson_add_null_should_add_null(void)
|
||||
@@ -111,6 +117,50 @@ static void cjson_add_true_should_fail_on_allocation_failure(void)
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
static void cjson_create_int_array_should_fail_on_allocation_failure(void)
|
||||
{
|
||||
int numbers[] = {1, 2, 3};
|
||||
|
||||
cJSON_InitHooks(&failing_hooks);
|
||||
|
||||
TEST_ASSERT_NULL(cJSON_CreateIntArray(numbers, 3));
|
||||
|
||||
cJSON_InitHooks(NULL);
|
||||
}
|
||||
|
||||
static void cjson_create_float_array_should_fail_on_allocation_failure(void)
|
||||
{
|
||||
float numbers[] = {1.0f, 2.0f, 3.0f};
|
||||
|
||||
cJSON_InitHooks(&failing_hooks);
|
||||
|
||||
TEST_ASSERT_NULL(cJSON_CreateFloatArray(numbers, 3));
|
||||
|
||||
cJSON_InitHooks(NULL);
|
||||
}
|
||||
|
||||
static void cjson_create_double_array_should_fail_on_allocation_failure(void)
|
||||
{
|
||||
double numbers[] = {1.0, 2.0, 3.0};
|
||||
|
||||
cJSON_InitHooks(&failing_hooks);
|
||||
|
||||
TEST_ASSERT_NULL(cJSON_CreateDoubleArray(numbers, 3));
|
||||
|
||||
cJSON_InitHooks(NULL);
|
||||
}
|
||||
|
||||
static void cjson_create_string_array_should_fail_on_allocation_failure(void)
|
||||
{
|
||||
const char* strings[] = {"1", "2", "3"};
|
||||
|
||||
cJSON_InitHooks(&failing_hooks);
|
||||
|
||||
TEST_ASSERT_NULL(cJSON_CreateStringArray(strings, 3));
|
||||
|
||||
cJSON_InitHooks(NULL);
|
||||
}
|
||||
|
||||
static void cjson_add_false_should_add_false(void)
|
||||
{
|
||||
cJSON *root = cJSON_CreateObject();
|
||||
@@ -372,7 +422,7 @@ static void cjson_add_array_should_fail_on_allocation_failure(void)
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
||||
@@ -384,6 +434,11 @@ int main(void)
|
||||
RUN_TEST(cjson_add_true_should_fail_with_null_pointers);
|
||||
RUN_TEST(cjson_add_true_should_fail_on_allocation_failure);
|
||||
|
||||
RUN_TEST(cjson_create_int_array_should_fail_on_allocation_failure);
|
||||
RUN_TEST(cjson_create_float_array_should_fail_on_allocation_failure);
|
||||
RUN_TEST(cjson_create_double_array_should_fail_on_allocation_failure);
|
||||
RUN_TEST(cjson_create_string_array_should_fail_on_allocation_failure);
|
||||
|
||||
RUN_TEST(cjson_add_false_should_add_false);
|
||||
RUN_TEST(cjson_add_false_should_fail_with_null_pointers);
|
||||
RUN_TEST(cjson_add_false_should_fail_on_allocation_failure);
|
||||
|
||||
@@ -64,6 +64,9 @@ static void cjson_compare_should_compare_numbers(void)
|
||||
TEST_ASSERT_TRUE(compare_from_string("1", "1", false));
|
||||
TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", true));
|
||||
TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", false));
|
||||
TEST_ASSERT_TRUE(compare_from_string("1E100", "10E99", false));
|
||||
|
||||
TEST_ASSERT_FALSE(compare_from_string("0.5E-100", "0.5E-101", false));
|
||||
|
||||
TEST_ASSERT_FALSE(compare_from_string("1", "2", true));
|
||||
TEST_ASSERT_FALSE(compare_from_string("1", "2", false));
|
||||
@@ -186,7 +189,7 @@ static void cjson_compare_should_compare_objects(void)
|
||||
false))
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
||||
|
||||
@@ -80,5 +80,12 @@
|
||||
"doc": { "foo": ["bar"] },
|
||||
"patch": [ { "op": "add", "path": "/foo/-", "value": ["abc", "def"] }],
|
||||
"expected": {"foo": ["bar", ["abc", "def"]] }
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"comment": "15",
|
||||
"doc": {"foo": {"bar": 1}},
|
||||
"patch": [{"op": "add", "path": "/foo/bar/baz", "value": "5"}],
|
||||
"error": "attempting to add to subfield of non-object"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -214,6 +214,7 @@
|
||||
|
||||
{ "doc": {"foo": null},
|
||||
"patch": [{"op": "test", "path": "/foo", "value": null}],
|
||||
"expected": {"foo": null},
|
||||
"comment": "null value should be valid obj property" },
|
||||
|
||||
{ "doc": {"foo": null},
|
||||
@@ -243,14 +244,17 @@
|
||||
|
||||
{ "doc": {"foo": {"foo": 1, "bar": 2}},
|
||||
"patch": [{"op": "test", "path": "/foo", "value": {"bar": 2, "foo": 1}}],
|
||||
"expected": {"foo": {"foo": 1, "bar": 2}},
|
||||
"comment": "test should pass despite rearrangement" },
|
||||
|
||||
{ "doc": {"foo": [{"foo": 1, "bar": 2}]},
|
||||
"patch": [{"op": "test", "path": "/foo", "value": [{"bar": 2, "foo": 1}]}],
|
||||
"expected": {"foo": [{"foo": 1, "bar": 2}]},
|
||||
"comment": "test should pass despite (nested) rearrangement" },
|
||||
|
||||
{ "doc": {"foo": {"bar": [1, 2, 5, 4]}},
|
||||
"patch": [{"op": "test", "path": "/foo", "value": {"bar": [1, 2, 5, 4]}}],
|
||||
"expected": {"foo": {"bar": [1, 2, 5, 4]}},
|
||||
"comment": "test should pass - no error" },
|
||||
|
||||
{ "doc": {"foo": {"bar": [1, 2, 5, 4]}},
|
||||
@@ -264,7 +268,8 @@
|
||||
|
||||
{ "comment": "Empty-string element",
|
||||
"doc": { "": 1 },
|
||||
"patch": [{"op": "test", "path": "/", "value": 1}] },
|
||||
"patch": [{"op": "test", "path": "/", "value": 1}],
|
||||
"expected": { "": 1 } },
|
||||
|
||||
{ "doc": {
|
||||
"foo": ["bar", "baz"],
|
||||
@@ -288,8 +293,23 @@
|
||||
{"op": "test", "path": "/i\\j", "value": 5},
|
||||
{"op": "test", "path": "/k\"l", "value": 6},
|
||||
{"op": "test", "path": "/ ", "value": 7},
|
||||
{"op": "test", "path": "/m~0n", "value": 8}] },
|
||||
|
||||
{"op": "test", "path": "/m~0n", "value": 8}],
|
||||
"expected": {
|
||||
"": 0,
|
||||
" ": 7,
|
||||
"a/b": 1,
|
||||
"c%d": 2,
|
||||
"e^f": 3,
|
||||
"foo": [
|
||||
"bar",
|
||||
"baz"
|
||||
],
|
||||
"g|h": 4,
|
||||
"i\\j": 5,
|
||||
"k\"l": 6,
|
||||
"m~n": 8
|
||||
}
|
||||
},
|
||||
{ "comment": "Move to same location has no effect",
|
||||
"doc": {"foo": 1},
|
||||
"patch": [{"op": "move", "from": "/foo", "path": "/foo"}],
|
||||
@@ -388,11 +408,21 @@
|
||||
"patch": [ { "op": "copy", "path": "/-" } ],
|
||||
"error": "missing 'from' parameter" },
|
||||
|
||||
{ "comment": "missing from location to copy",
|
||||
"doc": { "foo": 1 },
|
||||
"patch": [ { "op": "copy", "from": "/bar", "path": "/foo" } ],
|
||||
"error": "missing 'from' location" },
|
||||
|
||||
{ "comment": "missing from parameter to move",
|
||||
"doc": { "foo": 1 },
|
||||
"patch": [ { "op": "move", "path": "" } ],
|
||||
"error": "missing 'from' parameter" },
|
||||
|
||||
{ "comment": "missing from location to move",
|
||||
"doc": { "foo": 1 },
|
||||
"patch": [ { "op": "move", "from": "/bar", "path": "/foo" } ],
|
||||
"error": "missing 'from' location" },
|
||||
|
||||
{ "comment": "duplicate ops",
|
||||
"doc": { "foo": "bar" },
|
||||
"patch": [ { "op": "add", "path": "/baz", "value": "qux",
|
||||
|
||||
@@ -66,7 +66,7 @@ static cJSON_bool test_apply_patch(const cJSON * const test)
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Testing unkown\n");
|
||||
printf("Testing unknown\n");
|
||||
}
|
||||
|
||||
disabled = cJSON_GetObjectItemCaseSensitive(test, "disabled");
|
||||
|
||||
174
tests/minify_tests.c
Normal file
174
tests/minify_tests.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright (c) 2009-2019 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_minify_should_not_overflow_buffer(void)
|
||||
{
|
||||
char unclosed_multiline_comment[] = "/* bla";
|
||||
char pending_escape[] = "\"\\";
|
||||
|
||||
cJSON_Minify(unclosed_multiline_comment);
|
||||
TEST_ASSERT_EQUAL_STRING("", unclosed_multiline_comment);
|
||||
|
||||
cJSON_Minify(pending_escape);
|
||||
TEST_ASSERT_EQUAL_STRING("\"\\", pending_escape);
|
||||
}
|
||||
|
||||
static void cjson_minify_should_remove_single_line_comments(void)
|
||||
{
|
||||
const char to_minify[] = "{// this is {} \"some kind\" of [] comment /*, don't you see\n}";
|
||||
|
||||
char* minified = (char*) malloc(sizeof(to_minify));
|
||||
TEST_ASSERT_NOT_NULL(minified);
|
||||
strcpy(minified, to_minify);
|
||||
|
||||
cJSON_Minify(minified);
|
||||
TEST_ASSERT_EQUAL_STRING("{}", minified);
|
||||
|
||||
free(minified);
|
||||
}
|
||||
|
||||
static void cjson_minify_should_remove_spaces(void)
|
||||
{
|
||||
const char to_minify[] = "{ \"key\":\ttrue\r\n }";
|
||||
|
||||
char* minified = (char*) malloc(sizeof(to_minify));
|
||||
TEST_ASSERT_NOT_NULL(minified);
|
||||
strcpy(minified, to_minify);
|
||||
|
||||
cJSON_Minify(minified);
|
||||
TEST_ASSERT_EQUAL_STRING("{\"key\":true}", minified);
|
||||
|
||||
free(minified);
|
||||
}
|
||||
|
||||
static void cjson_minify_should_remove_multiline_comments(void)
|
||||
{
|
||||
const char to_minify[] = "{/* this is\n a /* multi\n //line \n {comment \"\\\" */}";
|
||||
|
||||
char* minified = (char*) malloc(sizeof(to_minify));
|
||||
TEST_ASSERT_NOT_NULL(minified);
|
||||
strcpy(minified, to_minify);
|
||||
|
||||
cJSON_Minify(minified);
|
||||
TEST_ASSERT_EQUAL_STRING("{}", minified);
|
||||
|
||||
free(minified);
|
||||
}
|
||||
|
||||
static void cjson_minify_should_not_modify_strings(void)
|
||||
{
|
||||
const char to_minify[] = "\"this is a string \\\" \\t bla\"";
|
||||
|
||||
char* minified = (char*) malloc(sizeof(to_minify));
|
||||
TEST_ASSERT_NOT_NULL(minified);
|
||||
strcpy(minified, to_minify);
|
||||
|
||||
cJSON_Minify(minified);
|
||||
TEST_ASSERT_EQUAL_STRING(to_minify, minified);
|
||||
|
||||
free(minified);
|
||||
}
|
||||
|
||||
static void cjson_minify_should_minify_json(void) {
|
||||
const char to_minify[] =
|
||||
"{\n"
|
||||
" \"glossary\": { // comment\n"
|
||||
" \"title\": \"example glossary\",\n"
|
||||
" /* multi\n"
|
||||
" line */\n"
|
||||
" \"GlossDiv\": {\n"
|
||||
" \"title\": \"S\",\n"
|
||||
" \"GlossList\": {\n"
|
||||
" \"GlossEntry\": {\n"
|
||||
" \"ID\": \"SGML\",\n"
|
||||
" \"SortAs\": \"SGML\",\n"
|
||||
" \"Acronym\": \"SGML\",\n"
|
||||
" \"Abbrev\": \"ISO 8879:1986\",\n"
|
||||
" \"GlossDef\": {\n"
|
||||
" \"GlossSeeAlso\": [\"GML\", \"XML\"]\n"
|
||||
" },\n"
|
||||
" \"GlossSee\": \"markup\"\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}";
|
||||
const char* minified =
|
||||
"{"
|
||||
"\"glossary\":{"
|
||||
"\"title\":\"example glossary\","
|
||||
"\"GlossDiv\":{"
|
||||
"\"title\":\"S\","
|
||||
"\"GlossList\":{"
|
||||
"\"GlossEntry\":{"
|
||||
"\"ID\":\"SGML\","
|
||||
"\"SortAs\":\"SGML\","
|
||||
"\"Acronym\":\"SGML\","
|
||||
"\"Abbrev\":\"ISO 8879:1986\","
|
||||
"\"GlossDef\":{"
|
||||
"\"GlossSeeAlso\":[\"GML\",\"XML\"]"
|
||||
"},"
|
||||
"\"GlossSee\":\"markup\""
|
||||
"}"
|
||||
"}"
|
||||
"}"
|
||||
"}"
|
||||
"}";
|
||||
|
||||
char *buffer = (char*) malloc(sizeof(to_minify));
|
||||
strcpy(buffer, to_minify);
|
||||
|
||||
cJSON_Minify(buffer);
|
||||
TEST_ASSERT_EQUAL_STRING(minified, buffer);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void cjson_minify_should_not_loop_infinitely(void) {
|
||||
char string[] = { '8', ' ', '/', ' ', '5', '\n', '\0' };
|
||||
/* this should not be an infinite loop */
|
||||
cJSON_Minify(string);
|
||||
}
|
||||
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
||||
RUN_TEST(cjson_minify_should_not_overflow_buffer);
|
||||
RUN_TEST(cjson_minify_should_minify_json);
|
||||
RUN_TEST(cjson_minify_should_remove_single_line_comments);
|
||||
RUN_TEST(cjson_minify_should_remove_multiline_comments);
|
||||
RUN_TEST(cjson_minify_should_remove_spaces);
|
||||
RUN_TEST(cjson_minify_should_not_modify_strings);
|
||||
RUN_TEST(cjson_minify_should_not_loop_infinitely);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
@@ -127,6 +127,28 @@ static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
|
||||
cJSON_Delete(item);
|
||||
}
|
||||
|
||||
static void cjson_get_object_item_should_not_crash_with_array(void) {
|
||||
cJSON *array = NULL;
|
||||
cJSON *found = NULL;
|
||||
array = cJSON_Parse("[1]");
|
||||
|
||||
found = cJSON_GetObjectItem(array, "name");
|
||||
TEST_ASSERT_NULL(found);
|
||||
|
||||
cJSON_Delete(array);
|
||||
}
|
||||
|
||||
static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void) {
|
||||
cJSON *array = NULL;
|
||||
cJSON *found = NULL;
|
||||
array = cJSON_Parse("[1]");
|
||||
|
||||
found = cJSON_GetObjectItemCaseSensitive(array, "name");
|
||||
TEST_ASSERT_NULL(found);
|
||||
|
||||
cJSON_Delete(array);
|
||||
}
|
||||
|
||||
static void typecheck_functions_should_check_type(void)
|
||||
{
|
||||
cJSON invalid[1];
|
||||
@@ -233,6 +255,7 @@ static void cjson_detach_item_via_pointer_should_detach_items(void)
|
||||
list[3].prev = &(list[2]);
|
||||
list[2].prev = &(list[1]);
|
||||
list[1].prev = &(list[0]);
|
||||
list[0].prev = &(list[3]);
|
||||
|
||||
parent->child = &list[0];
|
||||
|
||||
@@ -244,7 +267,7 @@ static void cjson_detach_item_via_pointer_should_detach_items(void)
|
||||
/* detach beginning (list[0]) */
|
||||
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach beginning.");
|
||||
TEST_ASSERT_TRUE_MESSAGE((list[0].prev == NULL) && (list[0].next == NULL), "Didn't set pointers of detached item to NULL.");
|
||||
TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (parent->child == &(list[2])), "Didn't set the new beginning.");
|
||||
TEST_ASSERT_TRUE_MESSAGE((list[2].prev == &(list[3])) && (parent->child == &(list[2])), "Didn't set the new beginning.");
|
||||
|
||||
/* detach end (list[3])*/
|
||||
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[3])) == &(list[3]), "Failed to detach end.");
|
||||
@@ -284,7 +307,7 @@ static void cjson_replace_item_via_pointer_should_replace_items(void)
|
||||
|
||||
/* replace beginning */
|
||||
TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, beginning, &(replacements[0])));
|
||||
TEST_ASSERT_NULL(replacements[0].prev);
|
||||
TEST_ASSERT_TRUE(replacements[0].prev == end);
|
||||
TEST_ASSERT_TRUE(replacements[0].next == middle);
|
||||
TEST_ASSERT_TRUE(middle->prev == &(replacements[0]));
|
||||
TEST_ASSERT_TRUE(array->child == &(replacements[0]));
|
||||
@@ -309,13 +332,15 @@ static void cjson_replace_item_in_object_should_preserve_name(void)
|
||||
cJSON root[1] = {{ NULL, NULL, NULL, 0, NULL, 0, 0, NULL }};
|
||||
cJSON *child = NULL;
|
||||
cJSON *replacement = NULL;
|
||||
cJSON_bool flag = false;
|
||||
|
||||
child = cJSON_CreateNumber(1);
|
||||
TEST_ASSERT_NOT_NULL(child);
|
||||
replacement = cJSON_CreateNumber(2);
|
||||
TEST_ASSERT_NOT_NULL(replacement);
|
||||
|
||||
cJSON_AddItemToObject(root, "child", child);
|
||||
flag = cJSON_AddItemToObject(root, "child", child);
|
||||
TEST_ASSERT_TRUE_MESSAGE(flag, "add item to object failed");
|
||||
cJSON_ReplaceItemInObject(root, "child", replacement);
|
||||
|
||||
TEST_ASSERT_TRUE(root->child == replacement);
|
||||
@@ -324,7 +349,7 @@ static void cjson_replace_item_in_object_should_preserve_name(void)
|
||||
cJSON_Delete(replacement);
|
||||
}
|
||||
|
||||
static void cjson_functions_shouldnt_crash_with_null_pointers(void)
|
||||
static void cjson_functions_should_not_crash_with_null_pointers(void)
|
||||
{
|
||||
char buffer[10];
|
||||
cJSON *item = cJSON_CreateString("item");
|
||||
@@ -387,19 +412,19 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
|
||||
cJSON_DeleteItemFromObject(item, NULL);
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item");
|
||||
cJSON_DeleteItemFromObjectCaseSensitive(item, NULL);
|
||||
cJSON_InsertItemInArray(NULL, 0, item);
|
||||
cJSON_InsertItemInArray(item, 0, NULL);
|
||||
TEST_ASSERT_FALSE(cJSON_InsertItemInArray(NULL, 0, item));
|
||||
TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, NULL, item));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, item, NULL));
|
||||
cJSON_ReplaceItemInArray(item, 0, NULL);
|
||||
cJSON_ReplaceItemInArray(NULL, 0, item);
|
||||
cJSON_ReplaceItemInObject(NULL, "item", item);
|
||||
cJSON_ReplaceItemInObject(item, NULL, item);
|
||||
cJSON_ReplaceItemInObject(item, "item", NULL);
|
||||
cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item);
|
||||
cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item);
|
||||
cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL);
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(item, 0, NULL));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(NULL, 0, item));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(NULL, "item", item));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, NULL, item));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, "item", NULL));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item));
|
||||
TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL));
|
||||
TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true));
|
||||
TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false));
|
||||
TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, false));
|
||||
@@ -410,7 +435,7 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
|
||||
cJSON_Delete(item);
|
||||
}
|
||||
|
||||
static void *failing_realloc(void *pointer, size_t size)
|
||||
static void * CJSON_CDECL failing_realloc(void *pointer, size_t size)
|
||||
{
|
||||
(void)size;
|
||||
(void)pointer;
|
||||
@@ -463,6 +488,19 @@ static void cjson_get_string_value_should_get_a_string(void)
|
||||
cJSON_Delete(string);
|
||||
}
|
||||
|
||||
static void cjson_get_number_value_should_get_a_number(void)
|
||||
{
|
||||
cJSON *string = cJSON_CreateString("test");
|
||||
cJSON *number = cJSON_CreateNumber(1);
|
||||
|
||||
TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble);
|
||||
TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string));
|
||||
TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL));
|
||||
|
||||
cJSON_Delete(number);
|
||||
cJSON_Delete(string);
|
||||
}
|
||||
|
||||
static void cjson_create_string_reference_should_create_a_string_reference(void) {
|
||||
const char *string = "I am a string!";
|
||||
|
||||
@@ -508,7 +546,111 @@ static void cjson_create_array_reference_should_create_an_array_reference(void)
|
||||
cJSON_Delete(number_reference);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
static void cjson_add_item_to_object_or_array_should_not_add_itself(void)
|
||||
{
|
||||
cJSON *object = cJSON_CreateObject();
|
||||
cJSON *array = cJSON_CreateArray();
|
||||
cJSON_bool flag = false;
|
||||
|
||||
flag = cJSON_AddItemToObject(object, "key", object);
|
||||
TEST_ASSERT_FALSE_MESSAGE(flag, "add an object to itself should fail");
|
||||
|
||||
flag = cJSON_AddItemToArray(array, array);
|
||||
TEST_ASSERT_FALSE_MESSAGE(flag, "add an array to itself should fail");
|
||||
|
||||
cJSON_Delete(object);
|
||||
cJSON_Delete(array);
|
||||
}
|
||||
|
||||
static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)
|
||||
{
|
||||
cJSON *object = cJSON_CreateObject();
|
||||
cJSON *number = cJSON_CreateNumber(42);
|
||||
char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks);
|
||||
|
||||
TEST_ASSERT_NOT_NULL(object);
|
||||
TEST_ASSERT_NOT_NULL(number);
|
||||
TEST_ASSERT_NOT_NULL(name);
|
||||
|
||||
number->string = name;
|
||||
|
||||
/* The following should not have a use after free
|
||||
* that would show up in valgrind or with AddressSanitizer */
|
||||
cJSON_AddItemToObject(object, number->string, number);
|
||||
|
||||
cJSON_Delete(object);
|
||||
}
|
||||
|
||||
static void cjson_delete_item_from_array_should_not_broken_list_structure(void)
|
||||
{
|
||||
const char expected_json1[] = "{\"rd\":[{\"a\":\"123\"}]}";
|
||||
const char expected_json2[] = "{\"rd\":[{\"a\":\"123\"},{\"b\":\"456\"}]}";
|
||||
const char expected_json3[] = "{\"rd\":[{\"b\":\"456\"}]}";
|
||||
char *str1 = NULL;
|
||||
char *str2 = NULL;
|
||||
char *str3 = NULL;
|
||||
|
||||
cJSON *root = cJSON_Parse("{}");
|
||||
|
||||
cJSON *array = cJSON_AddArrayToObject(root, "rd");
|
||||
cJSON *item1 = cJSON_Parse("{\"a\":\"123\"}");
|
||||
cJSON *item2 = cJSON_Parse("{\"b\":\"456\"}");
|
||||
|
||||
cJSON_AddItemToArray(array, item1);
|
||||
str1 = cJSON_PrintUnformatted(root);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_json1, str1);
|
||||
free(str1);
|
||||
|
||||
cJSON_AddItemToArray(array, item2);
|
||||
str2 = cJSON_PrintUnformatted(root);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_json2, str2);
|
||||
free(str2);
|
||||
|
||||
/* this should not broken list structure */
|
||||
cJSON_DeleteItemFromArray(array, 0);
|
||||
str3 = cJSON_PrintUnformatted(root);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_json3, str3);
|
||||
free(str3);
|
||||
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
|
||||
{
|
||||
cJSON *root = cJSON_Parse("{}");
|
||||
const char *stringvalue = "valuestring could be changed safely";
|
||||
const char *reference_valuestring = "reference item should be freed by yourself";
|
||||
const char *short_valuestring = "shorter valuestring";
|
||||
const char *long_valuestring = "new valuestring which much longer than previous should be changed safely";
|
||||
cJSON *item1 = cJSON_CreateString(stringvalue);
|
||||
cJSON *item2 = cJSON_CreateStringReference(reference_valuestring);
|
||||
char *ptr1 = NULL;
|
||||
char *return_value = NULL;
|
||||
|
||||
cJSON_AddItemToObject(root, "one", item1);
|
||||
cJSON_AddItemToObject(root, "two", item2);
|
||||
|
||||
ptr1 = item1->valuestring;
|
||||
return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), short_valuestring);
|
||||
TEST_ASSERT_NOT_NULL(return_value);
|
||||
TEST_ASSERT_EQUAL_PTR_MESSAGE(ptr1, return_value, "new valuestring shorter than old should not reallocate memory");
|
||||
TEST_ASSERT_EQUAL_STRING(short_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
|
||||
|
||||
/* we needn't to free the original valuestring manually */
|
||||
ptr1 = item1->valuestring;
|
||||
return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), long_valuestring);
|
||||
TEST_ASSERT_NOT_NULL(return_value);
|
||||
TEST_ASSERT_NOT_EQUAL_MESSAGE(ptr1, return_value, "new valuestring longer than old should reallocate memory")
|
||||
TEST_ASSERT_EQUAL_STRING(long_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
|
||||
|
||||
return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "two"), long_valuestring);
|
||||
TEST_ASSERT_NULL_MESSAGE(return_value, "valuestring of reference object should not be changed");
|
||||
TEST_ASSERT_EQUAL_STRING(reference_valuestring, cJSON_GetObjectItem(root, "two")->valuestring);
|
||||
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
||||
@@ -516,20 +658,27 @@ int main(void)
|
||||
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(cjson_get_object_item_should_not_crash_with_array);
|
||||
RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);
|
||||
RUN_TEST(typecheck_functions_should_check_type);
|
||||
RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
|
||||
RUN_TEST(cjson_set_number_value_should_set_numbers);
|
||||
RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
|
||||
RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
|
||||
RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
|
||||
RUN_TEST(cjson_functions_shouldnt_crash_with_null_pointers);
|
||||
RUN_TEST(cjson_functions_should_not_crash_with_null_pointers);
|
||||
RUN_TEST(ensure_should_fail_on_failed_realloc);
|
||||
RUN_TEST(skip_utf8_bom_should_skip_bom);
|
||||
RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
|
||||
RUN_TEST(cjson_get_string_value_should_get_a_string);
|
||||
RUN_TEST(cjson_get_number_value_should_get_a_number);
|
||||
RUN_TEST(cjson_create_string_reference_should_create_a_string_reference);
|
||||
RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
|
||||
RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
|
||||
RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself);
|
||||
RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
|
||||
RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure);
|
||||
RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
@@ -90,6 +90,10 @@ static void misc_tests(void)
|
||||
/* Misc tests */
|
||||
int numbers[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
cJSON *object = NULL;
|
||||
cJSON *object1 = NULL;
|
||||
cJSON *object2 = NULL;
|
||||
cJSON *object3 = NULL;
|
||||
cJSON *object4 = NULL;
|
||||
cJSON *nums = NULL;
|
||||
cJSON *num6 = NULL;
|
||||
char *pointer = NULL;
|
||||
@@ -112,7 +116,23 @@ static void misc_tests(void)
|
||||
TEST_ASSERT_EQUAL_STRING("", pointer);
|
||||
free(pointer);
|
||||
|
||||
object1 = cJSON_CreateObject();
|
||||
object2 = cJSON_CreateString("m~n");
|
||||
cJSON_AddItemToObject(object1, "m~n", object2);
|
||||
pointer = cJSONUtils_FindPointerFromObjectTo(object1, object2);
|
||||
TEST_ASSERT_EQUAL_STRING("/m~0n",pointer);
|
||||
free(pointer);
|
||||
|
||||
object3 = cJSON_CreateObject();
|
||||
object4 = cJSON_CreateString("m/n");
|
||||
cJSON_AddItemToObject(object3, "m/n", object4);
|
||||
pointer = cJSONUtils_FindPointerFromObjectTo(object3, object4);
|
||||
TEST_ASSERT_EQUAL_STRING("/m~1n",pointer);
|
||||
free(pointer);
|
||||
|
||||
cJSON_Delete(object);
|
||||
cJSON_Delete(object1);
|
||||
cJSON_Delete(object3);
|
||||
}
|
||||
|
||||
static void sort_tests(void)
|
||||
|
||||
@@ -90,7 +90,8 @@ static void parse_array_should_parse_arrays_with_one_element(void)
|
||||
|
||||
assert_parse_array("[[]]");
|
||||
assert_has_child(item);
|
||||
assert_is_array(item->child);
|
||||
TEST_ASSERT_NOT_NULL(item->child);
|
||||
assert_has_type(item->child, cJSON_Array);
|
||||
assert_has_no_child(item->child);
|
||||
reset(item);
|
||||
|
||||
@@ -152,7 +153,7 @@ static void parse_array_should_not_parse_non_arrays(void)
|
||||
assert_not_array("\"[]hello world!\n\"");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item */
|
||||
memset(item, 0, sizeof(cJSON));
|
||||
|
||||
@@ -195,7 +195,62 @@ static void test12_should_not_be_parsed(void)
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
static void test13_should_be_parsed_without_null_termination(void)
|
||||
{
|
||||
cJSON *tree = NULL;
|
||||
const char test_13[] = "{" \
|
||||
"\"Image\":{" \
|
||||
"\"Width\":800," \
|
||||
"\"Height\":600," \
|
||||
"\"Title\":\"Viewfrom15thFloor\"," \
|
||||
"\"Thumbnail\":{" \
|
||||
"\"Url\":\"http:/*www.example.com/image/481989943\"," \
|
||||
"\"Height\":125," \
|
||||
"\"Width\":\"100\"" \
|
||||
"}," \
|
||||
"\"IDs\":[116,943,234,38793]" \
|
||||
"}" \
|
||||
"}";
|
||||
|
||||
char test_13_wo_null[sizeof(test_13) - 1];
|
||||
memcpy(test_13_wo_null, test_13, sizeof(test_13) - 1);
|
||||
|
||||
tree = cJSON_ParseWithLength(test_13_wo_null, sizeof(test_13) - 1);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(tree, "Failed to parse valid json.");
|
||||
|
||||
if (tree != NULL)
|
||||
{
|
||||
cJSON_Delete(tree);
|
||||
}
|
||||
}
|
||||
|
||||
static void test14_should_not_be_parsed(void)
|
||||
{
|
||||
cJSON *tree = NULL;
|
||||
const char test_14[] = "{" \
|
||||
"\"Image\":{" \
|
||||
"\"Width\":800," \
|
||||
"\"Height\":600," \
|
||||
"\"Title\":\"Viewfrom15thFloor\"," \
|
||||
"\"Thumbnail\":{" \
|
||||
"\"Url\":\"http:/*www.example.com/image/481989943\"," \
|
||||
"\"Height\":125," \
|
||||
"\"Width\":\"100\"" \
|
||||
"}," \
|
||||
"\"IDs\":[116,943,234,38793]" \
|
||||
"}" \
|
||||
"}";
|
||||
|
||||
tree = cJSON_ParseWithLength(test_14, sizeof(test_14) - 2);
|
||||
TEST_ASSERT_NULL_MESSAGE(tree, "Should not continue after buffer_length is reached.");
|
||||
|
||||
if (tree != NULL)
|
||||
{
|
||||
cJSON_Delete(tree);
|
||||
}
|
||||
}
|
||||
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(file_test1_should_be_parsed_and_printed);
|
||||
@@ -210,5 +265,7 @@ int main(void)
|
||||
RUN_TEST(file_test10_should_be_parsed_and_printed);
|
||||
RUN_TEST(file_test11_should_be_parsed_and_printed);
|
||||
RUN_TEST(test12_should_not_be_parsed);
|
||||
RUN_TEST(test13_should_be_parsed_without_null_termination);
|
||||
RUN_TEST(test14_should_not_be_parsed);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ static void parse_hex4_should_parse_mixed_case(void)
|
||||
TEST_ASSERT_EQUAL_INT(0xBEEF, parse_hex4((const unsigned char*)"BEEF"));
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(parse_hex4_should_parse_all_combinations);
|
||||
|
||||
@@ -96,7 +96,7 @@ static void parse_number_should_parse_negative_reals(void)
|
||||
assert_parse_number("-123e-128", 0, -123e-128);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item */
|
||||
memset(item, 0, sizeof(cJSON));
|
||||
|
||||
@@ -162,7 +162,7 @@ static void parse_object_should_not_parse_non_objects(void)
|
||||
assert_not_object("\"{}hello world!\n\"");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item */
|
||||
memset(item, 0, sizeof(cJSON));
|
||||
|
||||
@@ -119,7 +119,7 @@ static void parse_string_should_parse_bug_94(void)
|
||||
reset(item);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item and error pointer */
|
||||
memset(item, 0, sizeof(cJSON));
|
||||
|
||||
@@ -96,7 +96,7 @@ static void parse_value_should_parse_object(void)
|
||||
reset(item);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item */
|
||||
memset(item, 0, sizeof(cJSON));
|
||||
|
||||
@@ -97,7 +97,7 @@ static void parse_with_opts_should_parse_utf8_bom(void)
|
||||
cJSON_Delete(without_bom);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ static void print_array_should_print_arrays_with_multiple_elements(void)
|
||||
assert_print_array("[1, null, true, false, [], \"hello\", {\n\t}]", "[1,null,true,false,[],\"hello\",{}]");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item */
|
||||
UNITY_BEGIN();
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
static void assert_print_number(const char *expected, double input)
|
||||
{
|
||||
unsigned char printed[1024];
|
||||
unsigned char new_buffer[26];
|
||||
unsigned int i = 0;
|
||||
cJSON item[1];
|
||||
printbuffer buffer = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
|
||||
buffer.buffer = printed;
|
||||
@@ -34,11 +36,29 @@ static void assert_print_number(const char *expected, double input)
|
||||
buffer.offset = 0;
|
||||
buffer.noalloc = true;
|
||||
buffer.hooks = global_hooks;
|
||||
buffer.buffer = new_buffer;
|
||||
|
||||
memset(item, 0, sizeof(item));
|
||||
memset(new_buffer, 0, sizeof(new_buffer));
|
||||
cJSON_SetNumberValue(item, input);
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(print_number(item, &buffer), "Failed to print number.");
|
||||
|
||||
/* In MinGW or visual studio(before 2015),the exponten is represented using three digits,like:"1e-009","1e+017"
|
||||
* remove extra "0" to output "1e-09" or "1e+17",which makes testcase PASS */
|
||||
for(i = 0;i <sizeof(new_buffer);i++)
|
||||
{
|
||||
if(i >3 && new_buffer[i] =='0')
|
||||
{
|
||||
if((new_buffer[i-3] =='e' && new_buffer[i-2] == '-' && new_buffer[i] =='0') ||(new_buffer[i-2] =='e' && new_buffer[i-1] =='+'))
|
||||
{
|
||||
while(new_buffer[i] !='\0')
|
||||
{
|
||||
new_buffer[i] = new_buffer[i+1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, buffer.buffer, "Printed number is not as expected.");
|
||||
}
|
||||
|
||||
@@ -89,7 +109,7 @@ static void print_number_should_print_non_number(void)
|
||||
/* assert_print_number("null", -INFTY); */
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item */
|
||||
UNITY_BEGIN();
|
||||
|
||||
@@ -88,7 +88,7 @@ static void print_object_should_print_objects_with_multiple_elements(void)
|
||||
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)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item */
|
||||
UNITY_BEGIN();
|
||||
|
||||
@@ -65,7 +65,7 @@ static void print_string_should_print_utf8(void)
|
||||
assert_print_string("\"ü猫慕\"", "ü猫慕");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item */
|
||||
UNITY_BEGIN();
|
||||
|
||||
@@ -90,7 +90,7 @@ static void print_value_should_print_object(void)
|
||||
assert_print_value("{}");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
/* initialize cJSON item */
|
||||
UNITY_BEGIN();
|
||||
|
||||
@@ -69,7 +69,7 @@ static char* create_monitor(void)
|
||||
goto end;
|
||||
}
|
||||
/* after creation was successful, immediately add it to the monitor,
|
||||
* thereby transfering ownership of the pointer to it */
|
||||
* thereby transferring ownership of the pointer to it */
|
||||
cJSON_AddItemToObject(monitor, "name", name);
|
||||
|
||||
resolutions = cJSON_CreateArray();
|
||||
@@ -202,7 +202,7 @@ static int supports_full_hd(const char * const monitor)
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
|
||||
if (compare_double(width->valuedouble, 1920) && compare_double(height->valuedouble, 1080))
|
||||
{
|
||||
status = 1;
|
||||
goto end;
|
||||
@@ -246,7 +246,7 @@ static void supports_full_hd_should_check_for_full_hd_support(void)
|
||||
TEST_ASSERT_FALSE(supports_full_hd(monitor_without_hd));
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int CJSON_CDECL main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
||||
|
||||
@@ -268,14 +268,14 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number)
|
||||
UNITY_DOUBLE number = input_number;
|
||||
|
||||
/* print minus sign (including for negative zero) */
|
||||
if (number < 0.0f || (number == 0.0f && 1.0f / number < 0.0f))
|
||||
if (number < (double)0.0f || (number == (double)0.0f && (double)1.0f / number < (double)0.0f))
|
||||
{
|
||||
UNITY_OUTPUT_CHAR('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
/* handle zero, NaN, and +/- infinity */
|
||||
if (number == 0.0f) UnityPrint("0");
|
||||
if (number == (double)0.0f) UnityPrint("0");
|
||||
else if (isnan(number)) UnityPrint("nan");
|
||||
else if (isinf(number)) UnityPrint("inf");
|
||||
else
|
||||
@@ -286,10 +286,10 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number)
|
||||
char buf[16];
|
||||
|
||||
/* scale up or down by powers of 10 */
|
||||
while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; }
|
||||
while (number < 100000.0f) { number *= 10.0f; exponent--; }
|
||||
while (number > 1000000.0f * 1e6f) { number /= 1e6f; exponent += 6; }
|
||||
while (number > 1000000.0f) { number /= 10.0f; exponent++; }
|
||||
while (number < (double)(100000.0f / 1e6f)) { number *= (double)1e6f; exponent -= 6; }
|
||||
while (number < (double)100000.0f) { number *= (double)10.0f; exponent--; }
|
||||
while (number > (double)(1000000.0f * 1e6f)) { number /= (double)1e6f; exponent += 6; }
|
||||
while (number > (double)1000000.0f) { number /= (double)10.0f; exponent++; }
|
||||
|
||||
/* round to nearest integer */
|
||||
n = ((UNITY_INT32)(number + number) + 1) / 2;
|
||||
|
||||
3
tests/unity_setup.c
Normal file
3
tests/unity_setup.c
Normal file
@@ -0,0 +1,3 @@
|
||||
// msvc doesn't support weak-linking, so we need to define these functions.
|
||||
void setUp(void) { }
|
||||
void tearDown(void) { }
|
||||
Reference in New Issue
Block a user