Full Code of DaveGamble/cJSON for AI

master b2890c8d76bb cached
160 files
820.0 KB
209.1k tokens
615 symbols
1 requests
Download .txt
Showing preview only (866K chars total). Download the full file or copy to clipboard to get everything.
Repository: DaveGamble/cJSON
Branch: master
Commit: b2890c8d76bb
Files: 160
Total size: 820.0 KB

Directory structure:
gitextract_0me4kfa0/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── CONTRIBUTING.md
│   └── workflows/
│       ├── CI.yml
│       └── ci-fuzz.yml
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── CMakeLists.txt
├── CONTRIBUTORS.md
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── appveyor.yml
├── cJSON.c
├── cJSON.h
├── cJSON_Utils.c
├── cJSON_Utils.h
├── fuzzing/
│   ├── .gitignore
│   ├── CMakeLists.txt
│   ├── afl-prepare-linux.sh
│   ├── afl.c
│   ├── afl.sh
│   ├── cjson_read_fuzzer.c
│   ├── fuzz_main.c
│   ├── inputs/
│   │   ├── test1
│   │   ├── test10
│   │   ├── test11
│   │   ├── test2
│   │   ├── test3
│   │   ├── test3.bu
│   │   ├── test3.uf
│   │   ├── test3.uu
│   │   ├── test4
│   │   ├── test5
│   │   ├── test6
│   │   ├── test7
│   │   ├── test8
│   │   └── test9
│   ├── json.dict
│   └── ossfuzz.sh
├── library_config/
│   ├── cJSONConfig.cmake.in
│   ├── cJSONConfigVersion.cmake.in
│   ├── libcjson.pc.in
│   ├── libcjson_utils.pc.in
│   └── uninstall.cmake
├── test.c
├── tests/
│   ├── CMakeLists.txt
│   ├── cjson_add.c
│   ├── common.h
│   ├── compare_tests.c
│   ├── inputs/
│   │   ├── test1
│   │   ├── test1.expected
│   │   ├── test10
│   │   ├── test10.expected
│   │   ├── test11
│   │   ├── test11.expected
│   │   ├── test2
│   │   ├── test2.expected
│   │   ├── test3
│   │   ├── test3.expected
│   │   ├── test4
│   │   ├── test4.expected
│   │   ├── test5
│   │   ├── test5.expected
│   │   ├── test6
│   │   ├── test7
│   │   ├── test7.expected
│   │   ├── test8
│   │   ├── test8.expected
│   │   ├── test9
│   │   └── test9.expected
│   ├── json-patch-tests/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── .npmignore
│   │   ├── README.md
│   │   ├── cjson-utils-tests.json
│   │   ├── package.json
│   │   ├── spec_tests.json
│   │   └── tests.json
│   ├── json_patch_tests.c
│   ├── minify_tests.c
│   ├── misc_tests.c
│   ├── misc_utils_tests.c
│   ├── old_utils_tests.c
│   ├── parse_array.c
│   ├── parse_examples.c
│   ├── parse_hex4.c
│   ├── parse_number.c
│   ├── parse_object.c
│   ├── parse_string.c
│   ├── parse_value.c
│   ├── parse_with_opts.c
│   ├── print_array.c
│   ├── print_number.c
│   ├── print_object.c
│   ├── print_string.c
│   ├── print_value.c
│   ├── readme_examples.c
│   ├── unity/
│   │   ├── .gitattributes
│   │   ├── .gitignore
│   │   ├── .travis.yml
│   │   ├── README.md
│   │   ├── auto/
│   │   │   ├── colour_prompt.rb
│   │   │   ├── colour_reporter.rb
│   │   │   ├── generate_config.yml
│   │   │   ├── generate_module.rb
│   │   │   ├── generate_test_runner.rb
│   │   │   ├── parse_output.rb
│   │   │   ├── stylize_as_junit.rb
│   │   │   ├── test_file_filter.rb
│   │   │   ├── type_sanitizer.rb
│   │   │   ├── unity_test_summary.py
│   │   │   ├── unity_test_summary.rb
│   │   │   └── unity_to_junit.py
│   │   ├── docs/
│   │   │   ├── ThrowTheSwitchCodingStandard.md
│   │   │   ├── UnityAssertionsReference.md
│   │   │   ├── UnityConfigurationGuide.md
│   │   │   ├── UnityGettingStartedGuide.md
│   │   │   ├── UnityHelperScriptsGuide.md
│   │   │   └── license.txt
│   │   ├── examples/
│   │   │   ├── example_1/
│   │   │   │   ├── makefile
│   │   │   │   ├── readme.txt
│   │   │   │   └── src/
│   │   │   │       ├── ProductionCode.c
│   │   │   │       ├── ProductionCode.h
│   │   │   │       ├── ProductionCode2.c
│   │   │   │       └── ProductionCode2.h
│   │   │   ├── example_2/
│   │   │   │   ├── makefile
│   │   │   │   ├── readme.txt
│   │   │   │   └── src/
│   │   │   │       ├── ProductionCode.c
│   │   │   │       ├── ProductionCode.h
│   │   │   │       ├── ProductionCode2.c
│   │   │   │       └── ProductionCode2.h
│   │   │   ├── example_3/
│   │   │   │   ├── helper/
│   │   │   │   │   ├── UnityHelper.c
│   │   │   │   │   └── UnityHelper.h
│   │   │   │   ├── rakefile.rb
│   │   │   │   ├── rakefile_helper.rb
│   │   │   │   ├── readme.txt
│   │   │   │   ├── src/
│   │   │   │   │   ├── ProductionCode.c
│   │   │   │   │   ├── ProductionCode.h
│   │   │   │   │   ├── ProductionCode2.c
│   │   │   │   │   └── ProductionCode2.h
│   │   │   │   └── target_gcc_32.yml
│   │   │   └── unity_config.h
│   │   ├── extras/
│   │   │   ├── eclipse/
│   │   │   │   └── error_parsers.txt
│   │   │   └── fixture/
│   │   │       ├── rakefile.rb
│   │   │       ├── rakefile_helper.rb
│   │   │       ├── readme.txt
│   │   │       └── src/
│   │   │           ├── unity_fixture.c
│   │   │           ├── unity_fixture.h
│   │   │           ├── unity_fixture_internals.h
│   │   │           └── unity_fixture_malloc_overrides.h
│   │   ├── release/
│   │   │   ├── build.info
│   │   │   └── version.info
│   │   └── src/
│   │       ├── unity.c
│   │       ├── unity.h
│   │       └── unity_internals.h
│   └── unity_setup.c
└── valgrind.supp

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
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


================================================
FILE: .gitattributes
================================================
*  					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


================================================
FILE: .github/CONTRIBUTING.md
================================================
Contribution Guidelines
=======================

Contributions to cJSON are welcome. If you find a bug or want to improve cJSON in another way, pull requests are appreciated.

For bigger changes, in order to avoid wasted effort, please open an issue to discuss the technical details before creating a pull request.

The further sections explain the process in more detail and provides some guidelines on how contributions should look like.

Branches
--------
There are two branches to be aware of, the `master` and the `develop` branch. The `master` branch is reserved for the latest release, so only make pull requests to the `master` branch for small bug- or security fixes (these are usually just a few lines). In all other cases, please make a pull request to the `develop` branch.

Coding Style
------------
The coding style has been discussed in [#24](https://github.com/DaveGamble/cJSON/issues/24). The basics are:

* Use 4 spaces for indentation
* No oneliners (conditions, loops, variable declarations ...)
* Always use parenthesis for control structures
* Don't implicitly rely on operator precedence, use round brackets in expressions. e.g. `(a > b) && (c < d)` instead of `a>b && c<d`
* opening curly braces start in the next line
* use spaces around operators
* lines should not have trailing whitespace
* use spaces between function parameters
* use pronouncable variable names, not just a combination of letters

Example:

```c
/* calculate the new length of the string in a printbuffer and update the offset */
static void update_offset(printbuffer * const buffer)
{
    const unsigned char *buffer_pointer = NULL;
    if ((buffer == NULL) || (buffer->buffer == NULL))
    {
        return;
    }
    buffer_pointer = buffer->buffer + buffer->offset;

    buffer->offset += strlen((const char*)buffer_pointer);
}
```

Unit Tests
----------
cJSON uses the [Unity](https://github.com/ThrowTheSwitch/Unity) library for unit tests. The tests are located in the `tests` directory. In order to add a new test, either add it to one of the existing files (if it fits) or add a new C file for the test. That new file has to be added to the list of tests in `tests/CMakeLists.txt`.

All new features have to be covered by unit tests.

Other Notes
-----------
* Internal functions are to be declared static.
* Wrap the return type of external function in the `CJSON_PUBLIC` macro.


================================================
FILE: .github/workflows/CI.yml
================================================
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-14 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


================================================
FILE: .github/workflows/ci-fuzz.yml
================================================
name: CIFuzz
on: [pull_request]
jobs:
  Fuzzing:
    runs-on: ubuntu-latest
    steps:
    - name: Build Fuzzers
      uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
      with:
        oss-fuzz-project-name: 'cjson'
        dry-run: false
    - name: Run Fuzzers
      uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
      with:
        oss-fuzz-project-name: 'cjson'
        fuzz-seconds: 600
        dry-run: false
    - name: Upload Crash
      uses: actions/upload-artifact@v4
      if: failure()
      with:
        name: artifacts
        path: ./out/artifacts


================================================
FILE: .gitignore
================================================
.svn
test
*.o
*.a
*.so
*.swp
*.patch
tags
*.dylib*
build/
cJSON_test
cJSON_test_utils
libcjson.so.*
libcjson_utils.so.*
*.orig
.vscode
.idea
cmake-build-debug
*.lst
*.lss


================================================
FILE: .travis.yml
================================================
dist: trusty
sudo: false
language: c
env:
  matrix:
    - VALGRIND=On SANITIZERS=Off
    - VALGRIND=Off SANITIZERS=Off
    - VALGRIND=Off SANITIZERS=On
compiler:
  - gcc
  - clang
addons:
  apt:
    packages:
      - valgrind
      - libasan0
      - lib32asan0
      # currently not supported on travis:
      # - libasan1
      # - libasan2
      # - libubsan0
      - llvm
script:
  - mkdir build
  - cd build
  - cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_VALGRIND="${VALGRIND}" -DENABLE_SAFE_STACK="${VALGRIND}" -DENABLE_SANITIZERS="${SANITIZERS}"
  - make
  - make test CTEST_OUTPUT_ON_FAILURE=On


================================================
FILE: CHANGELOG.md
================================================
1.7.19 (Sep 9, 2025)
======
Fixes:
------
* Fix indentation (should use spaces), see #814
* Fix spelling errors found by CodeSpell, see #841
* Check for NULL in cJSON_DetachItemViaPointer, fixes #882, see #886
* Fix #881, check overlap before calling strcpy in cJSON_SetValuestring, see #885
* Fix #880 Max recursion depth for cJSON_Duplicate to prevent stack exhaustion, see #888
* Allocate memory for the temporary buffer when paring numbers, see #939
* fix the incorrect check in decode_array_index_from_pointer, see #957

1.7.18 (May 13, 2024)
======
Fixes:
------
* Add NULL check to cJSON_SetValuestring()(CVE-2024-31755), see #839 and #840
* Remove non-functional list handling of compiler flags, see #851
* Fix heap buffer overflow, see #852
* remove misused optimization flag -01, see #854
* Set free'd pointers to NULL whenever they are not reassigned immediately after, see #855 and #833

1.7.17 (Dec 26, 2023)
======
Fixes:
------
* Fix null reference in cJSON_SetValuestring(CVE-2023-50472), see #809
* Fix null reference in cJSON_InsertItemInArray(CVE-2023-50471), see #809 and #810

1.7.16 (Jul 5, 2023)
======
Features:
------
* Add an option for ENABLE_CJSON_VERSION_SO in CMakeLists.txt, see #534
* Add cmake_policy to CMakeLists.txt, see #163
* Add cJSON_SetBoolValue, see #639
* Add meson documentation, see #761

Fixes:
------
* Fix memory leak in merge_patch, see #611
* Fix conflicting target names 'uninstall', see #617
* Bump cmake version to 3.0 and use new version syntax, see #587
* Print int without decimal places, see #630
* Fix 'cjson_utils-static' target not exist, see #625
* Add allocate check for replace_item_in_object, see #675
* Fix a null pointer crash in cJSON_ReplaceItemViaPointer, see #726

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:
------
* 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.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](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](https://github.com/DaveGamble/cJSON/pull/226)

Fixes:
------
* 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](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 (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](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:
--------------
* Add the new warnings `-Wswitch-enum`, `-Wused-but-makred-unused`, `-Wmissing-variable-declarations`, `-Wunused-macro`
* More number printing tests.
* Continuous integration testing with AppVeyor (semi automatic at this point), thanks @simon-p-r

1.5.9 (Sep 8, 2017)
=====
Fixes:
------
* 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.8 (Aug 21, 2017)
=====
Fixes:
------
* Fix `make test` in the Makefile, thanks @YanhaoMo for reporting this [#195](https://github.com/DaveGamble/cJSON/issues/195)

1.5.7 (Jul 13, 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](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.6 (Jun 28, 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, 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 (May 23, 2017)
=====
Fixes:
------
* Fix `cJSON_ReplaceItemInObject` not keeping the name of an item, see [#174](https://github.com/DaveGamble/cJSON/issues/174)

1.5.2 (May 10, 2017)
=====
Fixes:
------
* 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 (May 6, 2017)
=====
Fixes:
------
* 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 (May 2, 2017)
=====
Features:
* 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. see [02a05ee](https://github.com/DaveGamble/cJSON/commit/02a05eea4e6ba41811f130b322660bea8918e1a0)


Enhancements:
-------------
* Parse into a buffer, this will allow parsing `\u0000` in the future (not quite yet though)
* General simplifications and readability improvements
* More unit tests
* Update [unity](https://github.com/ThrowTheSwitch/Unity) testing library to 2.4.1
* Add the [json-patch-tests](https://github.com/json-patch/json-patch-tests) test suite to test cJSON_Utils.
* Move all tests from `test_utils.c` to unit tests with unity.

Fixes:
------
* 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`

Other Changes:
--------------
* Move generated files in the `library_config` subdirectory.

1.4.7 (Apr 19, 2017)
=====
Fixes:
------
* 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 (Apr 9, 2017)
=====
Fixes:
------
* Several corrections in the README
* Making clear that `valueint` should not be written to
* 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 (Mar 28, 2017)
=====
Fixes:
------
* 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 (Mar 24, 2017)
=====
Fixes:
------
* 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`, see [4bfb8800](https://github.com/DaveGamble/cJSON/commit/4bfb88009342fb568295a7f6dc4b7fee74fbf022)

1.4.3 (Mar 19, 2017)
=====
Fixes:
------
* 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 (Mar 16, 2017)
=====
Fixes:
------
* 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 (Mar 16, 2017)
=====
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 (Mar 4, 2017)
=====
Features
--------
* 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`, 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](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 (Mar 1, 2017)
=====
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 (Feb 27, 2017)
=====
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 (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`, 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 [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.

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](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 ([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 ([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 (Jan 31, 2017)
=====
Fixes:
------
* 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 (Jan 9, 2017)
=====
Features:
---------
* 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, 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 (Dec 6, 2016)
=====
* 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 (Nov 25, 2016)
=====
* Rename internal boolean type, see [#71](https://github.com/DaveGamble/cJSON/issues/71).

1.0.1 (Nov 20, 2016)
=====
Small bugfix release.
* 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 (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.


================================================
FILE: CMakeLists.txt
================================================
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
cmake_minimum_required(VERSION 3.5)

project(cJSON
    VERSION 1.7.19
    LANGUAGES C)

cmake_policy(SET CMP0054 NEW)  # set CMP0054 policy

include(GNUInstallDirs)

set(CJSON_VERSION_SO 1)
set(CJSON_UTILS_VERSION_SO 1)

set(custom_compiler_flags)

include(CheckCCompilerFlag)
option(ENABLE_CUSTOM_COMPILER_FLAGS "Enables custom compiler flags" ON)
if (ENABLE_CUSTOM_COMPILER_FLAGS)
    if (("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU"))
        list(APPEND custom_compiler_flags
            -std=c89
            -pedantic
            -Wall
            -Wextra
            -Werror
            -Wstrict-prototypes
            -Wwrite-strings
            -Wshadow
            -Winit-self
            -Wcast-align
            -Wformat=2
            -Wmissing-prototypes
            -Wstrict-overflow=2
            -Wcast-qual
            -Wundef
            -Wswitch-default
            -Wconversion
            -Wc++-compat
            -fstack-protector-strong
            -Wcomma
            -Wdouble-promotion
            -Wparentheses
            -Wformat-overflow
            -Wunused-macros
            -Wmissing-variable-declarations
            -Wused-but-marked-unused
            -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()

option(ENABLE_SANITIZERS "Enables AddressSanitizer and UndefinedBehaviorSanitizer." OFF)
if (ENABLE_SANITIZERS)
    list(APPEND custom_compiler_flags
        -fno-omit-frame-pointer
        -fsanitize=address
        -fsanitize=undefined
        -fsanitize=float-cast-overflow
        -fsanitize-address-use-after-scope
        -fsanitize=integer
        -fno-sanitize-recover
        )
endif()

option(ENABLE_SAFE_STACK "Enables the SafeStack instrumentation pass by the Code Pointer Integrity Project" OFF)
if (ENABLE_SAFE_STACK)
    if (ENABLE_SANITIZERS)
        message(FATAL_ERROR "ENABLE_SAFE_STACK cannot be used in combination with ENABLE_SANITIZERS")
    endif()
    list(APPEND custom_compiler_flags
        -fsanitize=safe-stack
        )
endif()

option(ENABLE_PUBLIC_SYMBOLS "Export library symbols." On)
if (ENABLE_PUBLIC_SYMBOLS)
    list(APPEND custom_compiler_flags -fvisibility=hidden)
    add_definitions(-DCJSON_EXPORT_SYMBOLS -DCJSON_API_VISIBILITY)
endif()
option(ENABLE_HIDDEN_SYMBOLS "Hide library symbols." Off)
if (ENABLE_HIDDEN_SYMBOLS)
    add_definitions(-DCJSON_HIDE_SYMBOLS -UCJSON_API_VISIBILITY)
endif()

# apply custom compiler flags
foreach(compiler_flag ${custom_compiler_flags})
    #remove problematic characters
    string(REGEX REPLACE "[^a-zA-Z0-9]" "" current_variable ${compiler_flag})

    CHECK_C_COMPILER_FLAG(${compiler_flag} "FLAG_SUPPORTED_${current_variable}")
    if (FLAG_SUPPORTED_${current_variable})
        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_flag}")
    endif()
endforeach()

option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_TARGET_EXPORT "Enable exporting of CMake targets. Disable when it causes problems!" ON)

#cJSON
set(CJSON_LIB cjson)

file(GLOB HEADERS cJSON.h)
set(SOURCES cJSON.c)

option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off)
option(CJSON_OVERRIDE_BUILD_SHARED_LIBS "Override BUILD_SHARED_LIBS with CJSON_BUILD_SHARED_LIBS" OFF)
option(CJSON_BUILD_SHARED_LIBS "Overrides BUILD_SHARED_LIBS if CJSON_OVERRIDE_BUILD_SHARED_LIBS is enabled" ON)
option(ENABLE_CJSON_VERSION_SO "Enables cJSON so version" ON)

if ((CJSON_OVERRIDE_BUILD_SHARED_LIBS AND CJSON_BUILD_SHARED_LIBS) OR ((NOT CJSON_OVERRIDE_BUILD_SHARED_LIBS) AND BUILD_SHARED_LIBS))
    set(CJSON_LIBRARY_TYPE SHARED)
else()
    set(CJSON_LIBRARY_TYPE STATIC)
endif()


if (NOT BUILD_SHARED_AND_STATIC_LIBS)
    add_library("${CJSON_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS}" "${SOURCES}")
else()
    # See https://cmake.org/Wiki/CMake_FAQ#How_do_I_make_my_shared_and_static_libraries_have_the_same_root_name.2C_but_different_suffixes.3F
    add_library("${CJSON_LIB}" SHARED "${HEADERS}" "${SOURCES}")
    add_library("${CJSON_LIB}-static" STATIC "${HEADERS}" "${SOURCES}")
    set_target_properties("${CJSON_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_LIB}")
    set_target_properties("${CJSON_LIB}-static" PROPERTIES PREFIX "lib")
endif()
if (NOT WIN32)
    target_link_libraries("${CJSON_LIB}" m)
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_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"
    EXPORT "${CJSON_LIB}" 
    ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
    INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
)
endif()
if(ENABLE_TARGET_EXPORT)
    # export library information for CMake projects
    install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif()

if(ENABLE_CJSON_VERSION_SO)
    set_target_properties("${CJSON_LIB}"
        PROPERTIES
            SOVERSION "${CJSON_VERSION_SO}"
            VERSION "${PROJECT_VERSION}")
endif()

#cJSON_Utils
option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF)
if(ENABLE_CJSON_UTILS)
    set(CJSON_UTILS_LIB cjson_utils)

    file(GLOB HEADERS_UTILS cJSON_Utils.h)
    set(SOURCES_UTILS cJSON_Utils.c)

    if (NOT BUILD_SHARED_AND_STATIC_LIBS)
        add_library("${CJSON_UTILS_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS_UTILS}" "${SOURCES_UTILS}")
        target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}")
    else()
        add_library("${CJSON_UTILS_LIB}" SHARED "${HEADERS_UTILS}" "${SOURCES_UTILS}")
        target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}")
        add_library("${CJSON_UTILS_LIB}-static" STATIC "${HEADERS_UTILS}" "${SOURCES_UTILS}")
        target_link_libraries("${CJSON_UTILS_LIB}-static" "${CJSON_LIB}-static")
        set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_UTILS_LIB}")
        set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES PREFIX "lib")
    endif()

    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}"
        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" 
        EXPORT "${CJSON_UTILS_LIB}" 
        ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
        INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
        )
    endif()
    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_FULL_LIBDIR}/cmake/cJSON")
    endif()

    if(ENABLE_CJSON_VERSION_SO)
        set_target_properties("${CJSON_UTILS_LIB}"
            PROPERTIES
                SOVERSION "${CJSON_UTILS_VERSION_SO}"
                VERSION "${PROJECT_VERSION}")
    endif()
endif()

# create the other package config files
configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfig.cmake.in"
    ${PROJECT_BINARY_DIR}/cJSONConfig.cmake @ONLY)
configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfigVersion.cmake.in"
    ${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake @ONLY)

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)
    enable_testing()

    set(TEST_CJSON cJSON_test)
    add_executable("${TEST_CJSON}" test.c)
    target_link_libraries("${TEST_CJSON}" "${CJSON_LIB}")

    add_test(NAME ${TEST_CJSON} COMMAND "${CMAKE_CURRENT_BINARY_DIR}/${TEST_CJSON}")

    # Disable -fsanitize=float-divide-by-zero for cJSON_test
    if (FLAG_SUPPORTED_fsanitizefloatdividebyzero)
        if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=float-divide-by-zero")
        else()
            target_compile_options(${TEST_CJSON} PRIVATE "-fno-sanitize=float-divide-by-zero")
        endif()
    endif()

    #"check" target that automatically builds everything and runs the tests
    add_custom_target(check
        COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
        DEPENDS ${TEST_CJSON})
endif()

#Create the uninstall target
option(ENABLE_CJSON_UNINSTALL "Enable creating uninstall target" ON)
if(ENABLE_CJSON_UNINSTALL)
  add_custom_target(uninstall "${CMAKE_COMMAND}" -P
    "${PROJECT_SOURCE_DIR}/library_config/uninstall.cmake")
endif()

# Enable the use of locales
option(ENABLE_LOCALES "Enable the use of locales" ON)
if(ENABLE_LOCALES)
	add_definitions(-DENABLE_LOCALES)
endif()

add_subdirectory(tests)
add_subdirectory(fuzzing)


================================================
FILE: CONTRIBUTORS.md
================================================
Contributors
============

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)
* [AlexanderVasiljev](https://github.com/AlexanderVasiljev)
* [Alper Akcan](https://github.com/alperakcan)
* [Andrew Tang](https://github.com/singku)
* [Andy](https://github.com/mlh0101)
* [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)
* [Dominik](https://github.com/DL6ER)
* [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
* [hopper-vul](https://github.com/hopper-vul)
* [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)
* [Joshua Arulsamy](https://github.com/jarulsamy)
* [Julian Ste](https://github.com/julian-st)
* [Julián Vásquez](https://github.com/juvasquezg)
* [Junbo Zheng](https://github.com/Junbo-Zheng)
* [Kevin Branigan](https://github.com/kbranigan)
* [Kevin Sapper](https://github.com/sappo)
* [Kyle Chisholm](https://github.com/ChisholmKyle)
* [Linus Wallgren](https://github.com/ecksun)
* [Luo Jin](https://github.com/Up-wind)
* [Max](https://github.com/maebex)
* [MaxBrandtner](https://github.com/MaxBrandtner)
* [Mateusz Szafoni](https://github.com/raiden00pl)
* Mike Pontillo
* [miaoerduo](https://github.com/miaoerduo)
* [mohawk2](https://github.com/mohawk2)
* [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)
* [Orri](https://github.com/sbvoxel)
* 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)
* [Sayan Bandyopadhyay](https://github.com/saynb)
* [Simon Sobisch](https://github.com/GitMensch)
* [Simon Ricaldone](https://github.com/simon-p-r)
* [Stoian Ivanov](https://github.com/sdrsdr)
* [SuperH-0630](https://github.com/SuperH-0630)
* [Square789](https://github.com/Square789)
* [Stephan Gatzka](https://github.com/gatzka)
* [Tony Langhammer](https://github.com/BigBrainAFK)
* [Vemake](https://github.com/vemakereporter)
* [vwvw](https://github.com/vwvw)
* [warmsocks](https://github.com/warmsocks)
* [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)
* [10km](https://github.com/10km)

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.


================================================
FILE: LICENSE
================================================
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.



================================================
FILE: Makefile
================================================
CJSON_OBJ = cJSON.o
UTILS_OBJ = cJSON_Utils.o
CJSON_LIBNAME = libcjson
UTILS_LIBNAME = libcjson_utils
CJSON_TEST = cJSON_test

CJSON_TEST_SRC = cJSON.c test.c

LDLIBS = -lm

LIBVERSION = 1.7.19
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

INSTALL_INCLUDE_PATH = $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH)
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 := "`$(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
else
    CFLAGS += -fstack-protector
endif

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

#library file extensions
SHARED = so
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
CJSON_SHARED = $(CJSON_LIBNAME).$(SHARED)
CJSON_SHARED_VERSION = $(CJSON_LIBNAME).$(SHARED).$(LIBVERSION)
CJSON_SHARED_SO = $(CJSON_LIBNAME).$(SHARED).$(CJSON_SOVERSION)
CJSON_STATIC = $(CJSON_LIBNAME).$(STATIC)

#cJSON_Utils library names
UTILS_SHARED = $(UTILS_LIBNAME).$(SHARED)
UTILS_SHARED_VERSION = $(UTILS_LIBNAME).$(SHARED).$(LIBVERSION)
UTILS_SHARED_SO = $(UTILS_LIBNAME).$(SHARED).$(UTILS_SOVERSION)
UTILS_STATIC = $(UTILS_LIBNAME).$(STATIC)

SHARED_CMD = $(CC) -shared -o

.PHONY: all shared static tests clean install

all: shared static tests

shared: $(CJSON_SHARED) $(UTILS_SHARED)

static: $(CJSON_STATIC) $(UTILS_STATIC)

tests: $(CJSON_TEST)

test: tests
	./$(CJSON_TEST)

.c.o:
	$(CC) -c $(R_CFLAGS) $<

#tests
#cJSON
$(CJSON_TEST): $(CJSON_TEST_SRC) cJSON.h
	$(CC) $(R_CFLAGS) $(CJSON_TEST_SRC)  -o $@ $(LDLIBS) -I.

#static libraries
#cJSON
$(CJSON_STATIC): $(CJSON_OBJ)
	$(AR) rcs $@ $<
#cJSON_Utils
$(UTILS_STATIC): $(UTILS_OBJ)
	$(AR) rcs $@ $<

#shared libraries .so.1.0.0
#cJSON
$(CJSON_SHARED_VERSION): $(CJSON_OBJ)
	$(CC) -shared -o $@ $< $(CJSON_SO_LDFLAG) $(LDFLAGS)
#cJSON_Utils
$(UTILS_SHARED_VERSION): $(UTILS_OBJ)
	$(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 cJSON.h


#links .so -> .so.1 -> .so.1.0.0
#cJSON
$(CJSON_SHARED_SO): $(CJSON_SHARED_VERSION)
	ln -s $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO)
$(CJSON_SHARED): $(CJSON_SHARED_SO)
	ln -s $(CJSON_SHARED_SO) $(CJSON_SHARED)
#cJSON_Utils
$(UTILS_SHARED_SO): $(UTILS_SHARED_VERSION)
	ln -s $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO)
$(UTILS_SHARED): $(UTILS_SHARED_SO)
	ln -s $(UTILS_SHARED_SO) $(UTILS_SHARED)

#install
#cJSON
install-cjson:
	mkdir -p $(INSTALL_LIBRARY_PATH) $(INSTALL_INCLUDE_PATH)
	$(INSTALL) cJSON.h $(INSTALL_INCLUDE_PATH)
	$(INSTALL) $(CJSON_SHARED) $(CJSON_SHARED_SO) $(CJSON_SHARED_VERSION) $(INSTALL_LIBRARY_PATH)
#cJSON_Utils
install-utils: install-cjson
	$(INSTALL) cJSON_Utils.h $(INSTALL_INCLUDE_PATH)
	$(INSTALL) $(UTILS_SHARED) $(UTILS_SHARED_SO) $(UTILS_SHARED_VERSION) $(INSTALL_LIBRARY_PATH)

install: install-cjson install-utils

#uninstall
#cJSON
uninstall-cjson: uninstall-utils
	$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED)
	$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_VERSION)
	$(RM) $(INSTALL_LIBRARY_PATH)/$(CJSON_SHARED_SO)
	$(RM) $(INSTALL_INCLUDE_PATH)/cJSON.h
	
#cJSON_Utils
uninstall-utils:
	$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED)
	$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_VERSION)
	$(RM) $(INSTALL_LIBRARY_PATH)/$(UTILS_SHARED_SO)
	$(RM) $(INSTALL_INCLUDE_PATH)/cJSON_Utils.h

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
	$(RM) $(CJSON_SHARED) $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) $(CJSON_STATIC) #delete cJSON
	$(RM) $(UTILS_SHARED) $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) $(UTILS_STATIC) #delete cJSON_Utils
	$(RM) $(CJSON_TEST)  #delete test


================================================
FILE: README.md
================================================
# cJSON

Ultralightweight JSON parser in ANSI C.

## Table of contents
* [License](#license)
* [Usage](#usage)
  * [Welcome to cJSON](#welcome-to-cjson)
  * [Building](#building)
    * [Copying the source](#copying-the-source)
    * [CMake](#cmake)
    * [Makefile](#makefile)
    * [Meson](#meson)
    * [Vcpkg](#Vcpkg)
  * [Including cJSON](#including-cjson)
  * [Data Structure](#data-structure)
  * [Working with the data structure](#working-with-the-data-structure)
    * [Basic types](#basic-types)
    * [Arrays](#arrays)
    * [Objects](#objects)
  * [Parsing JSON](#parsing-json)
  * [Printing JSON](#printing-json)
  * [Example](#example)
    * [Printing](#printing)
    * [Parsing](#parsing)
  * [Caveats](#caveats)
    * [Zero Character](#zero-character)
    * [Character Encoding](#character-encoding)
    * [C Standard](#c-standard)
    * [Floating Point Numbers](#floating-point-numbers)
    * [Deep Nesting Of Arrays And Objects](#deep-nesting-of-arrays-and-objects)
    * [Thread Safety](#thread-safety)
    * [Case Sensitivity](#case-sensitivity)
    * [Duplicate Object Members](#duplicate-object-members)
  * [Enjoy cJSON!](#enjoy-cjson)

## License

MIT License

>  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
>
>  Permission is hereby granted, free of charge, to any person obtaining a copy
>  of this software and associated documentation files (the "Software"), to deal
>  in the Software without restriction, including without limitation the rights
>  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>  copies of the Software, and to permit persons to whom the Software is
>  furnished to do so, subject to the following conditions:
>
>  The above copyright notice and this permission notice shall be included in
>  all copies or substantial portions of the Software.
>
>  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
>  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>  THE SOFTWARE.

## Usage

### Welcome to cJSON.

cJSON aims to be the dumbest possible parser that you can get your job done with.
It's a single file of C, and a single header file.

JSON is described best here: http://www.json.org/
It's like XML, but fat-free. You use it to move data around, store things, or just
generally represent your program's state.

As a library, cJSON exists to take away as much legwork as it can, but not get in your way.
As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it
in one of two modes: Auto and Manual. Let's have a quick run-through.

I lifted some JSON from this page: http://www.json.org/fatfree.html
That page inspired me to write cJSON, which is a parser that tries to share the same
philosophy as JSON itself. Simple, dumb, out of the way.

### Building

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 3.5 is supported. With CMake it is recommended to do an out of tree build, meaning the compiled files are put in a directory separate from the source files. So in order to build cJSON with CMake on a Unix platform, make a `build` directory and run CMake inside it.

```
mkdir build
cd build
cmake ..
```

This will create a Makefile and a bunch of other files. You can then compile it:

```
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)
* `-DENABLE_CUSTOM_COMPILER_FLAGS=On`: Enable custom compiler flags (currently for Clang, GCC and MSVC). Turn off if it makes problems. (on by default)
* `-DENABLE_VALGRIND=On`: Run tests with [valgrind](http://valgrind.org). (off by default)
* `-DENABLE_SANITIZERS=On`: Compile cJSON with [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) enabled (if possible). (off by default)
* `-DENABLE_SAFE_STACK`: Enable the [SafeStack](https://clang.llvm.org/docs/SafeStack.html) instrumentation pass. Currently only works with the Clang compiler. (off by default)
* `-DBUILD_SHARED_LIBS=On`: Build the shared libraries. (on by default)
* `-DBUILD_SHARED_AND_STATIC_LIBS=On`: Build both shared and static libraries. (off by default)
* `-DCMAKE_INSTALL_PREFIX=/usr`: Set a prefix for the installation.
* `-DENABLE_LOCALES=On`: Enable the usage of localeconv method. ( on by default )
* `-DCJSON_OVERRIDE_BUILD_SHARED_LIBS=On`: Enable overriding the value of `BUILD_SHARED_LIBS` with `-DCJSON_BUILD_SHARED_LIBS`.
* `-DENABLE_CJSON_VERSION_SO`: Enable cJSON so version. ( on by default )

If you are packaging cJSON for a distribution of Linux, you would probably take these steps for example:
```
mkdir build
cd build
cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr
make
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 (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`. And uninstall them with: `make PREFIX=/usr DESTDIR=temp uninstall`.

#### Meson

To make cjson work in a project using meson, the libcjson dependency has to be included:

```meson
project('c-json-example', 'c')

cjson = dependency('libcjson')

example = executable(
    'example',
    'example.c',
    dependencies: [cjson],
)
```


#### 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
#include <cjson/cJSON.h>
```

### Data Structure

cJSON represents JSON data using the `cJSON` struct data type:

```c
/* The cJSON structure: */
typedef struct cJSON
{
    struct cJSON *next;
    struct cJSON *prev;
    struct cJSON *child;
    int type;
    char *valuestring;
    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
    int valueint;
    double valuedouble;
    char *string;
} cJSON;
```

An item of this type represents a JSON value. The type is stored in `type` as a bit-flag (**this means that you cannot find out the type by just comparing the value of `type`**).

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

Deleting items is done with `cJSON_DeleteItemFromArray`. It works like `cJSON_DetachItemFromArray`, but deletes the detached item via `cJSON_Delete`.

You can also replace an item in an array in place. Either with `cJSON_ReplaceItemInArray` using an index or with `cJSON_ReplaceItemViaPointer` given a pointer to an element. `cJSON_ReplaceItemViaPointer` will return `0` if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place.

To get the size of an array, use `cJSON_GetArraySize`. Use `cJSON_GetArrayItem` to get an element at a given index.

Because an array is stored as a linked list, iterating it via index is inefficient (`O(n²)`), so you can iterate over an array using the `cJSON_ArrayForEach` macro in `O(n)` time complexity.

#### Objects

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

Deleting items is done with `cJSON_DeleteItemFromObjectCaseSensitive`. It works like `cJSON_DetachItemFromObjectCaseSensitive` followed by `cJSON_Delete`.

You can also replace an item in an object in place. Either with `cJSON_ReplaceItemInObjectCaseSensitive` using a key or with `cJSON_ReplaceItemViaPointer` given a pointer to an element. `cJSON_ReplaceItemViaPointer` will return `0` if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place.

To get the size of an object, you can use `cJSON_GetArraySize`, this works because internally objects are stored as arrays.

If you want to access an item in an object, use `cJSON_GetObjectItemCaseSensitive`.

To iterate over an object, you can use the `cJSON_ArrayForEach` macro the same way as for arrays.

cJSON also provides convenient helper functions for quickly creating a new item and adding it to an object, like `cJSON_AddNullToObject`. They return a pointer to the new item or `NULL` if they failed.

### Parsing JSON

Given some JSON in a zero terminated string, you can parse it with `cJSON_Parse`.

```c
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`.

If an error occurs a pointer to the position of the error in the input string can be accessed using `cJSON_GetErrorPtr`. Note though that this can produce race conditions in multithreading scenarios, in that case it is better to use `cJSON_ParseWithOpts` with `return_parse_end`.
By default, characters in the input string that follow the parsed JSON will not be considered as an error.

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

```c
char *string = cJSON_Print(json);
```

It will allocate a string and print a JSON representation of the tree into it. Once it returns, you are fully responsible for deallocating it after use with your allocator. (usually `free`, depends on what has been set with `cJSON_InitHooks`).

`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 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 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
{
    "name": "Awesome 4K",
    "resolutions": [
        {
            "width": 1280,
            "height": 720
        },
        {
            "width": 1920,
            "height": 1080
        },
        {
            "width": 3840,
            "height": 2160
        }
    ]
}
```

#### Printing

Let's build the above JSON and print it to a string:

```c
//create a monitor with a list of supported resolutions
//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},
        {1920, 1080},
        {3840, 2160}
    };
    char *string = NULL;
    cJSON *name = NULL;
    cJSON *resolutions = NULL;
    cJSON *resolution = NULL;
    cJSON *width = NULL;
    cJSON *height = NULL;
    size_t index = 0;

    cJSON *monitor = cJSON_CreateObject();
    if (monitor == NULL)
    {
        goto end;
    }

    name = cJSON_CreateString("Awesome 4K");
    if (name == NULL)
    {
        goto end;
    }
    /* after creation was successful, immediately add it to the monitor,
     * thereby transferring ownership of the pointer to it */
    cJSON_AddItemToObject(monitor, "name", name);

    resolutions = cJSON_CreateArray();
    if (resolutions == NULL)
    {
        goto end;
    }
    cJSON_AddItemToObject(monitor, "resolutions", resolutions);

    for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
    {
        resolution = cJSON_CreateObject();
        if (resolution == NULL)
        {
            goto end;
        }
        cJSON_AddItemToArray(resolutions, resolution);

        width = cJSON_CreateNumber(resolution_numbers[index][0]);
        if (width == NULL)
        {
            goto end;
        }
        cJSON_AddItemToObject(resolution, "width", width);

        height = cJSON_CreateNumber(resolution_numbers[index][1]);
        if (height == NULL)
        {
            goto end;
        }
        cJSON_AddItemToObject(resolution, "height", height);
    }

    string = cJSON_Print(monitor);
    if (string == NULL)
    {
        fprintf(stderr, "Failed to print monitor.\n");
    }

end:
    cJSON_Delete(monitor);
    return string;
}
```

Alternatively we can use the `cJSON_Add...ToObject` helper functions to make our lives 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] = {
        {1280, 720},
        {1920, 1080},
        {3840, 2160}
    };
    char *string = NULL;
    cJSON *resolutions = NULL;
    size_t index = 0;

    cJSON *monitor = cJSON_CreateObject();

    if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
    {
        goto end;
    }

    resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
    if (resolutions == NULL)
    {
        goto end;
    }

    for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
    {
        cJSON *resolution = cJSON_CreateObject();

        if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
        {
            goto end;
        }

        if (cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
        {
            goto end;
        }

        cJSON_AddItemToArray(resolutions, resolution);
    }

    string = cJSON_Print(monitor);
    if (string == NULL)
    {
        fprintf(stderr, "Failed to print monitor.\n");
    }

end:
    cJSON_Delete(monitor);
    return string;
}
```

#### 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
/* return 1 if the monitor supports full hd, 0 otherwise */
int supports_full_hd(const char * const monitor)
{
    const cJSON *resolution = NULL;
    const cJSON *resolutions = NULL;
    const cJSON *name = NULL;
    int status = 0;
    cJSON *monitor_json = cJSON_Parse(monitor);
    if (monitor_json == NULL)
    {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL)
        {
            fprintf(stderr, "Error before: %s\n", error_ptr);
        }
        status = 0;
        goto end;
    }

    name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name");
    if (cJSON_IsString(name) && (name->valuestring != NULL))
    {
        printf("Checking monitor \"%s\"\n", name->valuestring);
    }

    resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
    cJSON_ArrayForEach(resolution, resolutions)
    {
        cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
        cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height");

        if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height))
        {
            status = 0;
            goto end;
        }

        if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
        {
            status = 1;
            goto end;
        }
    }

end:
    cJSON_Delete(monitor_json);
    return status;
}
```

Note that there are no NULL checks except for the result of `cJSON_Parse` because `cJSON_GetObjectItemCaseSensitive` checks for `NULL` inputs already, so a `NULL` value is just propagated and `cJSON_IsNumber` and `cJSON_IsString` return `0` if the input is `NULL`.

### Caveats

#### Zero Character

cJSON doesn't support strings that contain the zero character `'\0'` or `\u0000`. This is impossible with the current API because strings are zero terminated.

#### Character Encoding

cJSON only supports UTF-8 encoded input. In most cases it doesn't reject invalid UTF-8 as input though, it just propagates it through as is. As long as the input doesn't contain invalid UTF-8, the output will always be valid UTF-8.

#### C Standard

cJSON is written in ANSI C (or C89, C90). If your compiler or C library doesn't follow this standard, correct behavior is not guaranteed.

NOTE: ANSI C is not C++ therefore it shouldn't be compiled with a C++ compiler. You can compile it with a C compiler and link it with your C++ code however. Although compiling with a C++ compiler might work, correct behavior is not guaranteed.

#### Floating Point Numbers

cJSON does not officially support any `double` implementations other than IEEE754 double precision floating point numbers. It might still work with other implementations but bugs with these will be considered invalid.

The maximum length of a floating point literal that cJSON supports is currently 63 characters.

#### Deep Nesting Of Arrays And Objects

cJSON doesn't support arrays and objects that are nested too deeply because this would result in a stack overflow. To prevent this cJSON limits the depth to `CJSON_NESTING_LIMIT` which is 1000 by default but can be changed at compile time.

#### Thread Safety

In general cJSON is **not thread safe**.

However it is thread safe under the following conditions:

* `cJSON_GetErrorPtr` is never used (the `return_parse_end` parameter of `cJSON_ParseWithOpts` can be used instead)
* `cJSON_InitHooks` is only ever called before using cJSON in any threads.
* `setlocale` is never called before all calls to cJSON functions have returned.

#### Case Sensitivity

When cJSON was originally created, it didn't follow the JSON standard and didn't make a distinction between uppercase and lowercase letters. If you want the correct, standard compliant, behavior, you need to use the `CaseSensitive` functions where available.

#### Duplicate Object Members

cJSON supports parsing and printing JSON that contains objects that have multiple members with the same name. `cJSON_GetObjectItemCaseSensitive` however will always only return the first one.

# Enjoy cJSON!

- Dave Gamble (original author)
- Max Bruckner and Alan Wang (current maintainer)
- and the other [cJSON contributors](CONTRIBUTORS.md)


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Supported Versions

Security is of the highest importance and all security vulnerabilities or suspected security vulnerabilities should be reported to cjson team privately, to minimize attacks against current users of cjson before they are fixed. Vulnerabilities will be investigated and patched on the next patch (or minor) release as soon as possible. This information could be kept entirely internal to the project.

## Reporting a Vulnerability

If you know of a publicly disclosed security vulnerability for cjson, please IMMEDIATELY contact wp_scut@163.com and peterlee@apache.org to inform the cjson Team.

IMPORTANT: Do not file public issues on GitHub for security vulnerabilities.


================================================
FILE: appveyor.yml
================================================
os: Visual Studio 2015

# ENABLE_CUSTOM_COMPILER_FLAGS - on by default
# ENABLE_SANITIZERS - off by default
# ENABLE_PUBLIC_SYMBOLS - on by default
# BUILD_SHARED_LIBS - on by default
# ENABLE_TARGET_EXPORT - on by default
# ENABLE_CJSON_UTILS - off by default
# ENABLE_CJSON_TEST -on by default
# ENABLE_VALGRIND - off by default
# ENABLE_FUZZING - off by default

environment:
  matrix:
    - GENERATOR: "Visual Studio 14 2015"
      BUILD_SHARED_LIBS: ON
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON

    - GENERATOR: "Visual Studio 14 2015"
      BUILD_SHARED_LIBS: OFF
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON

    - GENERATOR: "Visual Studio 12 2013"
      BUILD_SHARED_LIBS: ON
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON

    - GENERATOR: "Visual Studio 12 2013"
      BUILD_SHARED_LIBS: OFF
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON

    - GENERATOR: "Visual Studio 11 2012"
      BUILD_SHARED_LIBS: ON
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON

    - GENERATOR: "Visual Studio 11 2012"
      BUILD_SHARED_LIBS: OFF
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON

    - GENERATOR: "Visual Studio 10 2010"
      BUILD_SHARED_LIBS: ON
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON

    - GENERATOR: "Visual Studio 10 2010"
      BUILD_SHARED_LIBS: OFF
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON

    - GENERATOR: "Visual Studio 9 2008"
      BUILD_SHARED_LIBS: ON
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON

    - GENERATOR: "Visual Studio 9 2008"
      BUILD_SHARED_LIBS: OFF
      ENABLE_CJSON_TEST: OFF
      ENABLE_CJSON_UTILS: ON


platform:
  - x86
  - x64
matrix:
  exclude:
  - platform: x64
    GENERATOR: "Visual Studio 9 2008"

configuration:
  - Release


build_script:
  - ps: if($env:PLATFORM -eq "x64") { $env:CMAKE_GEN_SUFFIX=" Win64" }
  - cmake "-G%GENERATOR%%CMAKE_GEN_SUFFIX%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% -DENABLE_CJSON_TEST=%ENABLE_CJSON_TEST%  -H. -Bbuild
  - cmake --build build --config "%CONFIGURATION%"


on_failure:
  - ps: if(Test-Path builds/CMakeFiles/CMakeOutput.log) { cat builds/CMakeFiles/CMakeOutput.log }
  - ps: if(Test-Path builds/CMakeFiles/CMakeError.log) { cat builds/CMakeFiles/CMakeError.log }

================================================
FILE: cJSON.c
================================================
/*
  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

/* cJSON */
/* JSON parser in C. */

/* disable warnings about old C89 functions in MSVC */
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
#define _CRT_SECURE_NO_DEPRECATE
#endif

#ifdef __GNUC__
#pragma GCC visibility push(default)
#endif
#if defined(_MSC_VER)
#pragma warning (push)
/* disable warning about single line comments in system headers */
#pragma warning (disable : 4001)
#endif

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <float.h>

#ifdef ENABLE_LOCALES
#include <locale.h>
#endif

#if defined(_MSC_VER)
#pragma warning (pop)
#endif
#ifdef __GNUC__
#pragma GCC visibility pop
#endif

#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;
} error;
static error global_error = { NULL, 0 };

CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
{
    return (const char*) (global_error.json + global_error.position);
}

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 != 19)
    #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif

CJSON_PUBLIC(const char*) cJSON_Version(void)
{
    static char version[15];
    sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);

    return version;
}

/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
{
    if ((string1 == NULL) || (string2 == NULL))
    {
        return 1;
    }

    if (string1 == string2)
    {
        return 0;
    }

    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
    {
        if (*string1 == '\0')
        {
            return 0;
        }
    }

    return tolower(*string1) - tolower(*string2);
}

typedef struct internal_hooks
{
    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 dllimport '...' is not static */
static void * CJSON_CDECL internal_malloc(size_t size)
{
    return malloc(size);
}
static void CJSON_CDECL internal_free(void *pointer)
{
    free(pointer);
}
static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
{
    return realloc(pointer, size);
}
#else
#define internal_malloc malloc
#define internal_free free
#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)
{
    size_t length = 0;
    unsigned char *copy = NULL;

    if (string == NULL)
    {
        return NULL;
    }

    length = strlen((const char*)string) + sizeof("");
    copy = (unsigned char*)hooks->allocate(length);
    if (copy == NULL)
    {
        return NULL;
    }
    memcpy(copy, string, length);

    return copy;
}

CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
{
    if (hooks == NULL)
    {
        /* Reset hooks */
        global_hooks.allocate = malloc;
        global_hooks.deallocate = free;
        global_hooks.reallocate = realloc;
        return;
    }

    global_hooks.allocate = malloc;
    if (hooks->malloc_fn != NULL)
    {
        global_hooks.allocate = hooks->malloc_fn;
    }

    global_hooks.deallocate = free;
    if (hooks->free_fn != NULL)
    {
        global_hooks.deallocate = hooks->free_fn;
    }

    /* use realloc only if both free and malloc are used */
    global_hooks.reallocate = NULL;
    if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
    {
        global_hooks.reallocate = realloc;
    }
}

/* Internal constructor. */
static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
{
    cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
    if (node)
    {
        memset(node, '\0', sizeof(cJSON));
    }

    return node;
}

/* Delete a cJSON structure. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
{
    cJSON *next = NULL;
    while (item != NULL)
    {
        next = item->next;
        if (!(item->type & cJSON_IsReference) && (item->child != NULL))
        {
            cJSON_Delete(item->child);
        }
        if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
        {
            global_hooks.deallocate(item->valuestring);
            item->valuestring = NULL;
        }
        if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
        {
            global_hooks.deallocate(item->string);
            item->string = NULL;
        }
        global_hooks.deallocate(item);
        item = next;
    }
}

/* get the decimal point character of the current locale */
static unsigned char get_decimal_point(void)
{
#ifdef ENABLE_LOCALES
    struct lconv *lconv = localeconv();
    return (unsigned char) lconv->decimal_point[0];
#else
    return '.';
#endif
}

typedef struct
{
    const unsigned char *content;
    size_t length;
    size_t offset;
    size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
    internal_hooks hooks;
} parse_buffer;

/* check if the given size is left to read in a given parse buffer (starting with 1) */
#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
/* check if the buffer can be accessed at the given index (starting with 0) */
#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
/* get a pointer to the buffer at the position */
#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)

/* Parse the input text to generate a number, and populate the result into item. */
static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
{
    double number = 0;
    unsigned char *after_end = NULL;
    unsigned char *number_c_string;
    unsigned char decimal_point = get_decimal_point();
    size_t i = 0;
    size_t number_string_length = 0;
    cJSON_bool has_decimal_point = false;

    if ((input_buffer == NULL) || (input_buffer->content == NULL))
    {
        return false;
    }

    /* copy the number into a temporary buffer and replace '.' with the decimal point
     * of the current locale (for strtod)
     * This also takes care of '\0' not necessarily being available for marking the end of the input */
    for (i = 0; can_access_at_index(input_buffer, i); i++)
    {
        switch (buffer_at_offset(input_buffer)[i])
        {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            case '+':
            case '-':
            case 'e':
            case 'E':
                number_string_length++;
                break;

            case '.':
                number_string_length++;
                has_decimal_point = true;
                break;

            default:
                goto loop_end;
        }
    }
loop_end:
    /* malloc for temporary buffer, add 1 for '\0' */
    number_c_string = (unsigned char *) input_buffer->hooks.allocate(number_string_length + 1);
    if (number_c_string == NULL)
    {
        return false; /* allocation failure */
    }

    memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length);
    number_c_string[number_string_length] = '\0';

    if (has_decimal_point)
    {
        for (i = 0; i < number_string_length; i++)
        {
            if (number_c_string[i] == '.')
            {
                /* replace '.' with the decimal point of the current locale (for strtod) */
                number_c_string[i] = decimal_point;
            }
        }
    }

    number = strtod((const char*)number_c_string, (char**)&after_end);
    if (number_c_string == after_end)
    {
        /* free the temporary buffer */
        input_buffer->hooks.deallocate(number_c_string);
        return false; /* parse_error */
    }

    item->valuedouble = number;

    /* use saturation in case of overflow */
    if (number >= INT_MAX)
    {
        item->valueint = INT_MAX;
    }
    else if (number <= (double)INT_MIN)
    {
        item->valueint = INT_MIN;
    }
    else
    {
        item->valueint = (int)number;
    }

    item->type = cJSON_Number;

    input_buffer->offset += (size_t)(after_end - number_c_string);
    /* free the temporary buffer */
    input_buffer->hooks.deallocate(number_c_string);
    return true;
}

/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
{
    if (object == NULL)
    {
        return (double)NAN;
    }

    if (number >= INT_MAX)
    {
        object->valueint = INT_MAX;
    }
    else if (number <= (double)INT_MIN)
    {
        object->valueint = INT_MIN;
    }
    else
    {
        object->valueint = (int)number;
    }

    return object->valuedouble = number;
}

/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
{
    char *copy = NULL;
    size_t v1_len;
    size_t v2_len;
    /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
    if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
    {
        return NULL;
    }
    /* return NULL if the object is corrupted or valuestring is NULL */
    if (object->valuestring == NULL || valuestring == NULL)
    {
        return NULL;
    }

    v1_len = strlen(valuestring);
    v2_len = strlen(object->valuestring);

    if (v1_len <= v2_len)
    {
        /* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */
        if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring ))
        {
            return NULL;
        }
        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;
    size_t length;
    size_t offset;
    size_t depth; /* current nesting depth (for formatted printing) */
    cJSON_bool noalloc;
    cJSON_bool format; /* is this print a formatted print */
    internal_hooks hooks;
} printbuffer;

/* realloc printbuffer if necessary to have at least "needed" bytes more */
static unsigned char* ensure(printbuffer * const p, size_t needed)
{
    unsigned char *newbuffer = NULL;
    size_t newsize = 0;

    if ((p == NULL) || (p->buffer == NULL))
    {
        return NULL;
    }

    if ((p->length > 0) && (p->offset >= p->length))
    {
        /* make sure that offset is valid */
        return NULL;
    }

    if (needed > INT_MAX)
    {
        /* sizes bigger than INT_MAX are currently not supported */
        return NULL;
    }

    needed += p->offset + 1;
    if (needed <= p->length)
    {
        return p->buffer + p->offset;
    }

    if (p->noalloc) {
        return NULL;
    }

    /* calculate new buffer size */
    if (needed > (INT_MAX / 2))
    {
        /* overflow of int, use INT_MAX if possible */
        if (needed <= INT_MAX)
        {
            newsize = INT_MAX;
        }
        else
        {
            return NULL;
        }
    }
    else
    {
        newsize = needed * 2;
    }

    if (p->hooks.reallocate != NULL)
    {
        /* reallocate with realloc if available */
        newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
        if (newbuffer == NULL)
        {
            p->hooks.deallocate(p->buffer);
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }
    }
    else
    {
        /* otherwise reallocate manually */
        newbuffer = (unsigned char*)p->hooks.allocate(newsize);
        if (!newbuffer)
        {
            p->hooks.deallocate(p->buffer);
            p->length = 0;
            p->buffer = NULL;

            return NULL;
        }

        memcpy(newbuffer, p->buffer, p->offset + 1);
        p->hooks.deallocate(p->buffer);
    }
    p->length = newsize;
    p->buffer = newbuffer;

    return newbuffer + p->offset;
}

/* calculate the new length of the string in a printbuffer and update the offset */
static void update_offset(printbuffer * const buffer)
{
    const unsigned char *buffer_pointer = NULL;
    if ((buffer == NULL) || (buffer->buffer == NULL))
    {
        return;
    }
    buffer_pointer = buffer->buffer + buffer->offset;

    buffer->offset += strlen((const char*)buffer_pointer);
}

/* 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)
{
    unsigned char *output_pointer = NULL;
    double d = item->valuedouble;
    int length = 0;
    size_t i = 0;
    unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
    unsigned char decimal_point = get_decimal_point();
    double test = 0.0;

    if (output_buffer == NULL)
    {
        return false;
    }

    /* This checks for NaN and Infinity */
    if (isnan(d) || isinf(d))
    {
        length = sprintf((char*)number_buffer, "null");
    }
    else if(d == (double)item->valueint)
    {
        length = sprintf((char*)number_buffer, "%d", item->valueint);
    }
    else
    {
        /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
        length = sprintf((char*)number_buffer, "%1.15g", d);

        /* Check whether the original double can be recovered */
        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 occurred */
    if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
    {
        return false;
    }

    /* reserve appropriate space in the output */
    output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
    if (output_pointer == NULL)
    {
        return false;
    }

    /* copy the printed number to the output and replace locale
     * dependent decimal point with '.' */
    for (i = 0; i < ((size_t)length); i++)
    {
        if (number_buffer[i] == decimal_point)
        {
            output_pointer[i] = '.';
            continue;
        }

        output_pointer[i] = number_buffer[i];
    }
    output_pointer[i] = '\0';

    output_buffer->offset += (size_t)length;

    return true;
}

/* parse 4 digit hexadecimal number */
static unsigned parse_hex4(const unsigned char * const input)
{
    unsigned int h = 0;
    size_t i = 0;

    for (i = 0; i < 4; i++)
    {
        /* parse digit */
        if ((input[i] >= '0') && (input[i] <= '9'))
        {
            h += (unsigned int) input[i] - '0';
        }
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
        {
            h += (unsigned int) 10 + input[i] - 'A';
        }
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
        {
            h += (unsigned int) 10 + input[i] - 'a';
        }
        else /* invalid */
        {
            return 0;
        }

        if (i < 3)
        {
            /* shift left to make place for the next nibble */
            h = h << 4;
        }
    }

    return h;
}

/* converts a UTF-16 literal to UTF-8
 * A literal can be one or two sequences of the form \uXXXX */
static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
{
    long unsigned int codepoint = 0;
    unsigned int first_code = 0;
    const unsigned char *first_sequence = input_pointer;
    unsigned char utf8_length = 0;
    unsigned char utf8_position = 0;
    unsigned char sequence_length = 0;
    unsigned char first_byte_mark = 0;

    if ((input_end - first_sequence) < 6)
    {
        /* input ends unexpectedly */
        goto fail;
    }

    /* get the first utf16 sequence */
    first_code = parse_hex4(first_sequence + 2);

    /* check that the code is valid */
    if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
    {
        goto fail;
    }

    /* UTF16 surrogate pair */
    if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
    {
        const unsigned char *second_sequence = first_sequence + 6;
        unsigned int second_code = 0;
        sequence_length = 12; /* \uXXXX\uXXXX */

        if ((input_end - second_sequence) < 6)
        {
            /* input ends unexpectedly */
            goto fail;
        }

        if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
        {
            /* missing second half of the surrogate pair */
            goto fail;
        }

        /* get the second utf16 sequence */
        second_code = parse_hex4(second_sequence + 2);
        /* check that the code is valid */
        if ((second_code < 0xDC00) || (second_code > 0xDFFF))
        {
            /* invalid second half of the surrogate pair */
            goto fail;
        }


        /* calculate the unicode codepoint from the surrogate pair */
        codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
    }
    else
    {
        sequence_length = 6; /* \uXXXX */
        codepoint = first_code;
    }

    /* encode as UTF-8
     * takes at maximum 4 bytes to encode:
     * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
    if (codepoint < 0x80)
    {
        /* normal ascii, encoding 0xxxxxxx */
        utf8_length = 1;
    }
    else if (codepoint < 0x800)
    {
        /* two bytes, encoding 110xxxxx 10xxxxxx */
        utf8_length = 2;
        first_byte_mark = 0xC0; /* 11000000 */
    }
    else if (codepoint < 0x10000)
    {
        /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
        utf8_length = 3;
        first_byte_mark = 0xE0; /* 11100000 */
    }
    else if (codepoint <= 0x10FFFF)
    {
        /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
        utf8_length = 4;
        first_byte_mark = 0xF0; /* 11110000 */
    }
    else
    {
        /* invalid unicode codepoint */
        goto fail;
    }

    /* encode as utf8 */
    for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
    {
        /* 10xxxxxx */
        (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
        codepoint >>= 6;
    }
    /* encode first byte */
    if (utf8_length > 1)
    {
        (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
    }
    else
    {
        (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
    }

    *output_pointer += utf8_length;

    return sequence_length;

fail:
    return 0;
}

/* Parse the input text into an unescaped cinput, and populate item. */
static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
{
    const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
    const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
    unsigned char *output_pointer = NULL;
    unsigned char *output = NULL;

    /* not a string */
    if (buffer_at_offset(input_buffer)[0] != '\"')
    {
        goto fail;
    }

    {
        /* calculate approximate size of the output (overestimate) */
        size_t allocation_length = 0;
        size_t skipped_bytes = 0;
        while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
        {
            /* is escape sequence */
            if (input_end[0] == '\\')
            {
                if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
                {
                    /* prevent buffer overflow when last input character is a backslash */
                    goto fail;
                }
                skipped_bytes++;
                input_end++;
            }
            input_end++;
        }
        if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
        {
            goto fail; /* string ended unexpectedly */
        }

        /* This is at most how much we need for the output */
        allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
        output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
        if (output == NULL)
        {
            goto fail; /* allocation failure */
        }
    }

    output_pointer = output;
    /* loop through the string literal */
    while (input_pointer < input_end)
    {
        if (*input_pointer != '\\')
        {
            *output_pointer++ = *input_pointer++;
        }
        /* escape sequence */
        else
        {
            unsigned char sequence_length = 2;
            if ((input_end - input_pointer) < 1)
            {
                goto fail;
            }

            switch (input_pointer[1])
            {
                case 'b':
                    *output_pointer++ = '\b';
                    break;
                case 'f':
                    *output_pointer++ = '\f';
                    break;
                case 'n':
                    *output_pointer++ = '\n';
                    break;
                case 'r':
                    *output_pointer++ = '\r';
                    break;
                case 't':
                    *output_pointer++ = '\t';
                    break;
                case '\"':
                case '\\':
                case '/':
                    *output_pointer++ = input_pointer[1];
                    break;

                /* UTF-16 literal */
                case 'u':
                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
                    if (sequence_length == 0)
                    {
                        /* failed to convert UTF16-literal to UTF-8 */
                        goto fail;
                    }
                    break;

                default:
                    goto fail;
            }
            input_pointer += sequence_length;
        }
    }

    /* zero terminate the output */
    *output_pointer = '\0';

    item->type = cJSON_String;
    item->valuestring = (char*)output;

    input_buffer->offset = (size_t) (input_end - input_buffer->content);
    input_buffer->offset++;

    return true;

fail:
    if (output != NULL)
    {
        input_buffer->hooks.deallocate(output);
        output = NULL;
    }

    if (input_pointer != NULL)
    {
        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
    }

    return false;
}

/* Render the cstring provided to an escaped version that can be printed. */
static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
{
    const unsigned char *input_pointer = NULL;
    unsigned char *output = NULL;
    unsigned char *output_pointer = NULL;
    size_t output_length = 0;
    /* numbers of additional characters needed for escaping */
    size_t escape_characters = 0;

    if (output_buffer == NULL)
    {
        return false;
    }

    /* empty string */
    if (input == NULL)
    {
        output = ensure(output_buffer, sizeof("\"\""));
        if (output == NULL)
        {
            return false;
        }
        strcpy((char*)output, "\"\"");

        return true;
    }

    /* set "flag" to 1 if something needs to be escaped */
    for (input_pointer = input; *input_pointer; input_pointer++)
    {
        switch (*input_pointer)
        {
            case '\"':
            case '\\':
            case '\b':
            case '\f':
            case '\n':
            case '\r':
            case '\t':
                /* one character escape sequence */
                escape_characters++;
                break;
            default:
                if (*input_pointer < 32)
                {
                    /* UTF-16 escape sequence uXXXX */
                    escape_characters += 5;
                }
                break;
        }
    }
    output_length = (size_t)(input_pointer - input) + escape_characters;

    output = ensure(output_buffer, output_length + sizeof("\"\""));
    if (output == NULL)
    {
        return false;
    }

    /* no characters have to be escaped */
    if (escape_characters == 0)
    {
        output[0] = '\"';
        memcpy(output + 1, input, output_length);
        output[output_length + 1] = '\"';
        output[output_length + 2] = '\0';

        return true;
    }

    output[0] = '\"';
    output_pointer = output + 1;
    /* copy the string */
    for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
    {
        if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
        {
            /* normal character, copy */
            *output_pointer = *input_pointer;
        }
        else
        {
            /* character needs to be escaped */
            *output_pointer++ = '\\';
            switch (*input_pointer)
            {
                case '\\':
                    *output_pointer = '\\';
                    break;
                case '\"':
                    *output_pointer = '\"';
                    break;
                case '\b':
                    *output_pointer = 'b';
                    break;
                case '\f':
                    *output_pointer = 'f';
                    break;
                case '\n':
                    *output_pointer = 'n';
                    break;
                case '\r':
                    *output_pointer = 'r';
                    break;
                case '\t':
                    *output_pointer = 't';
                    break;
                default:
                    /* escape and print as unicode codepoint */
                    sprintf((char*)output_pointer, "u%04x", *input_pointer);
                    output_pointer += 4;
                    break;
            }
        }
    }
    output[output_length + 1] = '\"';
    output[output_length + 2] = '\0';

    return true;
}

/* Invoke print_string_ptr (which is useful) on an item. */
static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
{
    return print_string_ptr((unsigned char*)item->valuestring, p);
}

/* Predeclare these prototypes. */
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);

/* Utility to jump whitespace and cr/lf */
static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
{
    if ((buffer == NULL) || (buffer->content == NULL))
    {
        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++;
    }

    if (buffer->offset == buffer->length)
    {
        buffer->offset--;
    }

    return buffer;
}

/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
{
    if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
    {
        return NULL;
    }

    if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
    {
        buffer->offset += 3;
    }

    return buffer;
}

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;

    /* reset error position */
    global_error.json = NULL;
    global_error.position = 0;

    if (value == NULL || 0 == buffer_length)
    {
        goto fail;
    }

    buffer.content = (const unsigned char*)value;
    buffer.length = buffer_length;
    buffer.offset = 0;
    buffer.hooks = global_hooks;

    item = cJSON_New_Item(&global_hooks);
    if (item == NULL) /* memory fail */
    {
        goto fail;
    }

    if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
    {
        /* parse failure. ep is set. */
        goto fail;
    }

    /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
    if (require_null_terminated)
    {
        buffer_skip_whitespace(&buffer);
        if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
        {
            goto fail;
        }
    }
    if (return_parse_end)
    {
        *return_parse_end = (const char*)buffer_at_offset(&buffer);
    }

    return item;

fail:
    if (item != NULL)
    {
        cJSON_Delete(item);
    }

    if (value != NULL)
    {
        error local_error;
        local_error.json = (const unsigned char*)value;
        local_error.position = 0;

        if (buffer.offset < buffer.length)
        {
            local_error.position = buffer.offset;
        }
        else if (buffer.length > 0)
        {
            local_error.position = buffer.length - 1;
        }

        if (return_parse_end != NULL)
        {
            *return_parse_end = (const char*)local_error.json + local_error.position;
        }

        global_error = local_error;
    }

    return NULL;
}

/* Default options for cJSON_Parse */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
{
    return cJSON_ParseWithOpts(value, 0, 0);
}

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)
{
    static const size_t default_buffer_size = 256;
    printbuffer buffer[1];
    unsigned char *printed = NULL;

    memset(buffer, 0, sizeof(buffer));

    /* create buffer */
    buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
    buffer->length = default_buffer_size;
    buffer->format = format;
    buffer->hooks = *hooks;
    if (buffer->buffer == NULL)
    {
        goto fail;
    }

    /* print the value */
    if (!print_value(item, buffer))
    {
        goto fail;
    }
    update_offset(buffer);

    /* check if reallocate is available */
    if (hooks->reallocate != NULL)
    {
        printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
        if (printed == NULL) {
            goto fail;
        }
        buffer->buffer = NULL;
    }
    else /* otherwise copy the JSON over to a new buffer */
    {
        printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
        if (printed == NULL)
        {
            goto fail;
        }
        memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
        printed[buffer->offset] = '\0'; /* just to be sure */

        /* free the buffer */
        hooks->deallocate(buffer->buffer);
        buffer->buffer = NULL;
    }

    return printed;

fail:
    if (buffer->buffer != NULL)
    {
        hooks->deallocate(buffer->buffer);
        buffer->buffer = NULL;
    }

    if (printed != NULL)
    {
        hooks->deallocate(printed);
        printed = NULL;
    }

    return NULL;
}

/* Render a cJSON item/entity/structure to text. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
{
    return (char*)print(item, true, &global_hooks);
}

CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
{
    return (char*)print(item, false, &global_hooks);
}

CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
{
    printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };

    if (prebuffer < 0)
    {
        return NULL;
    }

    p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
    if (!p.buffer)
    {
        return NULL;
    }

    p.length = (size_t)prebuffer;
    p.offset = 0;
    p.noalloc = false;
    p.format = fmt;
    p.hooks = global_hooks;

    if (!print_value(item, &p))
    {
        global_hooks.deallocate(p.buffer);
        p.buffer = NULL;
        return NULL;
    }

    return (char*)p.buffer;
}

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 ((length < 0) || (buffer == NULL))
    {
        return false;
    }

    p.buffer = (unsigned char*)buffer;
    p.length = (size_t)length;
    p.offset = 0;
    p.noalloc = true;
    p.format = format;
    p.hooks = global_hooks;

    return print_value(item, &p);
}

/* Parser core - when encountering text, process appropriately. */
static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
{
    if ((input_buffer == NULL) || (input_buffer->content == NULL))
    {
        return false; /* no input */
    }

    /* parse the different types of values */
    /* null */
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
    {
        item->type = cJSON_NULL;
        input_buffer->offset += 4;
        return true;
    }
    /* false */
    if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
    {
        item->type = cJSON_False;
        input_buffer->offset += 5;
        return true;
    }
    /* true */
    if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
    {
        item->type = cJSON_True;
        item->valueint = 1;
        input_buffer->offset += 4;
        return true;
    }
    /* string */
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
    {
        return parse_string(item, input_buffer);
    }
    /* number */
    if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
    {
        return parse_number(item, input_buffer);
    }
    /* array */
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
    {
        return parse_array(item, input_buffer);
    }
    /* object */
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
    {
        return parse_object(item, input_buffer);
    }

    return false;
}

/* Render a value to text. */
static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
{
    unsigned char *output = NULL;

    if ((item == NULL) || (output_buffer == NULL))
    {
        return false;
    }

    switch ((item->type) & 0xFF)
    {
        case cJSON_NULL:
            output = ensure(output_buffer, 5);
            if (output == NULL)
            {
                return false;
            }
            strcpy((char*)output, "null");
            return true;

        case cJSON_False:
            output = ensure(output_buffer, 6);
            if (output == NULL)
            {
                return false;
            }
            strcpy((char*)output, "false");
            return true;

        case cJSON_True:
            output = ensure(output_buffer, 5);
            if (output == NULL)
            {
                return false;
            }
            strcpy((char*)output, "true");
            return true;

        case cJSON_Number:
            return print_number(item, output_buffer);

        case cJSON_Raw:
        {
            size_t raw_length = 0;
            if (item->valuestring == NULL)
            {
                return false;
            }

            raw_length = strlen(item->valuestring) + sizeof("");
            output = ensure(output_buffer, raw_length);
            if (output == NULL)
            {
                return false;
            }
            memcpy(output, item->valuestring, raw_length);
            return true;
        }

        case cJSON_String:
            return print_string(item, output_buffer);

        case cJSON_Array:
            return print_array(item, output_buffer);

        case cJSON_Object:
            return print_object(item, output_buffer);

        default:
            return false;
    }
}

/* Build an array from input text. */
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
{
    cJSON *head = NULL; /* head of the linked list */
    cJSON *current_item = NULL;

    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* to deeply nested */
    }
    input_buffer->depth++;

    if (buffer_at_offset(input_buffer)[0] != '[')
    {
        /* not an array */
        goto fail;
    }

    input_buffer->offset++;
    buffer_skip_whitespace(input_buffer);
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
    {
        /* empty array */
        goto success;
    }

    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

    /* step back to character in front of the first element */
    input_buffer->offset--;
    /* loop through the comma separated array elements */
    do
    {
        /* allocate next item */
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
        if (new_item == NULL)
        {
            goto fail; /* allocation failure */
        }

        /* attach next item to list */
        if (head == NULL)
        {
            /* start the linked list */
            current_item = head = new_item;
        }
        else
        {
            /* add to the end and advance */
            current_item->next = new_item;
            new_item->prev = current_item;
            current_item = new_item;
        }

        /* parse next value */
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
        if (!parse_value(current_item, input_buffer))
        {
            goto fail; /* failed to parse value */
        }
        buffer_skip_whitespace(input_buffer);
    }
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));

    if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
    {
        goto fail; /* expected end of array */
    }

success:
    input_buffer->depth--;

    if (head != NULL) {
        head->prev = current_item;
    }

    item->type = cJSON_Array;
    item->child = head;

    input_buffer->offset++;

    return true;

fail:
    if (head != NULL)
    {
        cJSON_Delete(head);
    }

    return false;
}

/* Render an array to text */
static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
{
    unsigned char *output_pointer = NULL;
    size_t length = 0;
    cJSON *current_element = item->child;

    if (output_buffer == NULL)
    {
        return false;
    }

    if (output_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* nesting is too deep */
    }

    /* Compose the output array. */
    /* opening square bracket */
    output_pointer = ensure(output_buffer, 1);
    if (output_pointer == NULL)
    {
        return false;
    }

    *output_pointer = '[';
    output_buffer->offset++;
    output_buffer->depth++;

    while (current_element != NULL)
    {
        if (!print_value(current_element, output_buffer))
        {
            return false;
        }
        update_offset(output_buffer);
        if (current_element->next)
        {
            length = (size_t) (output_buffer->format ? 2 : 1);
            output_pointer = ensure(output_buffer, length + 1);
            if (output_pointer == NULL)
            {
                return false;
            }
            *output_pointer++ = ',';
            if(output_buffer->format)
            {
                *output_pointer++ = ' ';
            }
            *output_pointer = '\0';
            output_buffer->offset += length;
        }
        current_element = current_element->next;
    }

    output_pointer = ensure(output_buffer, 2);
    if (output_pointer == NULL)
    {
        return false;
    }
    *output_pointer++ = ']';
    *output_pointer = '\0';
    output_buffer->depth--;

    return true;
}

/* Build an object from the text. */
static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
{
    cJSON *head = NULL; /* linked list head */
    cJSON *current_item = NULL;

    if (input_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* to deeply nested */
    }
    input_buffer->depth++;

    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
    {
        goto fail; /* not an object */
    }

    input_buffer->offset++;
    buffer_skip_whitespace(input_buffer);
    if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
    {
        goto success; /* empty object */
    }

    /* check if we skipped to the end of the buffer */
    if (cannot_access_at_index(input_buffer, 0))
    {
        input_buffer->offset--;
        goto fail;
    }

    /* step back to character in front of the first element */
    input_buffer->offset--;
    /* loop through the comma separated array elements */
    do
    {
        /* allocate next item */
        cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
        if (new_item == NULL)
        {
            goto fail; /* allocation failure */
        }

        /* attach next item to list */
        if (head == NULL)
        {
            /* start the linked list */
            current_item = head = new_item;
        }
        else
        {
            /* add to the end and advance */
            current_item->next = new_item;
            new_item->prev = current_item;
            current_item = new_item;
        }

        if (cannot_access_at_index(input_buffer, 1))
        {
            goto fail; /* nothing comes after the comma */
        }

        /* parse the name of the child */
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
        if (!parse_string(current_item, input_buffer))
        {
            goto fail; /* failed to parse name */
        }
        buffer_skip_whitespace(input_buffer);

        /* swap valuestring and string, because we parsed the name */
        current_item->string = current_item->valuestring;
        current_item->valuestring = NULL;

        if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
        {
            goto fail; /* invalid object */
        }

        /* parse the value */
        input_buffer->offset++;
        buffer_skip_whitespace(input_buffer);
        if (!parse_value(current_item, input_buffer))
        {
            goto fail; /* failed to parse value */
        }
        buffer_skip_whitespace(input_buffer);
    }
    while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));

    if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
    {
        goto fail; /* expected end of object */
    }

success:
    input_buffer->depth--;

    if (head != NULL) {
        head->prev = current_item;
    }

    item->type = cJSON_Object;
    item->child = head;

    input_buffer->offset++;
    return true;

fail:
    if (head != NULL)
    {
        cJSON_Delete(head);
    }

    return false;
}

/* Render an object to text. */
static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
{
    unsigned char *output_pointer = NULL;
    size_t length = 0;
    cJSON *current_item = item->child;

    if (output_buffer == NULL)
    {
        return false;
    }

    if (output_buffer->depth >= CJSON_NESTING_LIMIT)
    {
        return false; /* nesting is too deep */
    }

    /* Compose the output: */
    length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
    output_pointer = ensure(output_buffer, length + 1);
    if (output_pointer == NULL)
    {
        return false;
    }

    *output_pointer++ = '{';
    output_buffer->depth++;
    if (output_buffer->format)
    {
        *output_pointer++ = '\n';
    }
    output_buffer->offset += length;

    while (current_item)
    {
        if (output_buffer->format)
        {
            size_t i;
            output_pointer = ensure(output_buffer, output_buffer->depth);
            if (output_pointer == NULL)
            {
                return false;
            }
            for (i = 0; i < output_buffer->depth; i++)
            {
                *output_pointer++ = '\t';
            }
            output_buffer->offset += output_buffer->depth;
        }

        /* print key */
        if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
        {
            return false;
        }
        update_offset(output_buffer);

        length = (size_t) (output_buffer->format ? 2 : 1);
        output_pointer = ensure(output_buffer, length);
        if (output_pointer == NULL)
        {
            return false;
        }
        *output_pointer++ = ':';
        if (output_buffer->format)
        {
            *output_pointer++ = '\t';
        }
        output_buffer->offset += length;

        /* print value */
        if (!print_value(current_item, output_buffer))
        {
            return false;
        }
        update_offset(output_buffer);

        /* print comma if not last */
        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)
        {
            return false;
        }
        if (current_item->next)
        {
            *output_pointer++ = ',';
        }

        if (output_buffer->format)
        {
            *output_pointer++ = '\n';
        }
        *output_pointer = '\0';
        output_buffer->offset += length;

        current_item = current_item->next;
    }

    output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
    if (output_pointer == NULL)
    {
        return false;
    }
    if (output_buffer->format)
    {
        size_t i;
        for (i = 0; i < (output_buffer->depth - 1); i++)
        {
            *output_pointer++ = '\t';
        }
    }
    *output_pointer++ = '}';
    *output_pointer = '\0';
    output_buffer->depth--;

    return true;
}

/* Get Array size/item / object item. */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
{
    cJSON *child = NULL;
    size_t size = 0;

    if (array == NULL)
    {
        return 0;
    }

    child = array->child;

    while(child != NULL)
    {
        size++;
        child = child->next;
    }

    /* FIXME: Can overflow here. Cannot be fixed without breaking the API */

    return (int)size;
}

static cJSON* get_array_item(const cJSON *array, size_t index)
{
    cJSON *current_child = NULL;

    if (array == NULL)
    {
        return NULL;
    }

    current_child = array->child;
    while ((current_child != NULL) && (index > 0))
    {
        index--;
        current_child = current_child->next;
    }

    return current_child;
}

CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
{
    if (index < 0)
    {
        return NULL;
    }

    return get_array_item(array, (size_t)index);
}

static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
{
    cJSON *current_element = NULL;

    if ((object == NULL) || (name == NULL))
    {
        return NULL;
    }

    current_element = object->child;
    if (case_sensitive)
    {
        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
        {
            current_element = current_element->next;
        }
    }
    else
    {
        while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
        {
            current_element = current_element->next;
        }
    }

    if ((current_element == NULL) || (current_element->string == NULL)) {
        return NULL;
    }

    return current_element;
}

CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
{
    return get_object_item(object, string, false);
}

CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
{
    return get_object_item(object, string, true);
}

CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
{
    return cJSON_GetObjectItem(object, string) ? 1 : 0;
}

/* Utility for array list handling. */
static void suffix_object(cJSON *prev, cJSON *item)
{
    prev->next = item;
    item->prev = prev;
}

/* Utility for handling references. */
static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
{
    cJSON *reference = NULL;
    if (item == NULL)
    {
        return NULL;
    }

    reference = cJSON_New_Item(hooks);
    if (reference == NULL)
    {
        return NULL;
    }

    memcpy(reference, item, sizeof(cJSON));
    reference->string = NULL;
    reference->type |= cJSON_IsReference;
    reference->next = reference->prev = NULL;
    return reference;
}

static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
{
    cJSON *child = 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 */
        if (child->prev)
        {
            suffix_object(child->prev, item);
            array->child->prev = item;
        }
    }

    return true;
}

/* Add item to array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
{
    return add_item_to_array(array, item);
}

#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
    #pragma GCC diagnostic push
#endif
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
/* helper function to cast away const */
static void* cast_away_const(const void* string)
{
    return (void*)string;
}
#if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
    #pragma GCC diagnostic pop
#endif


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

    item->string = new_key;
    item->type = new_type;

    return add_item_to_array(object, item);
}

CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
{
    return add_item_to_object(object, string, item, &global_hooks, false);
}

/* Add an item to an object with constant string as key */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
{
    return add_item_to_object(object, string, item, &global_hooks, true);
}

CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
{
    if (array == NULL)
    {
        return false;
    }

    return add_item_to_array(array, create_reference(item, &global_hooks));
}

CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
{
    if ((object == NULL) || (string == NULL))
    {
        return 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)
{
    cJSON *null = cJSON_CreateNull();
    if (add_item_to_object(object, name, null, &global_hooks, false))
    {
        return null;
    }

    cJSON_Delete(null);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
{
    cJSON *true_item = cJSON_CreateTrue();
    if (add_item_to_object(object, name, true_item, &global_hooks, false))
    {
        return true_item;
    }

    cJSON_Delete(true_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
{
    cJSON *false_item = cJSON_CreateFalse();
    if (add_item_to_object(object, name, false_item, &global_hooks, false))
    {
        return false_item;
    }

    cJSON_Delete(false_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
{
    cJSON *bool_item = cJSON_CreateBool(boolean);
    if (add_item_to_object(object, name, bool_item, &global_hooks, false))
    {
        return bool_item;
    }

    cJSON_Delete(bool_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
{
    cJSON *number_item = cJSON_CreateNumber(number);
    if (add_item_to_object(object, name, number_item, &global_hooks, false))
    {
        return number_item;
    }

    cJSON_Delete(number_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
{
    cJSON *string_item = cJSON_CreateString(string);
    if (add_item_to_object(object, name, string_item, &global_hooks, false))
    {
        return string_item;
    }

    cJSON_Delete(string_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
{
    cJSON *raw_item = cJSON_CreateRaw(raw);
    if (add_item_to_object(object, name, raw_item, &global_hooks, false))
    {
        return raw_item;
    }

    cJSON_Delete(raw_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
{
    cJSON *object_item = cJSON_CreateObject();
    if (add_item_to_object(object, name, object_item, &global_hooks, false))
    {
        return object_item;
    }

    cJSON_Delete(object_item);
    return NULL;
}

CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
{
    cJSON *array = cJSON_CreateArray();
    if (add_item_to_object(object, name, array, &global_hooks, false))
    {
        return array;
    }

    cJSON_Delete(array);
    return NULL;
}

CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
{
    if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL))
    {
        return NULL;
    }

    if (item != parent->child)
    {
        /* not the first element */
        item->prev->next = item->next;
    }
    if (item->next != NULL)
    {
        /* not the last element */
        item->next->prev = item->prev;
    }

    if (item == parent->child)
    {
        /* 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;

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
{
    if (which < 0)
    {
        return NULL;
    }

    return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
}

CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
{
    cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}

CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
{
    cJSON *to_detach = cJSON_GetObjectItem(object, string);

    return cJSON_DetachItemViaPointer(object, to_detach);
}

CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
{
    cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);

    return cJSON_DetachItemViaPointer(object, to_detach);
}

CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
{
    cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}

CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
{
    cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
}

/* Replace array/object items with new ones. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
{
    cJSON *after_inserted = NULL;

    if (which < 0 || newitem == NULL)
    {
        return false;
    }

    after_inserted = get_array_item(array, (size_t)which);
    if (after_inserted == NULL)
    {
        return add_item_to_array(array, newitem);
    }

    if (after_inserted != array->child && after_inserted->prev == NULL) {
        /* return false if after_inserted is a corrupted array item */
        return false;
    }

    newitem->next = after_inserted;
    newitem->prev = after_inserted->prev;
    after_inserted->prev = newitem;
    if (after_inserted == array->child)
    {
        array->child = newitem;
    }
    else
    {
        newitem->prev->next = newitem;
    }
    return true;
}

CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
{
    if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
    {
        return false;
    }

    if (replacement == item)
    {
        return true;
    }

    replacement->next = item->next;
    replacement->prev = item->prev;

    if (replacement->next != NULL)
    {
        replacement->next->prev = 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;
    cJSON_Delete(item);

    return true;
}

CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
{
    if (which < 0)
    {
        return false;
    }

    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)
{
    if ((replacement == NULL) || (string == NULL))
    {
        return false;
    }

    /* replace the name in the replacement */
    if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
    {
        cJSON_free(replacement->string);
    }
    replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
    if (replacement->string == NULL)
    {
        return false;
    }

    replacement->type &= ~cJSON_StringIsConst;

    return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
}

CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
{
    return replace_item_in_object(object, string, newitem, false);
}

CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
{
    return replace_item_in_object(object, string, newitem, true);
}

/* Create basic types: */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if(item)
    {
        item->type = cJSON_NULL;
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if(item)
    {
        item->type = cJSON_True;
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if(item)
    {
        item->type = cJSON_False;
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if(item)
    {
        item->type = boolean ? cJSON_True : cJSON_False;
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if(item)
    {
        item->type = cJSON_Number;
        item->valuedouble = num;

        /* use saturation in case of overflow */
        if (num >= INT_MAX)
        {
            item->valueint = INT_MAX;
        }
        else if (num <= (double)INT_MIN)
        {
            item->valueint = INT_MIN;
        }
        else
        {
            item->valueint = (int)num;
        }
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if(item)
    {
        item->type = cJSON_String;
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
        if(!item->valuestring)
        {
            cJSON_Delete(item);
            return NULL;
        }
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if (item != NULL)
    {
        item->type = cJSON_String | cJSON_IsReference;
        item->valuestring = (char*)cast_away_const(string);
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if (item != NULL) {
        item->type = cJSON_Object | cJSON_IsReference;
        item->child = (cJSON*)cast_away_const(child);
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
    cJSON *item = cJSON_New_Item(&global_hooks);
    if (item != NULL) {
        item->type = cJSON_Array | cJSON_IsReference;
        item->child = (cJSON*)cast_away_const(child);
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if(item)
    {
        item->type = cJSON_Raw;
        item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
        if(!item->valuestring)
        {
            cJSON_Delete(item);
            return NULL;
        }
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if(item)
    {
        item->type=cJSON_Array;
    }

    return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
{
    cJSON *item = cJSON_New_Item(&global_hooks);
    if (item)
    {
        item->type = cJSON_Object;
    }

    return item;
}

/* Create Arrays: */
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
{
    size_t i = 0;
    cJSON *n = NULL;
    cJSON *p = NULL;
    cJSON *a = NULL;

    if ((count < 0) || (numbers == NULL))
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
    {
        n = cJSON_CreateNumber(numbers[i]);
        if (!n)
        {
            cJSON_Delete(a);
            return NULL;
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    if (a && a->child) {
        a->child->prev = n;
    }

    return a;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
{
    size_t i = 0;
    cJSON *n = NULL;
    cJSON *p = NULL;
    cJSON *a = NULL;

    if ((count < 0) || (numbers == NULL))
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
    {
        n = cJSON_CreateNumber((double)numbers[i]);
        if(!n)
        {
            cJSON_Delete(a);
            return NULL;
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    if (a && a->child) {
        a->child->prev = n;
    }

    return a;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
{
    size_t i = 0;
    cJSON *n = NULL;
    cJSON *p = NULL;
    cJSON *a = NULL;

    if ((count < 0) || (numbers == NULL))
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for(i = 0; a && (i < (size_t)count); i++)
    {
        n = cJSON_CreateNumber(numbers[i]);
        if(!n)
        {
            cJSON_Delete(a);
            return NULL;
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p, n);
        }
        p = n;
    }

    if (a && a->child) {
        a->child->prev = n;
    }

    return a;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
{
    size_t i = 0;
    cJSON *n = NULL;
    cJSON *p = NULL;
    cJSON *a = NULL;

    if ((count < 0) || (strings == NULL))
    {
        return NULL;
    }

    a = cJSON_CreateArray();

    for (i = 0; a && (i < (size_t)count); i++)
    {
        n = cJSON_CreateString(strings[i]);
        if(!n)
        {
            cJSON_Delete(a);
            return NULL;
        }
        if(!i)
        {
            a->child = n;
        }
        else
        {
            suffix_object(p,n);
        }
        p = n;
    }

    if (a && a->child) {
        a->child->prev = n;
    }

    return a;
}

/* Duplication */
cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse);

CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
{
    return cJSON_Duplicate_rec(item, 0, recurse );
}

cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
{
    cJSON *newitem = NULL;
    cJSON *child = NULL;
    cJSON *next = NULL;
    cJSON *newchild = NULL;

    /* Bail on bad ptr */
    if (!item)
    {
        goto fail;
    }
    /* Create new item */
    newitem = cJSON_New_Item(&global_hooks);
    if (!newitem)
    {
        goto fail;
    }
    /* Copy over all vars */
    newitem->type = item->type & (~cJSON_IsReference);
    newitem->valueint = item->valueint;
    newitem->valuedouble = item->valuedouble;
    if (item->valuestring)
    {
        newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
        if (!newitem->valuestring)
        {
            goto fail;
        }
    }
    if (item->string)
    {
        newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
        if (!newitem->string)
        {
            goto fail;
        }
    }
    /* If non-recursive, then we're done! */
    if (!recurse)
    {
        return newitem;
    }
    /* Walk the ->next chain for the child. */
    child = item->child;
    while (child != NULL)
    {
        if(depth >= CJSON_CIRCULAR_LIMIT) {
            goto fail;
        }
        newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */
        if (!newchild)
        {
            goto fail;
        }
        if (next != NULL)
        {
            /* If newitem->child already set, then crosswire ->prev and ->next and move on */
            next->next = newchild;
            newchild->prev = next;
            next = newchild;
        }
        else
        {
            /* Set newitem->child and move to it */
            newitem->child = newchild;
            next = newchild;
        }
        child = child->next;
    }
    if (newitem && newitem->child)
    {
        newitem->child->prev = newchild;
    }

    return newitem;

fail:
    if (newitem != NULL)
    {
        cJSON_Delete(newitem);
    }

    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)
{
    char *into = json;

    if (json == NULL)
    {
        return;
    }

    while (json[0] != '\0')
    {
        switch (json[0])
        {
            case ' ':
            case '\t':
            case '\r':
            case '\n':
                json++;
                break;

            case '/':
                if (json[1] == '/')
                {
                    skip_oneline_comment(&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++;
        }
    }

    /* and null-terminate. */
    *into = '\0';
}

CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Invalid;
}

CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_False;
}

CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xff) == cJSON_True;
}


CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & (cJSON_True | cJSON_False)) != 0;
}
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_NULL;
}

CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Number;
}

CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_String;
}

CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Array;
}

CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Object;
}

CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
{
    if (item == NULL)
    {
        return false;
    }

    return (item->type & 0xFF) == cJSON_Raw;
}

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)))
    {
        return false;
    }

    /* check if type is valid */
    switch (a->type & 0xFF)
    {
        case cJSON_False:
        case cJSON_True:
        case cJSON_NULL:
        case cJSON_Number:
        case cJSON_String:
        case cJSON_Raw:
        case cJSON_Array:
        case cJSON_Object:
            break;

        default:
            return false;
    }

    /* identical objects are equal */
    if (a == b)
    {
        return true;
    }

    switch (a->type & 0xFF)
    {
        /* in these cases and equal type is enough */
        case cJSON_False:
        case cJSON_True:
        case cJSON_NULL:
            return true;

        case cJSON_Number:
            if (compare_double(a->valuedouble, b->valuedouble))
            {
                return true;
            }
            return false;

        case cJSON_String:
        case cJSON_Raw:
            if ((a->valuestring == NULL) || (b->valuestring == NULL))
            {
                return false;
            }
            if (strcmp(a->valuestring, b->valuestring) == 0)
            {
                return true;
            }

            return false;

        case cJSON_Array:
        {
            cJSON *a_element = a->child;
            cJSON *b_element = b->child;

            for (; (a_element != NULL) && (b_element != NULL);)
            {
                if (!cJSON_Compare(a_element, b_element, case_sensitive))
                {
                    return false;
                }

                a_element = a_element->next;
                b_element = b_element->next;
            }

            /* one of the arrays is longer than the other */
            if (a_element != b_element) {
                return false;
            }

            return true;
        }

        case cJSON_Object:
        {
            cJSON *a_element = NULL;
            cJSON *b_element = NULL;
            cJSON_ArrayForEach(a_element, a)
            {
                /* TODO This has O(n^2) runtime, which is horrible! */
                b_element = get_object_item(b, a_element->string, case_sensitive);
                if (b_element == NULL)
                {
                    return false;
                }

                if (!cJSON_Compare(a_element, b_element, case_sensitive))
                {
                    return false;
                }
            }

            /* doing this twice, once on a and b to prevent true comparison if a subset of b
             * TODO: Do this the proper way, this is just a fix for now */
            cJSON_ArrayForEach(b_element, b)
            {
                a_element = get_object_item(a, b_element->string, case_sensitive);
                if (a_element == NULL)
                {
                    return false;
                }

                if (!cJSON_Compare(b_element, a_element, case_sensitive))
                {
                    return false;
                }
            }

            return true;
        }

        default:
            return false;
    }
}

CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
{
    return global_hooks.allocate(size);
}

CJSON_PUBLIC(void) cJSON_free(void *object)
{
    global_hooks.deallocate(object);
    object = NULL;
}


================================================
FILE: cJSON.h
================================================
/*
  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

#ifndef cJSON__h
#define cJSON__h

#ifdef __cplusplus
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 19

#include <stddef.h>

/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False  (1 << 0)
#define cJSON_True   (1 << 1)
#define cJSON_NULL   (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array  (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw    (1 << 7) /* raw json */

#define cJSON_IsReference 256
#define cJSON_StringIsConst 512

/* The cJSON structure: */
typedef struct cJSON
{
    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *next;
    struct cJSON *prev;
    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
    struct cJSON *child;

    /* The type of the item, as above. */
    int type;

    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
    char *valuestring;
    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
    int valueint;
    /* The item's number, if type==cJSON_Number */
    double valuedouble;

    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
    char *string;
} cJSON;

typedef struct cJSON_Hooks
{
      /* 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;

/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
 * This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif

/* Limits the length of circular references can be before cJSON rejects to parse them.
 * This is to prevent stack overflows. */
#ifndef CJSON_CIRCULAR_LIMIT
#define CJSON_CIRCULAR_LIMIT 10000
#endif

/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);

/* Supply malloc, realloc and free functions to cJSON */
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);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);

/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* 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);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);

/* 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);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);

/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
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/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.
 * 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 *const *strings, int count);

/* Append item to the specified array/object. */
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(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(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);

/* 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);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
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(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(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. */
/* 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.
 * They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);

/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* 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);

/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
    (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
    (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
    cJSON_Invalid\
)

/* 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)

/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);

#ifdef __cplusplus
}
#endif

#endif


================================================
FILE: cJSON_Utils.c
================================================
/*
  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

/* disable warnings about old C89 functions in MSVC */
#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
#define _CRT_SECURE_NO_DEPRECATE
#endif

#ifdef __GNUCC__
#pragma GCC visibility push(default)
#endif
#if defined(_MSC_VER)
#pragma warning (push)
/* disable warning about single line comments in system headers */
#pragma warning (disable : 4001)
#endif

#include <ctype.h>
#include <string.h>
#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)
#endif
#ifdef __GNUCC__
#pragma GCC visibility pop
#endif

#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)
{
    size_t length = 0;
    unsigned char *copy = NULL;

    length = strlen((const char*)string) + sizeof("");
    copy = (unsigned char*) cJSON_malloc(length);
    if (copy == NULL)
    {
        return NULL;
    }
    memcpy(copy, string, length);

    return copy;
}

/* string comparison which doesn't consider NULL pointers equal */
static int compare_strings(const unsigned char *string1, const unsigned char *string2, const cJSON_bool case_sensitive)
{
    if ((string1 == NULL) || (string2 == NULL))
    {
        return 1;
    }

    if (string1 == string2)
    {
        return 0;
    }

    if (case_sensitive)
    {
        return strcmp((const char*)string1, (const char*)string2);
    }

    for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
    {
        if (*string1 == '\0')
        {
            return 0;
        }
    }

    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)
{
    if ((name == NULL) || (pointer == NULL))
    {
        return false;
    }

    for (; (*name != '\0') && (*pointer != '\0') && (*pointer != '/'); (void)name++, pointer++) /* compare until next '/' */
    {
        if (*pointer == '~')
        {
            /* check for escaped '~' (~0) and '/' (~1) */
            if (((pointer[1] != '0') || (*name != '~')) && ((pointer[1] != '1') || (*name != '/')))
            {
                /* invalid escape sequence or wrong character in *name */
                return false;
            }
            else
            {
                pointer++;
            }
        }
        else if ((!case_sensitive && (tolower(*name) != tolower(*pointer))) || (case_sensitive && (*name != *pointer)))
        {
            return false;
        }
    }
    if (((*pointer != 0) && (*pointer != '/')) != (*name != 0))
    {
        /* one string has ended, the other not */
        return false;;
    }

    return true;
}

/* calculate the length of a string if encoded as JSON pointer with ~0 and ~1 escape sequences */
static size_t pointer_encoded_length(const unsigned char *string)
{
    size_t length;
    for (length = 0; *string != '\0'; (void)string++, length++)
    {
        /* character needs to be escaped? */
        if ((*string == '~') || (*string == '/'))
        {
            length++;
        }
    }

    return length;
}

/* copy a string while escaping '~' and '/' with ~0 and ~1 JSON pointer escape codes */
static void encode_string_as_pointer(unsigned char *destination, const unsigned char *source)
{
    for (; source[0] != '\0'; (void)source++, destination++)
    {
        if (source[0] == '/')
        {
            destination[0] = '~';
            destination[1] = '1';
            destination++;
        }
        else if (source[0] == '~')
        {
            destination[0] = '~';
            destination[1] = '0';
            destination++;
        }
        else
        {
            destination[0] = source[0];
        }
    }

    destination[0] = '\0';
}

CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target)
{
    size_t child_index = 0;
    cJSON *current_child = 0;

    if ((object == NULL) || (target == NULL))
    {
        return NULL;
    }

    if (object == target)
    {
        /* found */
        return (char*)cJSONUtils_strdup((const unsigned char*)"");
    }

    /* recursively search all children of the object or array */
    for (current_child = object->child; current_child != NULL; (void)(current_child = current_child->next), child_index++)
    {
        unsigned char *target_pointer = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(current_child, target);
        /* found the target? */
        if (target_pointer != NULL)
        {
            if (cJSON_IsArray(object))
            {
                /* reserve enough memory for a 64 bit integer + '/' and '\0' */
                unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + 20 + sizeof("/"));
                /* check if conversion to unsigned long is valid
                 * This should be eliminated at compile time by dead code elimination
                 * if size_t is an alias of unsigned long, or if it is bigger */
                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> */
                cJSON_free(target_pointer);

                return (char*)full_pointer;
            }

            if (cJSON_IsObject(object))
            {
                unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + pointer_encoded_length((unsigned char*)current_child->string) + 2);
                full_pointer[0] = '/';
                encode_string_as_pointer(full_pointer + 1, (unsigned char*)current_child->string);
                strcat((char*)full_pointer, (char*)target_pointer);
                cJSON_free(target_pointer);

                return (char*)full_pointer;
            }

            /* reached leaf of the tree, found nothing */
            cJSON_free(target_pointer);
            return NULL;
        }
    }

    /* not found */
    return NULL;
}

/* non broken version of cJSON_GetArrayItem */
static cJSON *get_array_item(const cJSON *array, size_t item)
{
    cJSON *child = array ? array->child : NULL;
    while ((child != NULL) && (item > 0))
    {
        item--;
        child = child->next;
    }

    return child;
}

static cJSON_bool decode_array_index_from_pointer(const unsigned char * const pointer, size_t * const index)
{
    size_t parsed_index = 0;
    size_t position = 0;

    if ((pointer[0] == '0') && ((pointer[1] != '\0') && (pointer[1] != '/')))
    {
        /* leading zeroes are not permitted */
        return 0;
    }

    for (position = 0; (pointer[position] >= '0') && (pointer[position] <= '9'); position++)
    {
        parsed_index = (10 * parsed_index) + (size_t)(pointer[position] - '0');

    }

    if ((pointer[position] != '\0') && (pointer[position] != '/'))
    {
        return 0;
    }

    *index = parsed_index;

    return 1;
}

static cJSON *get_item_from_pointer(cJSON * const object, const char * pointer, const cJSON_bool case_sensitive)
{
    cJSON *current_element = object;

    if (pointer == NULL)
    {
        return NULL;
    }

    /* follow path of the pointer */
    while ((pointer[0] == '/') && (current_element != NULL))
    {
        pointer++;
        if (cJSON_IsArray(current_element))
        {
            size_t index = 0;
            if (!decode_array_index_from_pointer((const unsigned char*)pointer, &index))
            {
                return NULL;
            }

            current_element = get_array_item(current_element, index);
        }
        else if (cJSON_IsObject(current_element))
        {
            current_element = current_element->child;
            /* GetObjectItem. */
            while ((current_element != NULL) && !compare_pointers((unsigned char*)current_element->string, (const unsigned char*)pointer, case_sensitive))
            {
                current_element = current_element->next;
            }
        }
        else
        {
            return NULL;
        }

        /* skip to the next path token or end of string */
        while ((pointer[0] != '\0') && (pointer[0] != '/'))
        {
            pointer++;
        }
    }

    return current_element;
}

CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer)
{
    return get_item_from_pointer(object, pointer, false);
}

CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer)
{
    return get_item_from_pointer(object, pointer, true);
}

/* JSON Patch implementation. */
static void decode_pointer_inplace(unsigned char *string)
{
    unsigned char *decoded_string = string;

    if (string == NULL) {
        return;
    }

    for (; *string; (void)decoded_string++, string++)
    {
        if (string[0] == '~')
        {
            if (string[1] == '0')
            {
                decoded_string[0] = '~';
            }
            else if (string[1] == '1')
            {
                decoded_string[1] = '/';
            }
            else
            {
                /* invalid escape sequence */
                return;
            }

            string++;
        }
    }

    decoded_string[0] = '\0';
}

/* non-broken cJSON_DetachItemFromArray */
static cJSON *detach_item_from_array(cJSON *array, size_t which)
{
    cJSON *c = array->child;
    while (c && (which > 0))
    {
        c = c->next;
        which--;
    }
    if (!c)
    {
        /* item doesn't exist */
        return NULL;
    }
    if (c != array->child)
    {
        /* not the first element */
        c->prev->next = c->next;
    }
    if (c->next)
    {
        c->next->prev = c->prev;
    }
    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;

    return c;
}

/* detach an item at the given path */
static cJSON *detach_path(cJSON *object, const unsigned char *path, const cJSON_bool case_sensitive)
{
    unsigned char *parent_pointer = NULL;
    unsigned char *child_pointer = NULL;
    cJSON *parent = NULL;
    cJSON *detached_item = NULL;

    /* copy path and split it in parent and child */
    parent_pointer = cJSONUtils_strdup(path);
    if (parent_pointer == NULL) {
        goto cleanup;
    }

    child_pointer = (unsigned char*)strrchr((char*)parent_pointer, '/'); /* last '/' */
    if (child_pointer == NULL)
    {
        goto cleanup;
    }
    /* split strings */
    child_pointer[0] = '\0';
    child_pointer++;

    parent = get_item_from_pointer(object, (char*)parent_pointer, case_sensitive);
    decode_pointer_inplace(child_pointer);

    if (cJSON_IsArray(parent))
    {
        size_t index = 0;
        if (!decode_array_index_from_pointer(child_pointer, &index))
        {
            goto cleanup;
        }
        detached_item = detach_item_from_array(parent, index);
    }
    else if (cJSON_IsObject(parent))
    {
        detached_item = cJSON_DetachItemFromObject(parent, (char*)child_pointer);
    }
    else
    {
        /* Couldn't find object to remove child from. */
        goto cleanup;
    }

cleanup:
    if (parent_pointer != NULL)
    {
        cJSON_free(parent_pointer);
    }

    return detached_item;
}

/* sort lists using mergesort */
static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
{
    cJSON *first = list;
    cJSON *second = list;
    cJSON *current_item = list;
    cJSON *result = list;
    cJSON *result_tail = NULL;

    if ((list == NULL) || (list->next == NULL))
    {
        /* One entry is sorted already. */
        return result;
    }

    while ((current_item != NULL) && (current_item->next != NULL) && (compare_strings((unsigned char*)current_item->string, (unsigned char*)current_item->next->string, case_sensitive) < 0))
    {
        /* Test for list sorted. */
        current_item = current_item->next;
    }
    if ((current_item == NULL) || (current_item->next == NULL))
    {
        /* Leave sorted lists unmodified. */
        return result;
    }

    /* reset pointer to the beginning */
    current_item = list;
    while (current_item != NULL)
    {
        /* Walk two pointers to find the middle. */
        second = second->next;
        current_item = current_item->next;
        /* advances current_item two steps at a time */
        if (current_item != NULL)
        {
            current_item = current_item->next;
        }
    }
    if ((second != NULL) && (second->prev != NULL))
    {
        /* Split the lists */
        second->prev->next = NULL;
        second->prev = NULL;
    }

    /* Recursively sort the sub-lists. */
    first = sort_list(first, case_sensitive);
    second = sort_list(second, case_sensitive);
    result = NULL;

    /* Merge the sub-lists */
    while ((first != NULL) && (second != NULL))
    {
        cJSON *smaller = NULL;
        if (compare_strings((unsigned char*)first->string, (unsigned char*)second->string, case_sensitive) < 0)
        {
            smaller = first;
        }
        else
        {
            smaller = second;
        }

        if (result == NULL)
        {
            /* start merged list with the smaller element */
            result_tail = smaller;
            result = smaller;
        }
        else
        {
            /* add smaller element to the list */
            result_tail->next = smaller;
            smaller->prev = result_tail;
            result_tail = smaller;
        }

        if (first == smaller)
        {
            first = first->next;
        }
        else
        {
            second = second->next;
        }
    }

    if (first != NULL)
    {
        /* Append rest of first list. */
        if (result == NULL)
        {
            return first;
        }
        result_tail->next = first;
        first->prev = result_tail;
    }
    if (second != NULL)
    {
        /* Append rest of second list */
        if (result == NULL)
        {
            return second;
        }
        result_tail->next = second;
        second->prev = result_tail;
    }

    return result;
}

static void sort_object(cJSON * const object, const cJSON_bool case_sensitive)
{
    if (object == NULL)
    {
        return;
    }
    object->child = sort_list(object->child, case_sensitive);
}

static 
Download .txt
gitextract_0me4kfa0/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── CONTRIBUTING.md
│   └── workflows/
│       ├── CI.yml
│       └── ci-fuzz.yml
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── CMakeLists.txt
├── CONTRIBUTORS.md
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── appveyor.yml
├── cJSON.c
├── cJSON.h
├── cJSON_Utils.c
├── cJSON_Utils.h
├── fuzzing/
│   ├── .gitignore
│   ├── CMakeLists.txt
│   ├── afl-prepare-linux.sh
│   ├── afl.c
│   ├── afl.sh
│   ├── cjson_read_fuzzer.c
│   ├── fuzz_main.c
│   ├── inputs/
│   │   ├── test1
│   │   ├── test10
│   │   ├── test11
│   │   ├── test2
│   │   ├── test3
│   │   ├── test3.bu
│   │   ├── test3.uf
│   │   ├── test3.uu
│   │   ├── test4
│   │   ├── test5
│   │   ├── test6
│   │   ├── test7
│   │   ├── test8
│   │   └── test9
│   ├── json.dict
│   └── ossfuzz.sh
├── library_config/
│   ├── cJSONConfig.cmake.in
│   ├── cJSONConfigVersion.cmake.in
│   ├── libcjson.pc.in
│   ├── libcjson_utils.pc.in
│   └── uninstall.cmake
├── test.c
├── tests/
│   ├── CMakeLists.txt
│   ├── cjson_add.c
│   ├── common.h
│   ├── compare_tests.c
│   ├── inputs/
│   │   ├── test1
│   │   ├── test1.expected
│   │   ├── test10
│   │   ├── test10.expected
│   │   ├── test11
│   │   ├── test11.expected
│   │   ├── test2
│   │   ├── test2.expected
│   │   ├── test3
│   │   ├── test3.expected
│   │   ├── test4
│   │   ├── test4.expected
│   │   ├── test5
│   │   ├── test5.expected
│   │   ├── test6
│   │   ├── test7
│   │   ├── test7.expected
│   │   ├── test8
│   │   ├── test8.expected
│   │   ├── test9
│   │   └── test9.expected
│   ├── json-patch-tests/
│   │   ├── .editorconfig
│   │   ├── .gitignore
│   │   ├── .npmignore
│   │   ├── README.md
│   │   ├── cjson-utils-tests.json
│   │   ├── package.json
│   │   ├── spec_tests.json
│   │   └── tests.json
│   ├── json_patch_tests.c
│   ├── minify_tests.c
│   ├── misc_tests.c
│   ├── misc_utils_tests.c
│   ├── old_utils_tests.c
│   ├── parse_array.c
│   ├── parse_examples.c
│   ├── parse_hex4.c
│   ├── parse_number.c
│   ├── parse_object.c
│   ├── parse_string.c
│   ├── parse_value.c
│   ├── parse_with_opts.c
│   ├── print_array.c
│   ├── print_number.c
│   ├── print_object.c
│   ├── print_string.c
│   ├── print_value.c
│   ├── readme_examples.c
│   ├── unity/
│   │   ├── .gitattributes
│   │   ├── .gitignore
│   │   ├── .travis.yml
│   │   ├── README.md
│   │   ├── auto/
│   │   │   ├── colour_prompt.rb
│   │   │   ├── colour_reporter.rb
│   │   │   ├── generate_config.yml
│   │   │   ├── generate_module.rb
│   │   │   ├── generate_test_runner.rb
│   │   │   ├── parse_output.rb
│   │   │   ├── stylize_as_junit.rb
│   │   │   ├── test_file_filter.rb
│   │   │   ├── type_sanitizer.rb
│   │   │   ├── unity_test_summary.py
│   │   │   ├── unity_test_summary.rb
│   │   │   └── unity_to_junit.py
│   │   ├── docs/
│   │   │   ├── ThrowTheSwitchCodingStandard.md
│   │   │   ├── UnityAssertionsReference.md
│   │   │   ├── UnityConfigurationGuide.md
│   │   │   ├── UnityGettingStartedGuide.md
│   │   │   ├── UnityHelperScriptsGuide.md
│   │   │   └── license.txt
│   │   ├── examples/
│   │   │   ├── example_1/
│   │   │   │   ├── makefile
│   │   │   │   ├── readme.txt
│   │   │   │   └── src/
│   │   │   │       ├── ProductionCode.c
│   │   │   │       ├── ProductionCode.h
│   │   │   │       ├── ProductionCode2.c
│   │   │   │       └── ProductionCode2.h
│   │   │   ├── example_2/
│   │   │   │   ├── makefile
│   │   │   │   ├── readme.txt
│   │   │   │   └── src/
│   │   │   │       ├── ProductionCode.c
│   │   │   │       ├── ProductionCode.h
│   │   │   │       ├── ProductionCode2.c
│   │   │   │       └── ProductionCode2.h
│   │   │   ├── example_3/
│   │   │   │   ├── helper/
│   │   │   │   │   ├── UnityHelper.c
│   │   │   │   │   └── UnityHelper.h
│   │   │   │   ├── rakefile.rb
│   │   │   │   ├── rakefile_helper.rb
│   │   │   │   ├── readme.txt
│   │   │   │   ├── src/
│   │   │   │   │   ├── ProductionCode.c
│   │   │   │   │   ├── ProductionCode.h
│   │   │   │   │   ├── ProductionCode2.c
│   │   │   │   │   └── ProductionCode2.h
│   │   │   │   └── target_gcc_32.yml
│   │   │   └── unity_config.h
│   │   ├── extras/
│   │   │   ├── eclipse/
│   │   │   │   └── error_parsers.txt
│   │   │   └── fixture/
│   │   │       ├── rakefile.rb
│   │   │       ├── rakefile_helper.rb
│   │   │       ├── readme.txt
│   │   │       └── src/
│   │   │           ├── unity_fixture.c
│   │   │           ├── unity_fixture.h
│   │   │           ├── unity_fixture_internals.h
│   │   │           └── unity_fixture_malloc_overrides.h
│   │   ├── release/
│   │   │   ├── build.info
│   │   │   └── version.info
│   │   └── src/
│   │       ├── unity.c
│   │       ├── unity.h
│   │       └── unity_internals.h
│   └── unity_setup.c
└── valgrind.supp
Download .txt
SYMBOL INDEX (615 symbols across 52 files)

FILE: cJSON.c
  type error (line 88) | typedef struct {
  function cJSON_GetErrorPtr (line 94) | CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
  function cJSON_GetStringValue (line 99) | CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
  function cJSON_GetNumberValue (line 109) | CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
  function cJSON_Version (line 124) | CJSON_PUBLIC(const char*) cJSON_Version(void)
  function case_insensitive_strcmp (line 133) | static int case_insensitive_strcmp(const unsigned char *string1, const u...
  type internal_hooks (line 156) | typedef struct internal_hooks
  function internal_free (line 169) | static void CJSON_CDECL internal_free(void *pointer)
  function cJSON_InitHooks (line 209) | CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
  function cJSON (line 241) | static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
  function cJSON_Delete (line 253) | CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
  function get_decimal_point (line 279) | static unsigned char get_decimal_point(void)
  type parse_buffer (line 289) | typedef struct
  function cJSON_bool (line 307) | static cJSON_bool parse_number(cJSON * const item, parse_buffer * const ...
  function cJSON_SetNumberHelper (line 411) | CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
  function cJSON_SetValuestring (line 435) | CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valu...
  type printbuffer (line 478) | typedef struct
  function update_offset (line 576) | static void update_offset(printbuffer * const buffer)
  function cJSON_bool (line 589) | static cJSON_bool compare_double(double a, double b)
  function cJSON_bool (line 596) | static cJSON_bool print_number(const cJSON * const item, printbuffer * c...
  function parse_hex4 (line 666) | static unsigned parse_hex4(const unsigned char * const input)
  function utf16_literal_to_utf8 (line 703) | static unsigned char utf16_literal_to_utf8(const unsigned char * const i...
  function cJSON_bool (line 824) | static cJSON_bool parse_string(cJSON * const item, parse_buffer * const ...
  function cJSON_bool (line 954) | static cJSON_bool print_string_ptr(const unsigned char * const input, pr...
  function cJSON_bool (line 1076) | static cJSON_bool print_string(const cJSON * const item, printbuffer * c...
  function parse_buffer (line 1090) | static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
  function parse_buffer (line 1116) | static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
  function cJSON_ParseWithOpts (line 1131) | CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char ...
  function cJSON_ParseWithLengthOpts (line 1147) | CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_...
  function cJSON_Parse (line 1227) | CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
  function cJSON_ParseWithLength (line 1232) | CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t bu...
  function cJSON_Print (line 1307) | CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
  function cJSON_PrintUnformatted (line 1312) | CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
  function cJSON_PrintBuffered (line 1317) | CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffe...
  function cJSON_PrintPreallocated (line 1348) | CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buff...
  function cJSON_bool (line 1368) | static cJSON_bool parse_value(cJSON * const item, parse_buffer * const i...
  function cJSON_bool (line 1423) | static cJSON_bool print_value(const cJSON * const item, printbuffer * co...
  function cJSON_bool (line 1497) | static cJSON_bool parse_array(cJSON * const item, parse_buffer * const i...
  function cJSON_bool (line 1595) | static cJSON_bool print_array(const cJSON * const item, printbuffer * co...
  function cJSON_bool (line 1662) | static cJSON_bool parse_object(cJSON * const item, parse_buffer * const ...
  function cJSON_bool (line 1780) | static cJSON_bool print_object(const cJSON * const item, printbuffer * c...
  function cJSON_GetArraySize (line 1899) | CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
  function cJSON (line 1922) | static cJSON* get_array_item(const cJSON *array, size_t index)
  function cJSON_GetArrayItem (line 1941) | CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
  function cJSON (line 1951) | static cJSON *get_object_item(const cJSON * const object, const char * c...
  function cJSON_GetObjectItem (line 1983) | CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, co...
  function cJSON_GetObjectItemCaseSensitive (line 1988) | CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * con...
  function cJSON_HasObjectItem (line 1993) | CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const ...
  function suffix_object (line 1999) | static void suffix_object(cJSON *prev, cJSON *item)
  function cJSON (line 2006) | static cJSON *create_reference(const cJSON *item, const internal_hooks *...
  function cJSON_bool (line 2027) | static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
  function cJSON_AddItemToArray (line 2061) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
  function cJSON_bool (line 2082) | static cJSON_bool add_item_to_object(cJSON * const object, const char * ...
  function cJSON_AddItemToObject (line 2119) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char...
  function cJSON_AddItemToObjectCS (line 2125) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const ch...
  function cJSON_AddItemReferenceToArray (line 2130) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJS...
  function cJSON_AddItemReferenceToObject (line 2140) | CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, c...
  function cJSON_AddNullToObject (line 2150) | CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const c...
  function cJSON_AddTrueToObject (line 2162) | CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const c...
  function cJSON_AddFalseToObject (line 2174) | CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const ...
  function cJSON_AddBoolToObject (line 2186) | CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const c...
  function cJSON_AddNumberToObject (line 2198) | CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const...
  function cJSON_AddStringToObject (line 2210) | CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const...
  function cJSON_AddRawToObject (line 2222) | CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const ch...
  function cJSON_AddObjectToObject (line 2234) | CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const...
  function cJSON_AddArrayToObject (line 2246) | CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const ...
  function cJSON_DetachItemViaPointer (line 2258) | CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * ...
  function cJSON_DetachItemFromArray (line 2294) | CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
  function cJSON_DeleteItemFromArray (line 2304) | CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
  function cJSON_DetachItemFromObject (line 2309) | CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const ch...
  function cJSON_DetachItemFromObjectCaseSensitive (line 2316) | CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *obj...
  function cJSON_DeleteItemFromObject (line 2323) | CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char ...
  function cJSON_DeleteItemFromObjectCaseSensitive (line 2328) | CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object...
  function cJSON_InsertItemInArray (line 2334) | CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which...
  function cJSON_ReplaceItemViaPointer (line 2368) | CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const paren...
  function cJSON_ReplaceItemInArray (line 2417) | CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int whic...
  function cJSON_bool (line 2427) | static cJSON_bool replace_item_in_object(cJSON *object, const char *stri...
  function cJSON_ReplaceItemInObject (line 2450) | CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const ...
  function cJSON_ReplaceItemInObjectCaseSensitive (line 2455) | CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *o...
  function cJSON_CreateNull (line 2461) | CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
  function cJSON_CreateTrue (line 2472) | CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
  function cJSON_CreateFalse (line 2483) | CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
  function cJSON_CreateBool (line 2494) | CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
  function cJSON_CreateNumber (line 2505) | CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
  function cJSON_CreateString (line 2531) | CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
  function cJSON_CreateStringReference (line 2548) | CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
  function cJSON_CreateObjectReference (line 2560) | CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
  function cJSON_CreateArrayReference (line 2571) | CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
  function cJSON_CreateRaw (line 2581) | CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
  function cJSON_CreateArray (line 2598) | CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
  function cJSON_CreateObject (line 2609) | CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
  function cJSON_CreateIntArray (line 2621) | CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
  function cJSON_CreateFloatArray (line 2661) | CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int c...
  function cJSON_CreateDoubleArray (line 2701) | CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int...
  function cJSON_CreateStringArray (line 2741) | CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings...
  function cJSON_Duplicate (line 2784) | CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recu...
  function cJSON (line 2789) | cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool ...
  function skip_oneline_comment (line 2875) | static void skip_oneline_comment(char **input)
  function skip_multiline_comment (line 2888) | static void skip_multiline_comment(char **input)
  function minify_string (line 2902) | static void minify_string(char **input, char **output) {
  function cJSON_Minify (line 2924) | CJSON_PUBLIC(void) cJSON_Minify(char *json)
  function cJSON_IsInvalid (line 2972) | CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
  function cJSON_IsFalse (line 2982) | CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
  function cJSON_IsTrue (line 2992) | CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
  function cJSON_IsBool (line 3003) | CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
  function cJSON_IsNull (line 3012) | CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
  function cJSON_IsNumber (line 3022) | CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
  function cJSON_IsString (line 3032) | CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
  function cJSON_IsArray (line 3042) | CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
  function cJSON_IsObject (line 3052) | CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
  function cJSON_IsRaw (line 3062) | CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
  function cJSON_Compare (line 3072) | CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSO...
  function cJSON_malloc (line 3197) | CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
  function cJSON_free (line 3202) | CJSON_PUBLIC(void) cJSON_free(void *object)

FILE: cJSON.h
  type cJSON (line 103) | typedef struct cJSON
  type cJSON_Hooks (line 125) | typedef struct cJSON_Hooks
  type cJSON_bool (line 132) | typedef int cJSON_bool;

FILE: cJSON_Utils.c
  function compare_strings (line 83) | static int compare_strings(const unsigned char *string1, const unsigned ...
  function cJSON_bool (line 112) | static cJSON_bool compare_double(double a, double b)
  function cJSON_bool (line 120) | static cJSON_bool compare_pointers(const unsigned char *name, const unsi...
  function pointer_encoded_length (line 157) | static size_t pointer_encoded_length(const unsigned char *string)
  function encode_string_as_pointer (line 173) | static void encode_string_as_pointer(unsigned char *destination, const u...
  function cJSONUtils_FindPointerFromObjectTo (line 198) | CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * co...
  function cJSON (line 262) | static cJSON *get_array_item(const cJSON *array, size_t item)
  function cJSON_bool (line 274) | static cJSON_bool decode_array_index_from_pointer(const unsigned char * ...
  function cJSON (line 301) | static cJSON *get_item_from_pointer(cJSON * const object, const char * p...
  function cJSONUtils_GetPointer (line 348) | CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const ...
  function cJSONUtils_GetPointerCaseSensitive (line 353) | CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const o...
  function decode_pointer_inplace (line 359) | static void decode_pointer_inplace(unsigned char *string)
  function cJSON (line 393) | static cJSON *detach_item_from_array(cJSON *array, size_t which)
  function cJSON (line 430) | static cJSON *detach_path(cJSON *object, const unsigned char *path, cons...
  function cJSON (line 484) | static cJSON *sort_list(cJSON *list, const cJSON_bool case_sensitive)
  function sort_object (line 595) | static void sort_object(cJSON * const object, const cJSON_bool case_sens...
  function cJSON_bool (line 604) | static cJSON_bool compare_json(cJSON *a, cJSON *b, const cJSON_bool case...
  function cJSON_bool (line 693) | static cJSON_bool insert_item_in_array(cJSON *array, size_t which, cJSON...
  function cJSON (line 730) | static cJSON *get_object_item(const cJSON * const object, const char* na...
  type patch_operation (line 740) | enum patch_operation { INVALID, ADD, REMOVE, REPLACE, MOVE, COPY, TEST }
  function decode_patch_operation (line 742) | static enum patch_operation decode_patch_operation(const cJSON * const p...
  function overwrite_item (line 784) | static void overwrite_item(cJSON * const root, const cJSON replacement)
  function apply_patch (line 807) | static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bo...
  function cJSONUtils_ApplyPatches (line 1038) | CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJ...
  function cJSONUtils_ApplyPatchesCaseSensitive (line 1067) | CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const obj...
  function compose_patch (line 1096) | static void compose_patch(cJSON * const patches, const unsigned char * c...
  function cJSONUtils_AddPatchToArray (line 1136) | CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const...
  function create_patches (line 1141) | static void create_patches(cJSON * const patches, const unsigned char * ...
  function cJSONUtils_GeneratePatches (line 1281) | CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJS...
  function cJSONUtils_GeneratePatchesCaseSensitive (line 1296) | CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * co...
  function cJSONUtils_SortObject (line 1311) | CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object)
  function cJSONUtils_SortObjectCaseSensitive (line 1316) | CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object)
  function cJSON (line 1321) | static cJSON *merge_patch(cJSON *target, const cJSON * const patch, cons...
  function cJSONUtils_MergePatch (line 1381) | CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON *...
  function cJSONUtils_MergePatchCaseSensitive (line 1386) | CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, ...
  function cJSON (line 1391) | static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to,...
  function cJSONUtils_GenerateMergePatch (line 1473) | CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, ...
  function cJSONUtils_GenerateMergePatchCaseSensitive (line 1478) | CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON *...

FILE: fuzzing/afl.c
  function main (line 85) | int main(int argc, char** argv)

FILE: fuzzing/cjson_read_fuzzer.c
  function LLVMFuzzerTestOneInput (line 13) | int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)

FILE: fuzzing/fuzz_main.c
  function main (line 9) | int main(int argc, char **argv)

FILE: test.c
  type record (line 29) | struct record
  function print_preallocated (line 43) | static int print_preallocated(cJSON *root)
  function create_objects (line 109) | static void create_objects(void)
  function main (line 259) | main(void)

FILE: tests/cjson_add.c
  function normal_free (line 38) | static void CJSON_CDECL normal_free(void *pointer)
  function cjson_add_null_should_add_null (line 48) | static void cjson_add_null_should_add_null(void)
  function cjson_add_null_should_fail_with_null_pointers (line 61) | static void cjson_add_null_should_fail_with_null_pointers(void)
  function cjson_add_null_should_fail_on_allocation_failure (line 71) | static void cjson_add_null_should_fail_on_allocation_failure(void)
  function cjson_add_true_should_add_true (line 84) | static void cjson_add_true_should_add_true(void)
  function cjson_add_true_should_fail_with_null_pointers (line 97) | static void cjson_add_true_should_fail_with_null_pointers(void)
  function cjson_add_true_should_fail_on_allocation_failure (line 107) | static void cjson_add_true_should_fail_on_allocation_failure(void)
  function cjson_create_int_array_should_fail_on_allocation_failure (line 120) | static void cjson_create_int_array_should_fail_on_allocation_failure(void)
  function cjson_create_float_array_should_fail_on_allocation_failure (line 131) | static void cjson_create_float_array_should_fail_on_allocation_failure(v...
  function cjson_create_double_array_should_fail_on_allocation_failure (line 142) | static void cjson_create_double_array_should_fail_on_allocation_failure(...
  function cjson_create_string_array_should_fail_on_allocation_failure (line 153) | static void cjson_create_string_array_should_fail_on_allocation_failure(...
  function cjson_add_false_should_add_false (line 164) | static void cjson_add_false_should_add_false(void)
  function cjson_add_false_should_fail_with_null_pointers (line 177) | static void cjson_add_false_should_fail_with_null_pointers(void)
  function cjson_add_false_should_fail_on_allocation_failure (line 187) | static void cjson_add_false_should_fail_on_allocation_failure(void)
  function cjson_add_bool_should_add_bool (line 200) | static void cjson_add_bool_should_add_bool(void)
  function cjson_add_bool_should_fail_with_null_pointers (line 219) | static void cjson_add_bool_should_fail_with_null_pointers(void)
  function cjson_add_bool_should_fail_on_allocation_failure (line 229) | static void cjson_add_bool_should_fail_on_allocation_failure(void)
  function cjson_add_number_should_add_number (line 242) | static void cjson_add_number_should_add_number(void)
  function cjson_add_number_should_fail_with_null_pointers (line 258) | static void cjson_add_number_should_fail_with_null_pointers(void)
  function cjson_add_number_should_fail_on_allocation_failure (line 268) | static void cjson_add_number_should_fail_on_allocation_failure(void)
  function cjson_add_string_should_add_string (line 281) | static void cjson_add_string_should_add_string(void)
  function cjson_add_string_should_fail_with_null_pointers (line 295) | static void cjson_add_string_should_fail_with_null_pointers(void)
  function cjson_add_string_should_fail_on_allocation_failure (line 305) | static void cjson_add_string_should_fail_on_allocation_failure(void)
  function cjson_add_raw_should_add_raw (line 318) | static void cjson_add_raw_should_add_raw(void)
  function cjson_add_raw_should_fail_with_null_pointers (line 332) | static void cjson_add_raw_should_fail_with_null_pointers(void)
  function cjson_add_raw_should_fail_on_allocation_failure (line 342) | static void cjson_add_raw_should_fail_on_allocation_failure(void)
  function cJSON_add_object_should_add_object (line 355) | static void cJSON_add_object_should_add_object(void)
  function cjson_add_object_should_fail_with_null_pointers (line 367) | static void cjson_add_object_should_fail_with_null_pointers(void)
  function cjson_add_object_should_fail_on_allocation_failure (line 377) | static void cjson_add_object_should_fail_on_allocation_failure(void)
  function cJSON_add_array_should_add_array (line 390) | static void cJSON_add_array_should_add_array(void)
  function cjson_add_array_should_fail_with_null_pointers (line 402) | static void cjson_add_array_should_fail_with_null_pointers(void)
  function cjson_add_array_should_fail_on_allocation_failure (line 412) | static void cjson_add_array_should_fail_on_allocation_failure(void)
  function main (line 425) | main(void)

FILE: tests/common.h
  function reset (line 29) | void reset(cJSON *item) {

FILE: tests/compare_tests.c
  function cJSON_bool (line 27) | static cJSON_bool compare_from_string(const char * const a, const char *...
  function cjson_compare_should_compare_null_pointer_as_not_equal (line 46) | static void cjson_compare_should_compare_null_pointer_as_not_equal(void)
  function cjson_compare_should_compare_invalid_as_not_equal (line 52) | static void cjson_compare_should_compare_invalid_as_not_equal(void)
  function cjson_compare_should_compare_numbers (line 61) | static void cjson_compare_should_compare_numbers(void)
  function cjson_compare_should_compare_booleans (line 75) | static void cjson_compare_should_compare_booleans(void)
  function cjson_compare_should_compare_null (line 92) | static void cjson_compare_should_compare_null(void)
  function cjson_compare_should_not_accept_invalid_types (line 101) | static void cjson_compare_should_not_accept_invalid_types(void)
  function cjson_compare_should_compare_strings (line 112) | static void cjson_compare_should_compare_strings(void)
  function cjson_compare_should_compare_raw (line 121) | static void cjson_compare_should_compare_raw(void)
  function cjson_compare_should_compare_arrays (line 141) | static void cjson_compare_should_compare_arrays(void)
  function cjson_compare_should_compare_objects (line 160) | static void cjson_compare_should_compare_objects(void)
  function main (line 192) | main(void)

FILE: tests/json_patch_tests.c
  function cJSON (line 32) | static cJSON *parse_test_file(const char * const filename)
  function cJSON_bool (line 49) | static cJSON_bool test_apply_patch(const cJSON * const test)
  function cJSON_bool (line 122) | static cJSON_bool test_generate_test(cJSON *test)
  function cjson_utils_should_pass_json_patch_test_tests (line 183) | static void cjson_utils_should_pass_json_patch_test_tests(void)
  function cjson_utils_should_pass_json_patch_test_spec_tests (line 200) | static void cjson_utils_should_pass_json_patch_test_spec_tests(void)
  function cjson_utils_should_pass_json_patch_test_cjson_utils_tests (line 217) | static void cjson_utils_should_pass_json_patch_test_cjson_utils_tests(void)
  function main (line 234) | int main(void)

FILE: tests/minify_tests.c
  function cjson_minify_should_not_overflow_buffer (line 32) | static void cjson_minify_should_not_overflow_buffer(void)
  function cjson_minify_should_remove_single_line_comments (line 44) | static void cjson_minify_should_remove_single_line_comments(void)
  function cjson_minify_should_remove_spaces (line 58) | static void cjson_minify_should_remove_spaces(void)
  function cjson_minify_should_remove_multiline_comments (line 72) | static void cjson_minify_should_remove_multiline_comments(void)
  function cjson_minify_should_not_modify_strings (line 86) | static void cjson_minify_should_not_modify_strings(void)
  function cjson_minify_should_minify_json (line 100) | static void cjson_minify_should_minify_json(void) {
  function cjson_minify_should_not_loop_infinitely (line 155) | static void cjson_minify_should_not_loop_infinitely(void) {
  function main (line 161) | main(void)

FILE: tests/misc_tests.c
  function cjson_array_foreach_should_loop_over_arrays (line 32) | static void cjson_array_foreach_should_loop_over_arrays(void)
  function cjson_array_foreach_should_not_dereference_null_pointer (line 60) | static void cjson_array_foreach_should_not_dereference_null_pointer(void)
  function cjson_get_object_item_should_get_object_items (line 67) | static void cjson_get_object_item_should_get_object_items(void)
  function cjson_get_object_item_case_sensitive_should_get_object_items (line 98) | static void cjson_get_object_item_case_sensitive_should_get_object_items...
  function cjson_get_object_item_should_not_crash_with_array (line 129) | static void cjson_get_object_item_should_not_crash_with_array(void)
  function cjson_get_object_item_case_sensitive_should_not_crash_with_array (line 141) | static void cjson_get_object_item_case_sensitive_should_not_crash_with_a...
  function typecheck_functions_should_check_type (line 153) | static void typecheck_functions_should_check_type(void)
  function cjson_should_not_parse_to_deeply_nested_jsons (line 209) | static void cjson_should_not_parse_to_deeply_nested_jsons(void)
  function cjson_should_not_follow_too_deep_circular_references (line 223) | static void cjson_should_not_follow_too_deep_circular_references(void)
  function cjson_set_number_value_should_set_numbers (line 240) | static void cjson_set_number_value_should_set_numbers(void)
  function cjson_detach_item_via_pointer_should_detach_items (line 261) | static void cjson_detach_item_via_pointer_should_detach_items(void)
  function cjson_detach_item_via_pointer_should_return_null_if_item_prev_is_null (line 301) | static void cjson_detach_item_via_pointer_should_return_null_if_item_pre...
  function cjson_replace_item_via_pointer_should_replace_items (line 316) | static void cjson_replace_item_via_pointer_should_replace_items(void)
  function cjson_replace_item_in_object_should_preserve_name (line 362) | static void cjson_replace_item_in_object_should_preserve_name(void)
  function cjson_functions_should_not_crash_with_null_pointers (line 384) | static void cjson_functions_should_not_crash_with_null_pointers(void)
  function cjson_set_valuestring_should_return_null_if_strings_overlap (line 492) | static void cjson_set_valuestring_should_return_null_if_strings_overlap(...
  function ensure_should_fail_on_failed_realloc (line 517) | static void ensure_should_fail_on_failed_realloc(void)
  function skip_utf8_bom_should_skip_bom (line 526) | static void skip_utf8_bom_should_skip_bom(void)
  function skip_utf8_bom_should_not_skip_bom_if_not_at_beginning (line 538) | static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
  function cjson_get_string_value_should_get_a_string (line 550) | static void cjson_get_string_value_should_get_a_string(void)
  function cjson_get_number_value_should_get_a_number (line 563) | static void cjson_get_number_value_should_get_a_number(void)
  function cjson_create_string_reference_should_create_a_string_reference (line 576) | static void cjson_create_string_reference_should_create_a_string_referen...
  function cjson_create_object_reference_should_create_an_object_reference (line 587) | static void cjson_create_object_reference_should_create_an_object_refere...
  function cjson_create_array_reference_should_create_an_array_reference (line 606) | static void cjson_create_array_reference_should_create_an_array_referenc...
  function cjson_add_item_to_object_or_array_should_not_add_itself (line 624) | static void cjson_add_item_to_object_or_array_should_not_add_itself(void)
  function cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased (line 640) | static void cjson_add_item_to_object_should_not_use_after_free_when_stri...
  function cjson_delete_item_from_array_should_not_broken_list_structure (line 659) | static void cjson_delete_item_from_array_should_not_broken_list_structur...
  function cjson_set_valuestring_to_object_should_not_leak_memory (line 693) | static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
  function cjson_set_bool_value_must_not_break_objects (line 728) | static void cjson_set_bool_value_must_not_break_objects(void)
  function cjson_parse_big_numbers_should_not_report_error (line 786) | static void cjson_parse_big_numbers_should_not_report_error(void)
  function main (line 802) | main(void)

FILE: tests/misc_utils_tests.c
  function cjson_utils_functions_shouldnt_crash_with_null_pointers (line 32) | static void cjson_utils_functions_shouldnt_crash_with_null_pointers(void)
  function main (line 73) | int main(void)

FILE: tests/old_utils_tests.c
  function json_pointer_tests (line 52) | static void json_pointer_tests(void)
  function misc_tests (line 88) | static void misc_tests(void)
  function sort_tests (line 138) | static void sort_tests(void)
  function merge_tests (line 168) | static void merge_tests(void)
  function generate_merge_tests (line 192) | static void generate_merge_tests(void)
  function main (line 214) | int main(void)

FILE: tests/parse_array.c
  function assert_is_array (line 33) | static void assert_is_array(cJSON *array_item)
  function assert_not_array (line 45) | static void assert_not_array(const char *json)
  function assert_parse_array (line 56) | static void assert_parse_array(const char *json)
  function parse_array_should_parse_empty_arrays (line 67) | static void parse_array_should_parse_empty_arrays(void)
  function parse_array_should_parse_arrays_with_one_element (line 77) | static void parse_array_should_parse_arrays_with_one_element(void)
  function parse_array_should_parse_arrays_with_multiple_elements (line 104) | static void parse_array_should_parse_arrays_with_multiple_elements(void)
  function parse_array_should_not_parse_non_arrays (line 145) | static void parse_array_should_not_parse_non_arrays(void)
  function main (line 156) | main(void)

FILE: tests/parse_examples.c
  function cJSON (line 31) | static cJSON *parse_file(const char *filename)
  function do_test (line 46) | static void do_test(const char *test_name)
  function file_test1_should_be_parsed_and_printed (line 109) | static void file_test1_should_be_parsed_and_printed(void)
  function file_test2_should_be_parsed_and_printed (line 114) | static void file_test2_should_be_parsed_and_printed(void)
  function file_test3_should_be_parsed_and_printed (line 119) | static void file_test3_should_be_parsed_and_printed(void)
  function file_test4_should_be_parsed_and_printed (line 124) | static void file_test4_should_be_parsed_and_printed(void)
  function file_test5_should_be_parsed_and_printed (line 129) | static void file_test5_should_be_parsed_and_printed(void)
  function file_test6_should_not_be_parsed (line 134) | static void file_test6_should_not_be_parsed(void)
  function file_test7_should_be_parsed_and_printed (line 157) | static void file_test7_should_be_parsed_and_printed(void)
  function file_test8_should_be_parsed_and_printed (line 162) | static void file_test8_should_be_parsed_and_printed(void)
  function file_test9_should_be_parsed_and_printed (line 167) | static void file_test9_should_be_parsed_and_printed(void)
  function file_test10_should_be_parsed_and_printed (line 172) | static void file_test10_should_be_parsed_and_printed(void)
  function file_test11_should_be_parsed_and_printed (line 177) | static void file_test11_should_be_parsed_and_printed(void)
  function test12_should_not_be_parsed (line 182) | static void test12_should_not_be_parsed(void)
  function test13_should_be_parsed_without_null_termination (line 198) | static void test13_should_be_parsed_without_null_termination(void)
  function test14_should_not_be_parsed (line 227) | static void test14_should_not_be_parsed(void)
  function test15_should_not_heap_buffer_overflow (line 254) | static void test15_should_not_heap_buffer_overflow(void)
  function main (line 280) | main(void)

FILE: tests/parse_hex4.c
  function parse_hex4_should_parse_all_combinations (line 31) | static void parse_hex4_should_parse_all_combinations(void)
  function parse_hex4_should_parse_mixed_case (line 47) | static void parse_hex4_should_parse_mixed_case(void)
  function main (line 67) | main(void)

FILE: tests/parse_number.c
  function assert_is_number (line 33) | static void assert_is_number(cJSON *number_item)
  function assert_parse_number (line 46) | static void assert_parse_number(const char *string, int integer, double ...
  function assert_parse_big_number (line 59) | static void assert_parse_big_number(const char *string)
  function parse_number_should_parse_zero (line 70) | static void parse_number_should_parse_zero(void)
  function parse_number_should_parse_negative_integers (line 77) | static void parse_number_should_parse_negative_integers(void)
  function parse_number_should_parse_positive_integers (line 84) | static void parse_number_should_parse_positive_integers(void)
  function parse_number_should_parse_positive_reals (line 91) | static void parse_number_should_parse_positive_reals(void)
  function parse_number_should_parse_negative_reals (line 101) | static void parse_number_should_parse_negative_reals(void)
  function parse_number_should_parse_big_numbers (line 111) | static void parse_number_should_parse_big_numbers(void)
  function main (line 118) | main(void)

FILE: tests/parse_object.c
  function assert_is_object (line 33) | static void assert_is_object(cJSON *object_item)
  function assert_is_child (line 45) | static void assert_is_child(cJSON *child_item, const char *name, int type)
  function assert_not_object (line 53) | static void assert_not_object(const char *json)
  function assert_parse_object (line 65) | static void assert_parse_object(const char *json)
  function parse_object_should_parse_empty_objects (line 76) | static void parse_object_should_parse_empty_objects(void)
  function parse_object_should_parse_objects_with_one_element (line 87) | static void parse_object_should_parse_objects_with_one_element(void)
  function parse_object_should_parse_objects_with_multiple_elements (line 107) | static void parse_object_should_parse_objects_with_multiple_elements(void)
  function parse_object_should_not_parse_non_objects (line 154) | static void parse_object_should_not_parse_non_objects(void)
  function main (line 165) | main(void)

FILE: tests/parse_string.c
  function assert_is_string (line 33) | static void assert_is_string(cJSON *string_item)
  function assert_parse_string (line 46) | static void assert_parse_string(const char *string, const char *expected)
  function assert_not_parse_string (line 60) | static void assert_not_parse_string(const char * const string)
  function parse_string_should_parse_strings (line 73) | static void parse_string_should_parse_strings(void)
  function parse_string_should_parse_utf16_surrogate_pairs (line 87) | static void parse_string_should_parse_utf16_surrogate_pairs(void)
  function parse_string_should_not_parse_non_strings (line 93) | static void parse_string_should_not_parse_non_strings(void)
  function parse_string_should_not_parse_invalid_backslash (line 101) | static void parse_string_should_not_parse_invalid_backslash(void)
  function parse_string_should_not_overflow_with_closing_backslash (line 109) | static void parse_string_should_not_overflow_with_closing_backslash(void)
  function parse_string_should_parse_bug_94 (line 115) | static void parse_string_should_parse_bug_94(void)
  function main (line 122) | main(void)

FILE: tests/parse_value.c
  function assert_is_value (line 33) | static void assert_is_value(cJSON *value_item, int type)
  function assert_parse_value (line 44) | static void assert_parse_value(const char *string, int type)
  function parse_value_should_parse_null (line 55) | static void parse_value_should_parse_null(void)
  function parse_value_should_parse_true (line 61) | static void parse_value_should_parse_true(void)
  function parse_value_should_parse_false (line 67) | static void parse_value_should_parse_false(void)
  function parse_value_should_parse_number (line 73) | static void parse_value_should_parse_number(void)
  function parse_value_should_parse_string (line 79) | static void parse_value_should_parse_string(void)
  function parse_value_should_parse_array (line 87) | static void parse_value_should_parse_array(void)
  function parse_value_should_parse_object (line 93) | static void parse_value_should_parse_object(void)
  function main (line 99) | main(void)

FILE: tests/parse_with_opts.c
  function parse_with_opts_should_handle_null (line 27) | static void parse_with_opts_should_handle_null(void)
  function parse_with_opts_should_handle_empty_strings (line 39) | static void parse_with_opts_should_handle_empty_strings(void)
  function parse_with_opts_should_handle_incomplete_json (line 52) | static void parse_with_opts_should_handle_incomplete_json(void)
  function parse_with_opts_should_require_null_if_requested (line 62) | static void parse_with_opts_should_require_null_if_requested(void)
  function parse_with_opts_should_return_parse_end (line 73) | static void parse_with_opts_should_return_parse_end(void)
  function parse_with_opts_should_parse_utf8_bom (line 84) | static void parse_with_opts_should_parse_utf8_bom(void)
  function main (line 100) | main(void)

FILE: tests/print_array.c
  function assert_print_array (line 27) | static void assert_print_array(const char * const expected, const char *...
  function print_array_should_print_empty_arrays (line 70) | static void print_array_should_print_empty_arrays(void)
  function print_array_should_print_arrays_with_one_element (line 75) | static void print_array_should_print_arrays_with_one_element(void)
  function print_array_should_print_arrays_with_multiple_elements (line 84) | static void print_array_should_print_arrays_with_multiple_elements(void)
  function main (line 90) | main(void)

FILE: tests/print_number.c
  function assert_print_number (line 27) | static void assert_print_number(const char *expected, double input)
  function print_number_should_print_zero (line 65) | static void print_number_should_print_zero(void)
  function print_number_should_print_negative_integers (line 70) | static void print_number_should_print_negative_integers(void)
  function print_number_should_print_positive_integers (line 77) | static void print_number_should_print_positive_integers(void)
  function print_number_should_print_positive_reals (line 84) | static void print_number_should_print_positive_reals(void)
  function print_number_should_print_negative_reals (line 94) | static void print_number_should_print_negative_reals(void)
  function print_number_should_print_non_number (line 103) | static void print_number_should_print_non_number(void)
  function main (line 112) | main(void)

FILE: tests/print_object.c
  function assert_print_object (line 27) | static void assert_print_object(const char * const expected, const char ...
  function print_object_should_print_empty_objects (line 71) | static void print_object_should_print_empty_objects(void)
  function print_object_should_print_objects_with_one_element (line 76) | static void print_object_should_print_objects_with_one_element(void)
  function print_object_should_print_objects_with_multiple_elements (line 85) | static void print_object_should_print_objects_with_multiple_elements(void)
  function main (line 91) | main(void)

FILE: tests/print_string.c
  function assert_print_string (line 27) | static void assert_print_string(const char *expected, const char *input)
  function print_string_should_print_empty_strings (line 41) | static void print_string_should_print_empty_strings(void)
  function print_string_should_print_ascii (line 47) | static void print_string_should_print_ascii(void)
  function print_string_should_print_utf8 (line 63) | static void print_string_should_print_utf8(void)
  function main (line 68) | main(void)

FILE: tests/print_value.c
  function assert_print_value (line 31) | static void assert_print_value(const char *input)
  function print_value_should_print_null (line 57) | static void print_value_should_print_null(void)
  function print_value_should_print_true (line 62) | static void print_value_should_print_true(void)
  function print_value_should_print_false (line 67) | static void print_value_should_print_false(void)
  function print_value_should_print_number (line 72) | static void print_value_should_print_number(void)
  function print_value_should_print_string (line 77) | static void print_value_should_print_string(void)
  function print_value_should_print_array (line 83) | static void print_value_should_print_array(void)
  function print_value_should_print_object (line 88) | static void print_value_should_print_object(void)
  function main (line 93) | main(void)

FILE: tests/readme_examples.c
  function supports_full_hd (line 169) | static int supports_full_hd(const char * const monitor)
  function create_monitor_should_create_a_monitor (line 217) | static void create_monitor_should_create_a_monitor(void)
  function create_monitor_with_helpers_should_create_a_monitor (line 226) | static void create_monitor_with_helpers_should_create_a_monitor(void)
  function supports_full_hd_should_check_for_full_hd_support (line 235) | static void supports_full_hd_should_check_for_full_hd_support(void)
  function main (line 249) | main(void)

FILE: tests/unity/auto/colour_prompt.rb
  class ColourCommandLine (line 22) | class ColourCommandLine
    method initialize (line 23) | def initialize
    method change_to (line 31) | def change_to(new_colour)
    method win32_colour (line 39) | def win32_colour(colour)
    method posix_colour (line 62) | def posix_colour(colour)
    method out_c (line 98) | def out_c(mode, colour, str)
  function colour_puts (line 112) | def colour_puts(role, str)
  function colour_print (line 116) | def colour_print(role, str)

FILE: tests/unity/auto/colour_reporter.rb
  function report (line 11) | def report(message)

FILE: tests/unity/auto/generate_module.rb
  class UnityModuleGenerator (line 45) | class UnityModuleGenerator
    method initialize (line 47) | def initialize(options = nil)
    method default_options (line 97) | def self.default_options
    method grab_config (line 113) | def self.grab_config(config_file)
    method files_to_operate_on (line 125) | def files_to_operate_on(module_name, pattern = nil)
    method create_filename (line 168) | def create_filename(part1, part2 = '')
    method generate (line 189) | def generate(module_name, pattern = nil)
    method destroy (line 229) | def destroy(module_name, pattern = nil)

FILE: tests/unity/auto/generate_test_runner.rb
  class UnityTestRunnerGenerator (line 9) | class UnityTestRunnerGenerator
    method initialize (line 10) | def initialize(options = nil)
    method default_options (line 21) | def self.default_options
    method grab_config (line 38) | def self.grab_config(config_file)
    method run (line 49) | def run(input_file, output_file, options = nil)
    method generate (line 73) | def generate(input_file, output_file, tests, used_mocks, testfile_incl...
    method find_tests (line 91) | def find_tests(source)
    method find_includes (line 132) | def find_includes(source)
    method find_mocks (line 147) | def find_mocks(includes)
    method create_header (line 156) | def create_header(output, mocks, testfile_includes = [])
    method create_externs (line 193) | def create_externs(output, tests, _mocks)
    method create_mock_management (line 203) | def create_mock_management(output, mock_headers)
    method create_suite_setup (line 240) | def create_suite_setup(output)
    method create_suite_teardown (line 256) | def create_suite_teardown(output)
    method create_runtest (line 274) | def create_runtest(output, used_mocks)
    method create_reset (line 307) | def create_reset(output, used_mocks)
    method create_main (line 320) | def create_main(output, filename, tests, used_mocks)
    method create_h_file (line 381) | def create_h_file(output, filename, tests, testfile_includes, used_mocks)

FILE: tests/unity/auto/parse_output.rb
  class ParseOutput (line 19) | class ParseOutput
    method initialize (line 20) | def initialize
    method set_xml_output (line 29) | def set_xml_output
    method write_xml_output (line 34) | def write_xml_output
    method test_suite_verify (line 45) | def test_suite_verify(test_suite_name)
    method test_passed (line 58) | def test_passed(array)
    method test_passed_unity_fixture (line 71) | def test_passed_unity_fixture(array)
    method test_ignored (line 82) | def test_ignored(array)
    method test_failed (line 104) | def test_failed(array)
    method detect_os (line 127) | def detect_os
    method process (line 141) | def process(name)

FILE: tests/unity/auto/stylize_as_junit.rb
  class ArgvParser (line 14) | class ArgvParser
    method parse (line 18) | def self.parse(args)
  class UnityToJUnit (line 67) | class UnityToJUnit
    method initialize (line 72) | def initialize
    method run (line 77) | def run
    method usage (line 120) | def usage(err_msg = nil)
    method get_details (line 139) | def get_details(_result_file, lines)
    method parse_test_summary (line 153) | def parse_test_summary(summary)
    method here (line 158) | def here
    method results_structure (line 164) | def results_structure
    method write_xml_header (line 175) | def write_xml_header(stream)
    method write_suites_header (line 179) | def write_suites_header(stream)
    method write_suite_header (line 183) | def write_suite_header(counts, stream)
    method write_failures (line 187) | def write_failures(results, stream)
    method write_tests (line 198) | def write_tests(results, stream)
    method write_ignored (line 205) | def write_ignored(results, stream)
    method write_suite_footer (line 217) | def write_suite_footer(stream)
    method write_suites_footer (line 221) | def write_suites_footer(stream)

FILE: tests/unity/auto/test_file_filter.rb
  type RakefileHelpers (line 9) | module RakefileHelpers
    class TestFileFilter (line 10) | class TestFileFilter
      method initialize (line 11) | def initialize(all_files = false)

FILE: tests/unity/auto/type_sanitizer.rb
  type TypeSanitizer (line 1) | module TypeSanitizer
    function sanitize_c_identifier (line 2) | def self.sanitize_c_identifier(unsanitized)

FILE: tests/unity/auto/unity_test_summary.py
  class UnityTestSummary (line 13) | class UnityTestSummary:
    method __init__ (line 14) | def __init__(self):
    method run (line 20) | def run(self):
    method set_targets (line 68) | def set_targets(self, target_array):
    method set_root_path (line 71) | def set_root_path(self, path):
    method usage (line 74) | def usage(self, err_msg=None):
    method get_details (line 85) | def get_details(self, result_file, lines):
    method parse_test_summary (line 108) | def parse_test_summary(self, summary):

FILE: tests/unity/auto/unity_test_summary.rb
  class UnityTestSummary (line 14) | class UnityTestSummary
    method initialize (line 20) | def initialize(_opts = {})
    method run (line 27) | def run
    method usage (line 73) | def usage(err_msg = nil)
    method get_details (line 86) | def get_details(_result_file, lines)
    method parse_test_summary (line 100) | def parse_test_summary(summary)
    method here (line 105) | def here

FILE: tests/unity/auto/unity_to_junit.py
  class UnityTestSummary (line 9) | class UnityTestSummary:
    method __init__ (line 10) | def __init__(self):
    method run (line 19) | def run(self):
    method set_targets (line 104) | def set_targets(self, target_array):
    method set_root_path (line 107) | def set_root_path(self, path):
    method usage (line 111) | def usage(err_msg=None):

FILE: tests/unity/examples/example_1/src/ProductionCode.c
  function FindFunction_WhichIsBroken (line 11) | int FindFunction_WhichIsBroken(int NumberToFind)
  function FunctionWhichReturnsLocalVariable (line 21) | int FunctionWhichReturnsLocalVariable(void)

FILE: tests/unity/examples/example_2/src/ProductionCode.c
  function FindFunction_WhichIsBroken (line 11) | int FindFunction_WhichIsBroken(int NumberToFind)
  function FunctionWhichReturnsLocalVariable (line 21) | int FunctionWhichReturnsLocalVariable(void)

FILE: tests/unity/examples/example_3/helper/UnityHelper.c
  function AssertEqualExampleStruct (line 6) | void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXA...

FILE: tests/unity/examples/example_3/rakefile_helper.rb
  type RakefileHelpers (line 7) | module RakefileHelpers
    function load_configuration (line 10) | def load_configuration(config_file)
    function configure_clean (line 15) | def configure_clean
    function configure_toolchain (line 19) | def configure_toolchain(config_file = DEFAULT_CONFIG_FILE)
    function unit_test_files (line 25) | def unit_test_files
    function local_include_dirs (line 31) | def local_include_dirs
    function extract_headers (line 37) | def extract_headers(filename)
    function find_source_file (line 47) | def find_source_file(header, paths)
    function tackit (line 55) | def tackit(strings)
    function squash (line 64) | def squash(prefix, items)
    function build_compiler_fields (line 70) | def build_compiler_fields
    function compile (line 84) | def compile(file, _defines = [])
    function build_linker_fields (line 93) | def build_linker_fields
    function link_it (line 109) | def link_it(exe_name, obj_list)
    function build_simulator_fields (line 119) | def build_simulator_fields
    function execute (line 140) | def execute(command_string, verbose = true, raise_on_fail = true)
    function report_summary (line 150) | def report_summary
    function run_tests (line 161) | def run_tests(test_files)
    function build_application (line 221) | def build_application(main)
    function fail_out (line 243) | def fail_out(msg)

FILE: tests/unity/examples/example_3/src/ProductionCode.c
  function FindFunction_WhichIsBroken (line 11) | int FindFunction_WhichIsBroken(int NumberToFind)
  function FunctionWhichReturnsLocalVariable (line 21) | int FunctionWhichReturnsLocalVariable(void)

FILE: tests/unity/extras/fixture/rakefile_helper.rb
  type RakefileHelpers (line 13) | module RakefileHelpers
    function load_configuration (line 16) | def load_configuration(config_file)
    function configure_clean (line 25) | def configure_clean
    function configure_toolchain (line 29) | def configure_toolchain(config_file = DEFAULT_CONFIG_FILE)
    function tackit (line 36) | def tackit(strings)
    function squash (line 45) | def squash(prefix, items)
    function build_compiler_fields (line 51) | def build_compiler_fields
    function compile (line 65) | def compile(file, _defines = [])
    function build_linker_fields (line 75) | def build_linker_fields
    function link_it (line 91) | def link_it(exe_name, obj_list)
    function build_simulator_fields (line 101) | def build_simulator_fields
    function execute (line 121) | def execute(command_string, verbose = true)
    function report_summary (line 129) | def report_summary
    function run_tests (line 139) | def run_tests

FILE: tests/unity/extras/fixture/src/unity_fixture.c
  type UNITY_FIXTURE_T (line 12) | struct UNITY_FIXTURE_T
  function setUp (line 19) | void setUp(void)    { /*does nothing*/ }
  function tearDown (line 20) | void tearDown(void) { /*does nothing*/ }
  function announceTestRun (line 23) | static void announceTestRun(unsigned int runNumber)
  function UnityMain (line 32) | int UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
  function selected (line 51) | static int selected(const char* filter, const char* name)
  function testSelected (line 58) | static int testSelected(const char* test)
  function groupSelected (line 63) | static int groupSelected(const char* group)
  function UnityTestRunner (line 68) | void UnityTestRunner(unityfunction* setup,
  function UnityIgnoreTest (line 115) | void UnityIgnoreTest(const char* printableName, const char* group, const...
  function UnityMalloc_StartTest (line 138) | void UnityMalloc_StartTest(void)
  function UnityMalloc_EndTest (line 144) | void UnityMalloc_EndTest(void)
  function UnityMalloc_MakeMallocFailAfterCount (line 153) | void UnityMalloc_MakeMallocFailAfterCount(int countdown)
  type Guard (line 172) | typedef struct GuardBytes
  function isOverrun (line 218) | static int isOverrun(void* mem)
  function release_memory (line 227) | static void release_memory(void* mem)
  function unity_free (line 243) | void unity_free(void* mem)
  type PointerPair (line 308) | struct PointerPair
  type PointerPair (line 314) | struct PointerPair
  function UnityPointer_Init (line 317) | void UnityPointer_Init(void)
  function UnityPointer_Set (line 322) | void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line)
  function UnityPointer_UndoAllSets (line 337) | void UnityPointer_UndoAllSets(void)
  function UnityGetCommandLineOptions (line 347) | int UnityGetCommandLineOptions(int argc, const char* argv[])
  function UnityConcludeFixtureTest (line 409) | void UnityConcludeFixtureTest(void)

FILE: tests/unity/extras/fixture/src/unity_fixture_internals.h
  type UNITY_FIXTURE_T (line 16) | struct UNITY_FIXTURE_T
  type UNITY_FIXTURE_T (line 23) | struct UNITY_FIXTURE_T

FILE: tests/unity/src/unity.c
  type UNITY_STORAGE_T (line 21) | struct UNITY_STORAGE_T
  function UnityPrint (line 70) | void UnityPrint(const char* string)
  function UnityPrintLen (line 119) | void UnityPrintLen(const char* string, const UNITY_UINT32 length)
  function UnityPrintNumberByStyle (line 157) | void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY...
  function UnityPrintNumber (line 176) | void UnityPrintNumber(const UNITY_INT number_to_print)
  function UnityPrintNumberUnsigned (line 191) | void UnityPrintNumberUnsigned(const UNITY_UINT number)
  function UnityPrintNumberHex (line 210) | void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_...
  function UnityPrintMask (line 233) | void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number)
  function UnityPrintFloat (line 266) | void UnityPrintFloat(const UNITY_DOUBLE input_number)
  function UnityTestResultsBegin (line 357) | static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYP...
  function UnityTestResultsFailBegin (line 368) | static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line)
  function UnityConcludeTest (line 376) | void UnityConcludeTest(void)
  function UnityAddMsgIfSpecified (line 399) | static void UnityAddMsgIfSpecified(const char* msg)
  function UnityPrintExpectedAndActualStrings (line 422) | static void UnityPrintExpectedAndActualStrings(const char* expected, con...
  function UnityPrintExpectedAndActualStringsLen (line 449) | static void UnityPrintExpectedAndActualStringsLen(const char* expected,
  function UnityIsOneArrayNull (line 481) | static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected,
  function UnityAssertBits (line 513) | void UnityAssertBits(const UNITY_INT mask,
  function UnityAssertEqualNumber (line 534) | void UnityAssertEqualNumber(const UNITY_INT expected,
  function UnityAssertGreaterOrLessOrEqualNumber (line 555) | void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold,
  function UnityAssertEqualIntArray (line 601) | void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
  function UnityFloatsWithin (line 706) | static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UN...
  function UnityAssertEqualFloatArray (line 712) | void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* e...
  function UnityAssertFloatsWithin (line 754) | void UnityAssertFloatsWithin(const UNITY_FLOAT delta,
  function UnityAssertFloatSpecial (line 773) | void UnityAssertFloatSpecial(const UNITY_FLOAT actual,
  function UnityDoublesWithin (line 836) | static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected,...
  function UnityAssertEqualDoubleArray (line 842) | void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE*...
  function UnityAssertDoublesWithin (line 884) | void UnityAssertDoublesWithin(const UNITY_DOUBLE delta,
  function UnityAssertDoubleSpecial (line 903) | void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual,
  function UnityAssertNumbersWithin (line 965) | void UnityAssertNumbersWithin(const UNITY_UINT delta,
  function UnityAssertEqualString (line 1004) | void UnityAssertEqualString(const char* expected,
  function UnityAssertEqualStringLen (line 1043) | void UnityAssertEqualStringLen(const char* expected,
  function UnityAssertEqualStringArray (line 1083) | void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected,
  function UnityAssertEqualMemory (line 1162) | void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected,
  function UNITY_INTERNAL_PTR (line 1237) | UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 ...
  function UNITY_INTERNAL_PTR (line 1261) | UNITY_INTERNAL_PTR UnityFloatToPtr(const float num)
  function UNITY_INTERNAL_PTR (line 1269) | UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num)
  function UnityFail (line 1280) | void UnityFail(const char* msg, const UNITY_LINE_TYPE line)
  function UnityIgnore (line 1314) | void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line)
  function UnityDefaultTestRun (line 1330) | void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, c...
  function UnityBegin (line 1349) | void UnityBegin(const char* filename)
  function UnityEnd (line 1365) | int UnityEnd(void)
  function UnityParseOptions (line 1403) | int UnityParseOptions(int argc, char** argv)
  function IsStringInBiggerString (line 1459) | int IsStringInBiggerString(const char* longstring, const char* shortstring)
  function UnityStringArgumentMatches (line 1500) | int UnityStringArgumentMatches(const char* str)
  function UnityTestMatches (line 1549) | int UnityTestMatches(void)

FILE: tests/unity/src/unity.h
  function UNITY_WEAK_ATTRIBUTE (line 39) | UNITY_WEAK_ATTRIBUTE void setUp(void) { }
  function UNITY_WEAK_ATTRIBUTE (line 40) | UNITY_WEAK_ATTRIBUTE void tearDown(void) { }
  function UNITY_WEAK_ATTRIBUTE (line 41) | UNITY_WEAK_ATTRIBUTE void suiteSetUp(void) { }
  function UNITY_WEAK_ATTRIBUTE (line 42) | UNITY_WEAK_ATTRIBUTE int suiteTearDown(int num_failures) { return num_fa...
  function setUp (line 45) | void setUp(void) { }
  function tearDown (line 47) | void tearDown(void) { }
  function suiteSetUp (line 49) | void suiteSetUp(void) { }
  function suiteTearDown (line 51) | int suiteTearDown(int num_failures) { return num_failures; }

FILE: tests/unity/src/unity_internals.h
  type UNITY_UINT8 (line 90) | typedef unsigned char   UNITY_UINT8;
  type UNITY_UINT16 (line 91) | typedef unsigned short  UNITY_UINT16;
  type UNITY_UINT32 (line 92) | typedef unsigned int    UNITY_UINT32;
  type UNITY_INT8 (line 93) | typedef signed char     UNITY_INT8;
  type UNITY_INT16 (line 94) | typedef signed short    UNITY_INT16;
  type UNITY_INT32 (line 95) | typedef signed int      UNITY_INT32;
  type UNITY_UINT8 (line 97) | typedef unsigned char   UNITY_UINT8;
  type UNITY_UINT16 (line 98) | typedef unsigned int    UNITY_UINT16;
  type UNITY_UINT32 (line 99) | typedef unsigned long   UNITY_UINT32;
  type UNITY_INT8 (line 100) | typedef signed char     UNITY_INT8;
  type UNITY_INT16 (line 101) | typedef signed int      UNITY_INT16;
  type UNITY_INT32 (line 102) | typedef signed long     UNITY_INT32;
  type UNITY_UINT32 (line 119) | typedef UNITY_UINT32 UNITY_UINT;
  type UNITY_INT32 (line 120) | typedef UNITY_INT32 UNITY_INT;
  type UNITY_UINT64 (line 125) | typedef unsigned long long UNITY_UINT64;
  type UNITY_INT64 (line 126) | typedef signed long long   UNITY_INT64;
  type UNITY_UINT64 (line 128) | typedef unsigned long      UNITY_UINT64;
  type UNITY_INT64 (line 129) | typedef signed long        UNITY_INT64;
  type UNITY_UINT64 (line 133) | typedef UNITY_UINT64 UNITY_UINT;
  type UNITY_INT64 (line 134) | typedef UNITY_INT64 UNITY_INT;
  type UNITY_FLOAT_TYPE (line 186) | typedef UNITY_FLOAT_TYPE UNITY_FLOAT;
  type UNITY_FLOAT (line 220) | typedef UNITY_FLOAT UNITY_DOUBLE;
  type UNITY_DOUBLE_TYPE (line 234) | typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE;
  type UNITY_DISPLAY_STYLE_T (line 325) | typedef enum
  type UNITY_COMPARISON_T (line 353) | typedef enum
  type UNITY_FLOAT_TRAIT_T (line 363) | typedef enum UNITY_FLOAT_TRAIT
  type UNITY_FLAGS_T (line 377) | typedef enum
  type UNITY_STORAGE_T (line 383) | struct UNITY_STORAGE_T
  type UNITY_STORAGE_T (line 402) | struct UNITY_STORAGE_T

FILE: tests/unity_setup.c
  function setUp (line 2) | void setUp(void) { }
  function tearDown (line 3) | void tearDown(void) { }
Condensed preview — 160 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (885K chars).
[
  {
    "path": ".editorconfig",
    "chars": 428,
    "preview": "root = true\n\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".gitattributes",
    "chars": 340,
    "preview": "*  \t\t\t\t\ttext=auto\n/tests/inputs/*\ttext eol=lf\n\n.gitattributes          export-ignore\n.gitignore              export-igno"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 2386,
    "preview": "Contribution Guidelines\n=======================\n\nContributions to cJSON are welcome. If you find a bug or want to improv"
  },
  {
    "path": ".github/workflows/CI.yml",
    "chars": 3308,
    "preview": "name: CI\n\non:\n  push:\n    branches: [ master ]\n    paths-ignore:\n      - '**.md'\n      - 'LICENSE'\n  pull_request:\n    t"
  },
  {
    "path": ".github/workflows/ci-fuzz.yml",
    "chars": 599,
    "preview": "name: CIFuzz\non: [pull_request]\njobs:\n  Fuzzing:\n    runs-on: ubuntu-latest\n    steps:\n    - name: Build Fuzzers\n      u"
  },
  {
    "path": ".gitignore",
    "chars": 171,
    "preview": ".svn\ntest\n*.o\n*.a\n*.so\n*.swp\n*.patch\ntags\n*.dylib*\nbuild/\ncJSON_test\ncJSON_test_utils\nlibcjson.so.*\nlibcjson_utils.so.*\n"
  },
  {
    "path": ".travis.yml",
    "chars": 602,
    "preview": "dist: trusty\nsudo: false\nlanguage: c\nenv:\n  matrix:\n    - VALGRIND=On SANITIZERS=Off\n    - VALGRIND=Off SANITIZERS=Off\n "
  },
  {
    "path": "CHANGELOG.md",
    "chars": 25980,
    "preview": "1.7.19 (Sep 9, 2025)\n======\nFixes:\n------\n* Fix indentation (should use spaces), see #814\n* Fix spelling errors found by"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 10205,
    "preview": "set(CMAKE_LEGACY_CYGWIN_WIN32 0)\ncmake_minimum_required(VERSION 3.5)\n\nproject(cJSON\n    VERSION 1.7.19\n    LANGUAGES C)\n"
  },
  {
    "path": "CONTRIBUTORS.md",
    "chars": 4119,
    "preview": "Contributors\n============\n\nOriginal Author: \n- [Dave Gamble](https://github.com/DaveGamble)  \n\nCurrent Maintainer: \n- [M"
  },
  {
    "path": "LICENSE",
    "chars": 1084,
    "preview": "Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\nPermission is hereby granted, free of charge, to any person "
  },
  {
    "path": "Makefile",
    "chars": 4650,
    "preview": "CJSON_OBJ = cJSON.o\nUTILS_OBJ = cJSON_Utils.o\nCJSON_LIBNAME = libcjson\nUTILS_LIBNAME = libcjson_utils\nCJSON_TEST = cJSON"
  },
  {
    "path": "README.md",
    "chars": 27629,
    "preview": "# cJSON\n\nUltralightweight JSON parser in ANSI C.\n\n## Table of contents\n* [License](#license)\n* [Usage](#usage)\n  * [Welc"
  },
  {
    "path": "SECURITY.md",
    "chars": 713,
    "preview": "# Security Policy\n\n## Supported Versions\n\nSecurity is of the highest importance and all security vulnerabilities or susp"
  },
  {
    "path": "appveyor.yml",
    "chars": 2284,
    "preview": "os: Visual Studio 2015\n\n# ENABLE_CUSTOM_COMPILER_FLAGS - on by default\n# ENABLE_SANITIZERS - off by default\n# ENABLE_PUB"
  },
  {
    "path": "cJSON.c",
    "chars": 80692,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "cJSON.h",
    "chars": 16394,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "cJSON_Utils.c",
    "chars": 40736,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "cJSON_Utils.h",
    "chars": 3938,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "fuzzing/.gitignore",
    "chars": 10,
    "preview": "afl-build\n"
  },
  {
    "path": "fuzzing/CMakeLists.txt",
    "chars": 1169,
    "preview": "option(ENABLE_FUZZING \"Create executables and targets for fuzzing cJSON with afl.\" Off)\nif (ENABLE_FUZZING)\n    find_pro"
  },
  {
    "path": "fuzzing/afl-prepare-linux.sh",
    "chars": 153,
    "preview": "#!/bin/bash\n\nset -x\necho core | sudo tee /proc/sys/kernel/core_pattern\necho performance | sudo tee /sys/devices/system/c"
  },
  {
    "path": "fuzzing/afl.c",
    "chars": 4192,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "fuzzing/afl.sh",
    "chars": 192,
    "preview": "#!/bin/bash\n\nmkdir -p afl-build || exit 1\ncd afl-build || exit 1\n#cleanup\nrm -r -- *\n\nCC=afl-clang-fast cmake ../.. -DEN"
  },
  {
    "path": "fuzzing/cjson_read_fuzzer.c",
    "chars": 1695,
    "preview": "#include <stdlib.h>\n#include <stdint.h>\n#include <string.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"../cJSON."
  },
  {
    "path": "fuzzing/fuzz_main.c",
    "chars": 992,
    "preview": "#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n\nint LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)"
  },
  {
    "path": "fuzzing/inputs/test1",
    "chars": 585,
    "preview": "bf{\n    \"glossary\": {\n        \"title\": \"example glossary\",\n\t\t\"GlossDiv\": {\n            \"title\": \"S\",\n\t\t\t\"GlossList\": {\n "
  },
  {
    "path": "fuzzing/inputs/test10",
    "chars": 81,
    "preview": "bf[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]\n"
  },
  {
    "path": "fuzzing/inputs/test11",
    "chars": 151,
    "preview": "bf{\n\"name\": \"Jack (\\\"Bee\\\") Nimble\",\n\"format\": {\"type\":       \"rect\",\n\"width\":      1920,\n\"height\":     1080,\n\"interlace"
  },
  {
    "path": "fuzzing/inputs/test2",
    "chars": 244,
    "preview": "bf{\"menu\": {\n  \"id\": \"file\",\n  \"value\": \"File\",\n  \"popup\": {\n    \"menuitem\": [\n      {\"value\": \"New\", \"onclick\": \"Create"
  },
  {
    "path": "fuzzing/inputs/test3",
    "chars": 603,
    "preview": "bf{\"widget\": {\n    \"debug\": \"on\",\n    \"window\": {\n        \"title\": \"Sample Konfabulator Widget\",\n        \"name\": \"main_w"
  },
  {
    "path": "fuzzing/inputs/test3.bu",
    "chars": 603,
    "preview": "bu{\"widget\": {\n    \"debug\": \"on\",\n    \"window\": {\n        \"title\": \"Sample Konfabulator Widget\",\n        \"name\": \"main_w"
  },
  {
    "path": "fuzzing/inputs/test3.uf",
    "chars": 603,
    "preview": "uf{\"widget\": {\n    \"debug\": \"on\",\n    \"window\": {\n        \"title\": \"Sample Konfabulator Widget\",\n        \"name\": \"main_w"
  },
  {
    "path": "fuzzing/inputs/test3.uu",
    "chars": 603,
    "preview": "uu{\"widget\": {\n    \"debug\": \"on\",\n    \"window\": {\n        \"title\": \"Sample Konfabulator Widget\",\n        \"name\": \"main_w"
  },
  {
    "path": "fuzzing/inputs/test4",
    "chars": 3465,
    "preview": "bf{\"web-app\": {\n  \"servlet\": [\n    {\n      \"servlet-name\": \"cofaxCDS\",\n      \"servlet-class\": \"org.cofax.cds.CDSServlet\""
  },
  {
    "path": "fuzzing/inputs/test5",
    "chars": 875,
    "preview": "bf{\"menu\": {\n    \"header\": \"SVG Viewer\",\n    \"items\": [\n        {\"id\": \"Open\"},\n        {\"id\": \"OpenNew\", \"label\": \"Open"
  },
  {
    "path": "fuzzing/inputs/test6",
    "chars": 487,
    "preview": "bf<!DOCTYPE html>\n    <html>\n    <head>\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n     "
  },
  {
    "path": "fuzzing/inputs/test7",
    "chars": 401,
    "preview": "bf[\n\t {\n\t \"precision\": \"zip\",\n\t \"Latitude\":  37.7668,\n\t \"Longitude\": -122.3959,\n\t \"Address\":   \"\",\n\t \"City\":      \"SAN F"
  },
  {
    "path": "fuzzing/inputs/test8",
    "chars": 249,
    "preview": "bf{\n\t\t\"Image\": {\n\t\t\t\"Width\":  800,\n\t\t\t\"Height\": 600,\n\t\t\t\"Title\":  \"View from 15th Floor\",\n\t\t\t\"Thumbnail\": {\n\t\t\t\t\"Url\":  "
  },
  {
    "path": "fuzzing/inputs/test9",
    "chars": 52,
    "preview": "bf[\n    [0, -1, 0],\n    [1, 0, 0],\n    [0, 0, 1]\n\t]\n"
  },
  {
    "path": "fuzzing/json.dict",
    "chars": 914,
    "preview": "#\n# AFL dictionary for JSON\n# -----------------------------\n#\n\nobject_start=\"{\"\nobject_end=\"}\"\nobject_empty=\"{}\"\nobject_"
  },
  {
    "path": "fuzzing/ossfuzz.sh",
    "chars": 529,
    "preview": "#!/bin/bash -eu\n\n# This script is meant to be run by\n# https://github.com/google/oss-fuzz/blob/master/projects/cjson/Doc"
  },
  {
    "path": "library_config/cJSONConfig.cmake.in",
    "chars": 802,
    "preview": "# Whether the utils lib was build.\nset(CJSON_UTILS_FOUND @ENABLE_CJSON_UTILS@)\n\n# The include directories used by cJSON\n"
  },
  {
    "path": "library_config/cJSONConfigVersion.cmake.in",
    "chars": 379,
    "preview": "set(PACKAGE_VERSION \"@PROJECT_VERSION@\")\n\n# Check whether the requested PACKAGE_FIND_VERSION is compatible\nif(\"${PACKAGE"
  },
  {
    "path": "library_config/libcjson.pc.in",
    "chars": 304,
    "preview": "libdir=@CMAKE_INSTALL_FULL_LIBDIR@\nincludedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@\n\nName: libcjson\nVersion: @PROJECT_VERSION@"
  },
  {
    "path": "library_config/libcjson_utils.pc.in",
    "chars": 351,
    "preview": "libdir=@CMAKE_INSTALL_FULL_LIBDIR@\nincludedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@\n\nName: libcjson_utils\nVersion: @PROJECT_VE"
  },
  {
    "path": "library_config/uninstall.cmake",
    "chars": 726,
    "preview": "cmake_minimum_required(VERSION 3.5)\n\nset(MANIFEST \"${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt\")\n\nif(NOT EXISTS ${M"
  },
  {
    "path": "test.c",
    "chars": 7711,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/CMakeLists.txt",
    "chars": 4530,
    "preview": "if(ENABLE_CJSON_TEST)\n    add_library(unity STATIC unity/src/unity.c)\n\n    # Disable -Werror for Unity\n    if (FLAG_SUPP"
  },
  {
    "path": "tests/cjson_add.c",
    "chars": 12774,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/common.h",
    "chars": 4166,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/compare_tests.c",
    "chars": 8588,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/inputs/test1",
    "chars": 583,
    "preview": "{\n    \"glossary\": {\n        \"title\": \"example glossary\",\n\t\t\"GlossDiv\": {\n            \"title\": \"S\",\n\t\t\t\"GlossList\": {\n   "
  },
  {
    "path": "tests/inputs/test1.expected",
    "chars": 474,
    "preview": "{\n\t\"glossary\":\t{\n\t\t\"title\":\t\"example glossary\",\n\t\t\"GlossDiv\":\t{\n\t\t\t\"title\":\t\"S\",\n\t\t\t\"GlossList\":\t{\n\t\t\t\t\"GlossEntry\":\t{\n\t"
  },
  {
    "path": "tests/inputs/test10",
    "chars": 79,
    "preview": "[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]\n"
  },
  {
    "path": "tests/inputs/test10.expected",
    "chars": 78,
    "preview": "[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]"
  },
  {
    "path": "tests/inputs/test11",
    "chars": 149,
    "preview": "{\n\"name\": \"Jack (\\\"Bee\\\") Nimble\",\n\"format\": {\"type\":       \"rect\",\n\"width\":      1920,\n\"height\":     1080,\n\"interlace\":"
  },
  {
    "path": "tests/inputs/test11.expected",
    "chars": 147,
    "preview": "{\n\t\"name\":\t\"Jack (\\\"Bee\\\") Nimble\",\n\t\"format\":\t{\n\t\t\"type\":\t\"rect\",\n\t\t\"width\":\t1920,\n\t\t\"height\":\t1080,\n\t\t\"interlace\":\tfal"
  },
  {
    "path": "tests/inputs/test2",
    "chars": 242,
    "preview": "{\"menu\": {\n  \"id\": \"file\",\n  \"value\": \"File\",\n  \"popup\": {\n    \"menuitem\": [\n      {\"value\": \"New\", \"onclick\": \"CreateNe"
  },
  {
    "path": "tests/inputs/test2.expected",
    "chars": 268,
    "preview": "{\n\t\"menu\":\t{\n\t\t\"id\":\t\"file\",\n\t\t\"value\":\t\"File\",\n\t\t\"popup\":\t{\n\t\t\t\"menuitem\":\t[{\n\t\t\t\t\t\"value\":\t\"New\",\n\t\t\t\t\t\"onclick\":\t\"Cre"
  },
  {
    "path": "tests/inputs/test3",
    "chars": 603,
    "preview": "{\"widget\": {\n    \"debug\": \"on\",\n    \"window\": {\n        \"title\": \"Sample Konfabulator Widget\",\n        \"name\": \"main_win"
  },
  {
    "path": "tests/inputs/test3.expected",
    "chars": 505,
    "preview": "{\n\t\"widget\":\t{\n\t\t\"debug\":\t\"on\",\n\t\t\"window\":\t{\n\t\t\t\"title\":\t\"Sample Konfabulator Widget\",\n\t\t\t\"name\":\t\"main_window\",\n\t\t\t\"wi"
  },
  {
    "path": "tests/inputs/test4",
    "chars": 3464,
    "preview": "{\"web-app\": {\n  \"servlet\": [  \n    {\n      \"servlet-name\": \"cofaxCDS\",\n      \"servlet-class\": \"org.cofax.cds.CDSServlet\""
  },
  {
    "path": "tests/inputs/test4.expected",
    "chars": 3285,
    "preview": "{\n\t\"web-app\":\t{\n\t\t\"servlet\":\t[{\n\t\t\t\t\"servlet-name\":\t\"cofaxCDS\",\n\t\t\t\t\"servlet-class\":\t\"org.cofax.cds.CDSServlet\",\n\t\t\t\t\"in"
  },
  {
    "path": "tests/inputs/test5",
    "chars": 873,
    "preview": "{\"menu\": {\n    \"header\": \"SVG Viewer\",\n    \"items\": [\n        {\"id\": \"Open\"},\n        {\"id\": \"OpenNew\", \"label\": \"Open N"
  },
  {
    "path": "tests/inputs/test5.expected",
    "chars": 900,
    "preview": "{\n\t\"menu\":\t{\n\t\t\"header\":\t\"SVG Viewer\",\n\t\t\"items\":\t[{\n\t\t\t\t\"id\":\t\"Open\"\n\t\t\t}, {\n\t\t\t\t\"id\":\t\"OpenNew\",\n\t\t\t\t\"label\":\t\"Open Ne"
  },
  {
    "path": "tests/inputs/test6",
    "chars": 484,
    "preview": "<!DOCTYPE html>\n    <html>\n    <head>\n      <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n      <"
  },
  {
    "path": "tests/inputs/test7",
    "chars": 399,
    "preview": "[\n\t {\n\t \"precision\": \"zip\",\n\t \"Latitude\":  37.7668,\n\t \"Longitude\": -122.3959,\n\t \"Address\":   \"\",\n\t \"City\":      \"SAN FRA"
  },
  {
    "path": "tests/inputs/test7.expected",
    "chars": 347,
    "preview": "[{\n\t\t\"precision\":\t\"zip\",\n\t\t\"Latitude\":\t37.7668,\n\t\t\"Longitude\":\t-122.3959,\n\t\t\"Address\":\t\"\",\n\t\t\"City\":\t\"SAN FRANCISCO\",\n\t\t"
  },
  {
    "path": "tests/inputs/test8",
    "chars": 247,
    "preview": "{\n\t\t\"Image\": {\n\t\t\t\"Width\":  800,\n\t\t\t\"Height\": 600,\n\t\t\t\"Title\":  \"View from 15th Floor\",\n\t\t\t\"Thumbnail\": {\n\t\t\t\t\"Url\":    "
  },
  {
    "path": "tests/inputs/test8.expected",
    "chars": 228,
    "preview": "{\n\t\"Image\":\t{\n\t\t\"Width\":\t800,\n\t\t\"Height\":\t600,\n\t\t\"Title\":\t\"View from 15th Floor\",\n\t\t\"Thumbnail\":\t{\n\t\t\t\"Url\":\t\"http:/*www"
  },
  {
    "path": "tests/inputs/test9",
    "chars": 50,
    "preview": "[\n    [0, -1, 0],\n    [1, 0, 0],\n    [0, 0, 1]\n\t]\n"
  },
  {
    "path": "tests/inputs/test9.expected",
    "chars": 34,
    "preview": "[[0, -1, 0], [1, 0, 0], [0, 0, 1]]"
  },
  {
    "path": "tests/json-patch-tests/.editorconfig",
    "chars": 183,
    "preview": "# EditorConfig is awesome: http://EditorConfig.org\n\nroot = true\n\n[*]\nend_of_line = lf\ninsert_final_newline = true\ncharse"
  },
  {
    "path": "tests/json-patch-tests/.gitignore",
    "chars": 34,
    "preview": "*~\n\\#*\n!.editorconfig\n!.gitignore\n"
  },
  {
    "path": "tests/json-patch-tests/.npmignore",
    "chars": 25,
    "preview": ".editorconfig\n.gitignore\n"
  },
  {
    "path": "tests/json-patch-tests/README.md",
    "chars": 2306,
    "preview": "JSON Patch Tests\n================\n\nThese are test cases for implementations of [IETF JSON Patch (RFC6902)](http://tools."
  },
  {
    "path": "tests/json-patch-tests/cjson-utils-tests.json",
    "chars": 2659,
    "preview": "[\n    {\n\t\"comment\": \"1\",\n\t\"doc\": { \"foo\": \"bar\"},\n\t\"patch\": [{ \"op\": \"add\", \"path\": \"/baz\", \"value\": \"qux\" }],\n\t\"expecte"
  },
  {
    "path": "tests/json-patch-tests/package.json",
    "chars": 393,
    "preview": "{\n  \"name\": \"json-patch-test-suite\",\n  \"version\": \"1.1.0\",\n  \"description\": \"JSON Patch RFC 6902 test suite\",\n  \"reposit"
  },
  {
    "path": "tests/json-patch-tests/spec_tests.json",
    "chars": 4031,
    "preview": "[\n  {\n    \"comment\": \"4.1. add with missing object\",\n    \"doc\": { \"q\": { \"bar\": 2 } },\n    \"patch\": [ {\"op\": \"add\", \"pat"
  },
  {
    "path": "tests/json-patch-tests/tests.json",
    "chars": 17205,
    "preview": "[\n    { \"comment\": \"empty list, empty docs\",\n      \"doc\": {},\n      \"patch\": [],\n      \"expected\": {} },\n\n    { \"comment"
  },
  {
    "path": "tests/json_patch_tests.c",
    "chars": 6776,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/minify_tests.c",
    "chars": 5456,
    "preview": "/*\n  Copyright (c) 2009-2019 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/misc_tests.c",
    "chars": 32086,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/misc_utils_tests.c",
    "chars": 3386,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/old_utils_tests.c",
    "chars": 7766,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/parse_array.c",
    "chars": 5068,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/parse_examples.c",
    "chars": 8699,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/parse_hex4.c",
    "chars": 3434,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/parse_number.c",
    "chars": 4673,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/parse_object.c",
    "chars": 5568,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/parse_string.c",
    "chars": 4672,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/parse_value.c",
    "chars": 3302,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/parse_with_opts.c",
    "chars": 4168,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/print_array.c",
    "chars": 3818,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/print_number.c",
    "chars": 4447,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/print_object.c",
    "chars": 4223,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/print_string.c",
    "chars": 2812,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/print_value.c",
    "chars": 3189,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/readme_examples.c",
    "chars": 6854,
    "preview": "/*\n  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors\n\n  Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "tests/unity/.gitattributes",
    "chars": 573,
    "preview": "*           text=auto\n\n# These files are text and should be normalized (convert crlf to lf)\n*.rb        text\n*.test     "
  },
  {
    "path": "tests/unity/.gitignore",
    "chars": 212,
    "preview": "build/\ntest/sandbox\n.DS_Store\nexamples/example_1/test1.exe\nexamples/example_1/test2.exe\nexamples/example_2/all_tests.exe"
  },
  {
    "path": "tests/unity/.travis.yml",
    "chars": 852,
    "preview": "language: c\n\nmatrix:\n include:\n    - os: osx\n      compiler: clang\n      osx_image: xcode7.3\n    - os: linux\n      dist:"
  },
  {
    "path": "tests/unity/README.md",
    "chars": 7806,
    "preview": "Unity Test API\n==============\n\n[![Unity Build Status](https://api.travis-ci.org/ThrowTheSwitch/Unity.png?branch=master)]"
  },
  {
    "path": "tests/unity/auto/colour_prompt.rb",
    "chars": 3462,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/auto/colour_reporter.rb",
    "chars": 1178,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/auto/generate_config.yml",
    "chars": 1273,
    "preview": "#this is a sample configuration file for generate_module\n#you would use it by calling generate_module with the -ygenerat"
  },
  {
    "path": "tests/unity/auto/generate_module.rb",
    "chars": 11086,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/auto/generate_test_runner.rb",
    "chars": 18170,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/auto/parse_output.rb",
    "chars": 6995,
    "preview": "#============================================================\n#  Author:   John Theofanopoulos\n#  A simple parser.   Tak"
  },
  {
    "path": "tests/unity/auto/stylize_as_junit.rb",
    "chars": 7698,
    "preview": "#!/usr/bin/ruby\n#\n# unity_to_junit.rb\n#\nrequire 'fileutils'\nrequire 'optparse'\nrequire 'ostruct'\nrequire 'set'\n\nrequire "
  },
  {
    "path": "tests/unity/auto/test_file_filter.rb",
    "chars": 766,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/auto/type_sanitizer.rb",
    "chars": 201,
    "preview": "module TypeSanitizer\n  def self.sanitize_c_identifier(unsanitized)\n    # convert filename to valid C identifier by repla"
  },
  {
    "path": "tests/unity/auto/unity_test_summary.py",
    "chars": 5173,
    "preview": "#! python3\n# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 201"
  },
  {
    "path": "tests/unity/auto/unity_test_summary.rb",
    "chars": 4143,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/auto/unity_to_junit.py",
    "chars": 5939,
    "preview": "import sys\nimport os\nfrom glob import glob\n\nfrom pyparsing import *\nfrom junit_xml import TestSuite, TestCase\n\n\nclass Un"
  },
  {
    "path": "tests/unity/docs/ThrowTheSwitchCodingStandard.md",
    "chars": 8086,
    "preview": "# ThrowTheSwitch.org Coding Standard\n\nHi. Welcome to the coding standard for ThrowTheSwitch.org. For the most part,\nwe t"
  },
  {
    "path": "tests/unity/docs/UnityAssertionsReference.md",
    "chars": 28588,
    "preview": "# Unity Assertions Reference\n\n## Background and Overview\n\n### Super Condensed Version\n\n- An assertion establishes truth "
  },
  {
    "path": "tests/unity/docs/UnityConfigurationGuide.md",
    "chars": 18093,
    "preview": "# Unity Configuration Guide\n\n## C Standards, Compilers and Microcontrollers\n\nThe embedded software world contains its ch"
  },
  {
    "path": "tests/unity/docs/UnityGettingStartedGuide.md",
    "chars": 8248,
    "preview": "# Unity - Getting Started\n\n## Welcome\n\nCongratulations. You're now the proud owner of your very own pile of bits! What\na"
  },
  {
    "path": "tests/unity/docs/UnityHelperScriptsGuide.md",
    "chars": 9332,
    "preview": "# Unity Helper Scripts\n\n## With a Little Help From Our Friends\n\nSometimes what it takes to be a really efficient C progr"
  },
  {
    "path": "tests/unity/docs/license.txt",
    "chars": 1123,
    "preview": "The MIT License (MIT)\n\nCopyright (c) <year> 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams\n\nPermission is hereby"
  },
  {
    "path": "tests/unity/examples/example_1/makefile",
    "chars": 2237,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/examples/example_1/readme.txt",
    "chars": 139,
    "preview": "Example 1\n=========\n\nClose to the simplest possible example of Unity, using only basic features.\nRun make to build & run"
  },
  {
    "path": "tests/unity/examples/example_1/src/ProductionCode.c",
    "chars": 862,
    "preview": "\n#include \"ProductionCode.h\"\n\nint Counter = 0;\nint NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obn"
  },
  {
    "path": "tests/unity/examples/example_1/src/ProductionCode.h",
    "chars": 96,
    "preview": "\nint FindFunction_WhichIsBroken(int NumberToFind);\nint FunctionWhichReturnsLocalVariable(void);\n"
  },
  {
    "path": "tests/unity/examples/example_1/src/ProductionCode2.c",
    "chars": 335,
    "preview": "\n#include \"ProductionCode2.h\"\n\nchar* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction)\n{\n  (void)Poor;\n  (voi"
  },
  {
    "path": "tests/unity/examples/example_1/src/ProductionCode2.h",
    "chars": 69,
    "preview": "\nchar* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction);\n"
  },
  {
    "path": "tests/unity/examples/example_2/makefile",
    "chars": 1768,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/examples/example_2/readme.txt",
    "chars": 175,
    "preview": "Example 2\n=========\n\nSame as the first example, but now using Unity's test fixture to group tests\ntogether. Using the te"
  },
  {
    "path": "tests/unity/examples/example_2/src/ProductionCode.c",
    "chars": 847,
    "preview": "\n#include \"ProductionCode.h\"\n\nint Counter = 0;\nint NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obno"
  },
  {
    "path": "tests/unity/examples/example_2/src/ProductionCode.h",
    "chars": 96,
    "preview": "\nint FindFunction_WhichIsBroken(int NumberToFind);\nint FunctionWhichReturnsLocalVariable(void);\n"
  },
  {
    "path": "tests/unity/examples/example_2/src/ProductionCode2.c",
    "chars": 331,
    "preview": "\n#include \"ProductionCode2.h\"\n\nchar* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction)\n{\n  (void)Poor;\n  (voi"
  },
  {
    "path": "tests/unity/examples/example_2/src/ProductionCode2.h",
    "chars": 69,
    "preview": "\nchar* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction);\n"
  },
  {
    "path": "tests/unity/examples/example_3/helper/UnityHelper.c",
    "chars": 405,
    "preview": "#include \"unity.h\"\n#include \"UnityHelper.h\"\n#include <stdio.h>\n#include <string.h>\n\nvoid AssertEqualExampleStruct(const "
  },
  {
    "path": "tests/unity/examples/example_3/helper/UnityHelper.h",
    "chars": 483,
    "preview": "#ifndef _TESTHELPER_H\n#define _TESTHELPER_H\n\n#include \"Types.h\"\n\nvoid AssertEqualExampleStruct(const EXAMPLE_STRUCT_T ex"
  },
  {
    "path": "tests/unity/examples/example_3/rakefile.rb",
    "chars": 884,
    "preview": "HERE = File.expand_path(File.dirname(__FILE__)) + '/'\nUNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/../..'\n\n"
  },
  {
    "path": "tests/unity/examples/example_3/rakefile_helper.rb",
    "chars": 8367,
    "preview": "require 'yaml'\nrequire 'fileutils'\nrequire UNITY_ROOT + '/auto/unity_test_summary'\nrequire UNITY_ROOT + '/auto/generate_"
  },
  {
    "path": "tests/unity/examples/example_3/readme.txt",
    "chars": 696,
    "preview": "Example 3\n=========\n\nThis example project gives an example of some passing, ignored, and failing tests.\nIt's simple and "
  },
  {
    "path": "tests/unity/examples/example_3/src/ProductionCode.c",
    "chars": 847,
    "preview": "\n#include \"ProductionCode.h\"\n\nint Counter = 0;\nint NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obno"
  },
  {
    "path": "tests/unity/examples/example_3/src/ProductionCode.h",
    "chars": 96,
    "preview": "\nint FindFunction_WhichIsBroken(int NumberToFind);\nint FunctionWhichReturnsLocalVariable(void);\n"
  },
  {
    "path": "tests/unity/examples/example_3/src/ProductionCode2.c",
    "chars": 331,
    "preview": "\n#include \"ProductionCode2.h\"\n\nchar* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction)\n{\n  (void)Poor;\n  (voi"
  },
  {
    "path": "tests/unity/examples/example_3/src/ProductionCode2.h",
    "chars": 69,
    "preview": "\nchar* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction);\n"
  },
  {
    "path": "tests/unity/examples/example_3/target_gcc_32.yml",
    "chars": 852,
    "preview": "# Copied from ~Unity/targets/gcc_32.yml\nunity_root:  &unity_root '../..'\ncompiler:\n  path: gcc\n  source_path:     'src/'"
  },
  {
    "path": "tests/unity/examples/unity_config.h",
    "chars": 12322,
    "preview": "/* Unity Configuration\n * As of May 11th, 2016 at ThrowTheSwitch/Unity commit 837c529\n * Update: December 29th, 2016\n * "
  },
  {
    "path": "tests/unity/extras/eclipse/error_parsers.txt",
    "chars": 1139,
    "preview": "Eclipse error parsers\n=====================\n\nThese are a godsend for extracting  & quickly navigating to\nwarnings & erro"
  },
  {
    "path": "tests/unity/extras/fixture/rakefile.rb",
    "chars": 1109,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/extras/fixture/rakefile_helper.rb",
    "chars": 6621,
    "preview": "# ==========================================\n#   Unity Project - A Test Framework for C\n#   Copyright (c) 2007 Mike Karl"
  },
  {
    "path": "tests/unity/extras/fixture/readme.txt",
    "chars": 515,
    "preview": "Copyright (c) 2010 James Grenning and Contributed to Unity Project\n\nUnity Project - A Test Framework for C\nCopyright (c)"
  },
  {
    "path": "tests/unity/extras/fixture/src/unity_fixture.c",
    "chars": 10386,
    "preview": "/* Copyright (c) 2010 James Grenning and Contributed to Unity Project\n * ==========================================\n *  "
  },
  {
    "path": "tests/unity/extras/fixture/src/unity_fixture.h",
    "chars": 3348,
    "preview": "/* Copyright (c) 2010 James Grenning and Contributed to Unity Project\n * ==========================================\n *  "
  },
  {
    "path": "tests/unity/extras/fixture/src/unity_fixture_internals.h",
    "chars": 1518,
    "preview": "/* Copyright (c) 2010 James Grenning and Contributed to Unity Project\n * ==========================================\n *  "
  },
  {
    "path": "tests/unity/extras/fixture/src/unity_fixture_malloc_overrides.h",
    "chars": 1892,
    "preview": "/* Copyright (c) 2010 James Grenning and Contributed to Unity Project\n * ==========================================\n *  "
  },
  {
    "path": "tests/unity/release/build.info",
    "chars": 5,
    "preview": "122\n\n"
  },
  {
    "path": "tests/unity/release/version.info",
    "chars": 7,
    "preview": "2.4.3\n\n"
  },
  {
    "path": "tests/unity/src/unity.c",
    "chars": 49463,
    "preview": "/* =========================================================================\n    Unity Project - A Test Framework for C\n"
  },
  {
    "path": "tests/unity/src/unity.h",
    "chars": 66485,
    "preview": "/* ==========================================\n    Unity Project - A Test Framework for C\n    Copyright (c) 2007-14 Mike "
  },
  {
    "path": "tests/unity/src/unity_internals.h",
    "chars": 69552,
    "preview": "/* ==========================================\n    Unity Project - A Test Framework for C\n    Copyright (c) 2007-14 Mike "
  },
  {
    "path": "tests/unity_setup.c",
    "chars": 121,
    "preview": "// msvc doesn't support weak-linking, so we need to define these functions.\nvoid setUp(void) { }\nvoid tearDown(void) { }"
  },
  {
    "path": "valgrind.supp",
    "chars": 61,
    "preview": "{\n\tsuppress_ld_on_armv7\n\tMemcheck:Cond\n\t...\n\tobj:*/ld-*.so\n}\n"
  }
]

About this extraction

This page contains the full source code of the DaveGamble/cJSON GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 160 files (820.0 KB), approximately 209.1k tokens, and a symbol index with 615 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!