mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-03 05:36:42 +02:00
Compare commits
134 Commits
Author | SHA1 | Date | |
---|---|---|---|
46bd98fd10 | |||
63c89f166d | |||
8340b36170 | |||
ad4b13c8f0 | |||
f20f8e3171 | |||
5c297ba4a2 | |||
f483b06735 | |||
a0011ba7f8 | |||
ae2bfee0b1 | |||
b171872b58 | |||
0d01e84336 | |||
0685a36f0e | |||
ef12c74771 | |||
0bc03e8071 | |||
04286f3228 | |||
0d4a93018b | |||
3ca40db9f8 | |||
ce607196d1 | |||
0b3af166ae | |||
fa1a40ac6e | |||
954428e341 | |||
7b229e4c38 | |||
9ac9b533b6 | |||
011aac43d2 | |||
eb20ae6a3f | |||
7c0af91844 | |||
3523296e3d | |||
689ae5c08d | |||
d9b1e7e810 | |||
b4eece01f8 | |||
cf5396aaed | |||
e390587e91 | |||
bae179ed67 | |||
7e4fcb0868 | |||
fbfdca1de9 | |||
0612eef69b | |||
ae0b7a3ebd | |||
e92612b511 | |||
5c33fd4b94 | |||
c3f51e2980 | |||
de47c0af9e | |||
e53e4e3dd9 | |||
36fe6535c4 | |||
b55e57a7cf | |||
7626db624e | |||
6d8329b255 | |||
461e30148c | |||
57d98e48f7 | |||
cf2babc598 | |||
d10277df31 | |||
d3a1203782 | |||
126f7ab819 | |||
221c2861fc | |||
66667382e1 | |||
a7e928d126 | |||
591fe7e92b | |||
d6e61cbcda | |||
5825366fe4 | |||
6df204cf40 | |||
3f7e1db549 | |||
a6091136b0 | |||
353bbd0e8c | |||
a428e125fa | |||
2e262b2689 | |||
a2d055e408 | |||
57defe00ee | |||
ac5a2676e7 | |||
ed98ea4e43 | |||
729bf0afd2 | |||
2ea7ea153c | |||
2772e66064 | |||
d41f7a8165 | |||
abfd3997eb | |||
788c9be016 | |||
c3d7a79a83 | |||
1782348275 | |||
edfe5c6622 | |||
2b9492317b | |||
5da41edf6a | |||
476e5aaa86 | |||
789fa507b5 | |||
508f936317 | |||
e9d88dda8e | |||
ecceb71a1e | |||
bff77abe6a | |||
98413089f6 | |||
a2446f6c68 | |||
c955049207 | |||
574c00c096 | |||
7415f206ea | |||
f76017a015 | |||
cda05aec04 | |||
639286f8b6 | |||
cc66618e70 | |||
9efc0ec40d | |||
34674fc282 | |||
01c3166043 | |||
bf2e3d5669 | |||
4e9f0b2e2e | |||
223f14710d | |||
f7ae91b85d | |||
445dff499b | |||
9afa05e2f4 | |||
c3e1677b7d | |||
024976cda2 | |||
df541a2a22 | |||
f2ef338cb8 | |||
8c6f64c111 | |||
5a16b2117b | |||
71edcaf20f | |||
ac89d91db5 | |||
e664c1ab05 | |||
adba668109 | |||
ad972725de | |||
185eccf6f5 | |||
c4567bac18 | |||
13409c433a | |||
20431debe0 | |||
797ea356ef | |||
2321473c34 | |||
0d5f65c5f3 | |||
c30241775a | |||
31827d03f9 | |||
7bcdf3e722 | |||
db9a76f7c6 | |||
3fd87e8e82 | |||
22a2786610 | |||
2b5a6df1e1 | |||
5fefeae404 | |||
d4f725d1fa | |||
a096098c1f | |||
cc8c0472ca | |||
fb554071dc | |||
17a17c8957 |
19
.github/ISSUE_TEMPLATE.md
vendored
19
.github/ISSUE_TEMPLATE.md
vendored
@ -1,11 +1,14 @@
|
||||
<!--
|
||||
Thanks for using ArduinoJson :-)
|
||||
Before opening an issue, please read the FAQ:
|
||||
https://arduinojson.org/faq/
|
||||
|
||||
Before opening an issue, please make sure you've read these:
|
||||
https://github.com/bblanchon/ArduinoJson/wiki/FAQ
|
||||
https://github.com/bblanchon/ArduinoJson/wiki/Avoiding-pitfalls
|
||||
Please provide all the relevant information:
|
||||
* good title
|
||||
* short description of the problem
|
||||
* target platform
|
||||
* compiler model and version
|
||||
* MVCE (https://stackoverflow.com/help/mcve)
|
||||
* compiler output
|
||||
|
||||
Next, make sure you provide all the relevant information: platform, code snippet, and error messages.
|
||||
|
||||
Please be concise!
|
||||
-->
|
||||
Good questions get fast answers!
|
||||
-->
|
||||
|
@ -1,5 +1,6 @@
|
||||
.github/
|
||||
examples/
|
||||
fuzzing/
|
||||
scripts/
|
||||
test/
|
||||
third-party/
|
||||
|
104
.travis.yml
104
.travis.yml
@ -7,103 +7,127 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.4']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.4
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.5']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.5
|
||||
env: SCRIPT=cmake GCC=4.4
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.6']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.6
|
||||
env: SCRIPT=cmake GCC=4.6
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.7']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.7
|
||||
env: SCRIPT=cmake GCC=4.7
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.8']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.8
|
||||
env: SCRIPT=cmake GCC=4.8 SANITIZE=address
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.9']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.9
|
||||
env: SCRIPT=cmake GCC=4.9 SANITIZE=leak
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-5
|
||||
env: SCRIPT=cmake GCC=5
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-6']
|
||||
env: SCRIPT=cmake GCC=6
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-7']
|
||||
env: SCRIPT=cmake GCC=7
|
||||
- compiler: clang
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++
|
||||
env: SCRIPT=cmake
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5']
|
||||
packages: ['clang-3.5']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.5
|
||||
env: SCRIPT=cmake CLANG=3.5 SANITIZE=address
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.6']
|
||||
packages: ['clang-3.6']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.6
|
||||
env: SCRIPT=cmake CLANG=3.6 SANITIZE=leak
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.7']
|
||||
packages: ['clang-3.7']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.7
|
||||
env: SCRIPT=cmake CLANG=3.7
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
|
||||
packages: ['clang-3.8']
|
||||
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.8
|
||||
env: SCRIPT=cmake CLANG=3.8 SANITIZE=undefined
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
|
||||
packages: ['clang-3.8']
|
||||
env: SCRIPT=sanitize CMAKE_CXX_COMPILER=clang++-3.8
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-3.9']
|
||||
packages: ['clang-3.9']
|
||||
env: SCRIPT=cmake CLANG=3.9
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-4.0']
|
||||
packages: ['clang-4.0']
|
||||
env: SCRIPT=cmake CLANG=4.0
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-5.0']
|
||||
packages: ['clang-5.0']
|
||||
env: SCRIPT=cmake CLANG=5.0
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
|
||||
packages: ['clang-6.0']
|
||||
env: SCRIPT=cmake CLANG=6.0
|
||||
- compiler: gcc
|
||||
env: SCRIPT=coverage
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake-osx
|
||||
- os: osx
|
||||
osx_image: xcode7
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake-osx
|
||||
- os: osx
|
||||
osx_image: xcode7.1
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake-osx
|
||||
- os: osx
|
||||
osx_image: xcode7.2
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake-osx
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake-osx
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode10
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake SANITIZE=address
|
||||
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=arduino VERSION=1.6.12 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=platformio BOARD=uno
|
||||
- env: SCRIPT=platformio BOARD=due
|
||||
- env: SCRIPT=platformio BOARD=esp01
|
||||
- env: SCRIPT=platformio BOARD=teensy31
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
|
||||
packages: ['clang-6.0','llvm-6.0']
|
||||
env: SCRIPT=fuzz CLANG=6.0
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
|
@ -1,8 +1,5 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include "include/ArduinoJson.h"
|
||||
#include "src/ArduinoJson.h"
|
||||
|
386
CHANGELOG.md
386
CHANGELOG.md
@ -1,6 +1,190 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
HEAD
|
||||
----
|
||||
|
||||
* `JsonObject::createNestedObject()` returns `JsonObject::invalid()` if key is null (issue #1891)
|
||||
* `JsonObject::createNestedArray()` returns `JsonArray::invalid()` if key is null
|
||||
|
||||
v5.13.5
|
||||
-------
|
||||
|
||||
* Fixed warning "unused variable" with GCC 4.4 (issue #912)
|
||||
* Fixed warning "maybe uninitialized" (issue #909)
|
||||
* Added an clear message for `StaticJsonDocument`, `DynamicJsonDocument`...
|
||||
|
||||
v5.13.4
|
||||
-------
|
||||
|
||||
* Removed spurious files in the Particle library
|
||||
|
||||
v5.13.3
|
||||
-------
|
||||
|
||||
* Improved float serialization when `-fsingle-precision-constant` is used
|
||||
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
|
||||
* Fixed `JsonVariant::is<String>()` (closes #763)
|
||||
|
||||
v5.13.2
|
||||
-------
|
||||
|
||||
* Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693)
|
||||
* Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu)
|
||||
* Fixed null values that could be pass to `strcmp()` (PR #745 from Mike Karlesky)
|
||||
* Added macros `ARDUINOJSON_VERSION`, `ARDUINOJSON_VERSION_MAJOR`...
|
||||
|
||||
v5.13.1
|
||||
-------
|
||||
|
||||
* Fixed `JsonVariant::operator|(int)` that returned the default value if the variant contained a double (issue #675)
|
||||
* Allowed non-quoted key to contain underscores (issue #665)
|
||||
|
||||
v5.13.0
|
||||
-------
|
||||
|
||||
* Changed the rules of string duplication (issue #658)
|
||||
* `RawJson()` accepts any kind of string and obeys to the same rules for duplication
|
||||
* Changed the return type of `strdup()` to `const char*` to prevent double duplication
|
||||
* Marked `strdup()` as deprecated
|
||||
|
||||
> ### New rules for string duplication
|
||||
>
|
||||
> | type | duplication |
|
||||
> |:---------------------------|:------------|
|
||||
> | const char* | no |
|
||||
> | char* | ~~no~~ yes |
|
||||
> | String | yes |
|
||||
> | std::string | yes |
|
||||
> | const __FlashStringHelper* | yes |
|
||||
>
|
||||
> These new rules make `JsonBuffer::strdup()` useless.
|
||||
|
||||
v5.12.0
|
||||
-------
|
||||
|
||||
* Added `JsonVariant::operator|` to return a default value (see below)
|
||||
* Added a clear error message when compiled as C instead of C++ (issue #629)
|
||||
* Added detection of MPLAB XC compiler (issue #629)
|
||||
* Added detection of Keil ARM Compiler (issue #629)
|
||||
* Added an example that shows how to save and load a configuration file
|
||||
* Reworked all other examples
|
||||
|
||||
> ### How to use the new feature?
|
||||
>
|
||||
> If you have a block like this:
|
||||
>
|
||||
> ```c++
|
||||
> const char* ssid = root["ssid"];
|
||||
> if (!ssid)
|
||||
> ssid = "default ssid";
|
||||
> ```
|
||||
>
|
||||
> You can simplify like that:
|
||||
>
|
||||
> ```c++
|
||||
> const char* ssid = root["ssid"] | "default ssid";
|
||||
> ```
|
||||
|
||||
v5.11.2
|
||||
-------
|
||||
|
||||
* Fixed `DynamicJsonBuffer::clear()` not resetting allocation size (issue #561)
|
||||
* Fixed incorrect rounding for float values (issue #588)
|
||||
|
||||
v5.11.1
|
||||
-------
|
||||
|
||||
* Removed dependency on `PGM_P` as Particle 0.6.2 doesn't define it (issue #546)
|
||||
* Fixed warning "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]"
|
||||
* Fixed warning "floating constant exceeds range of 'float' [-Woverflow]" (issue #544)
|
||||
* Fixed warning "this statement may fall through" [-Wimplicit-fallthrough=] (issue #539)
|
||||
* Removed `ARDUINOJSON_DOUBLE_IS_64BITS` as it became useless.
|
||||
* Fixed too many decimals places in float serialization (issue #543)
|
||||
|
||||
v5.11.0
|
||||
-------
|
||||
|
||||
* Made `JsonBuffer` non-copyable (PR #524 by @luisrayas3)
|
||||
* Added `StaticJsonBuffer::clear()`
|
||||
* Added `DynamicJsonBuffer::clear()`
|
||||
|
||||
v5.10.1
|
||||
-------
|
||||
|
||||
* Fixed IntelliSense errors in Visual Micro (issue #483)
|
||||
* Fixed compilation in IAR Embedded Workbench (issue #515)
|
||||
* Fixed reading "true" as a float (issue #516)
|
||||
* Added `ARDUINOJSON_DOUBLE_IS_64BITS`
|
||||
* Added `ARDUINOJSON_EMBEDDED_MODE`
|
||||
|
||||
v5.10.0
|
||||
-------
|
||||
|
||||
* Removed configurable number of decimal places (issues #288, #427 and #506)
|
||||
* Changed exponentiation thresholds to `1e7` and `1e-5` (issues #288, #427 and #506)
|
||||
* `JsonVariant::is<double>()` now returns `true` for integers
|
||||
* Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495)
|
||||
* Fixed error `forming reference to reference` (issue #495)
|
||||
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> | Old syntax | New syntax |
|
||||
> |:--------------------------------|:--------------------|
|
||||
> | `double_with_n_digits(3.14, 2)` | `3.14` |
|
||||
> | `float_with_n_digits(3.14, 2)` | `3.14f` |
|
||||
> | `obj.set("key", 3.14, 2)` | `obj["key"] = 3.14` |
|
||||
> | `arr.add(3.14, 2)` | `arr.add(3.14)` |
|
||||
>
|
||||
> | Input | Old output | New output |
|
||||
> |:----------|:-----------|:-----------|
|
||||
> | `3.14159` | `3.14` | `3.14159` |
|
||||
> | `42.0` | `42.00` | `42` |
|
||||
> | `0.0` | `0.00` | `0` |
|
||||
>
|
||||
> | Expression | Old result | New result |
|
||||
> |:-------------------------------|:-----------|:-----------|
|
||||
> | `JsonVariant(42).is<int>()` | `true` | `true` |
|
||||
> | `JsonVariant(42).is<float>()` | `false` | `true` |
|
||||
> | `JsonVariant(42).is<double>()` | `false` | `true` |
|
||||
|
||||
v5.9.0
|
||||
------
|
||||
|
||||
* Added `JsonArray::remove(iterator)` (issue #479)
|
||||
* Added `JsonObject::remove(iterator)`
|
||||
* Renamed `JsonArray::removeAt(size_t)` into `remove(size_t)`
|
||||
* Renamed folder `include/` to `src/`
|
||||
* Fixed warnings `floating constant exceeds range of float`and `floating constant truncated to zero` (issue #483)
|
||||
* Removed `Print` class and converted `printTo()` to a template method (issue #276)
|
||||
* Removed example `IndentedPrintExample.ino`
|
||||
* Now compatible with Particle 0.6.1, thanks to Jacob Nite (issue #294 and PR #461 by @foodbag)
|
||||
|
||||
v5.8.4
|
||||
------
|
||||
|
||||
* Added custom implementation of `strtod()` (issue #453)
|
||||
* Added custom implementation of `strtol()` (issue #465)
|
||||
* `char` is now treated as an integral type (issue #337, #370)
|
||||
|
||||
v5.8.3
|
||||
------
|
||||
|
||||
* Fixed an access violation in `DynamicJsonBuffer` when memory allocation fails (issue #433)
|
||||
* Added operators `==` and `!=` for two `JsonVariant`s (issue #436)
|
||||
* Fixed `JsonVariant::operator[const FlashStringHelper*]` (issue #441)
|
||||
|
||||
v5.8.2
|
||||
------
|
||||
|
||||
* Fixed parsing of comments (issue #421)
|
||||
* Fixed ignored `Stream` timeout (issue #422)
|
||||
* Made sure we don't read more that necessary (issue #422)
|
||||
* Fixed error when the key of a `JsonObject` is a `char[]` (issue #423)
|
||||
* Reduced code size when using `const` references
|
||||
* Fixed error with string of type `unsigned char*` (issue #428)
|
||||
* Added `deprecated` attribute on `asArray()`, `asObject()` and `asString()` (issue #420)
|
||||
|
||||
v5.8.1
|
||||
------
|
||||
|
||||
@ -16,23 +200,23 @@ v5.8.0
|
||||
* Added support for `Stream` (issue #300)
|
||||
* Reduced memory consumption by not duplicating spaces and comments
|
||||
|
||||
**BREAKING CHANGES**:
|
||||
|
||||
`JsonBuffer::parseObject()` and `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`.
|
||||
|
||||
This means that if you have code like:
|
||||
|
||||
```c++
|
||||
void myFunction(JsonBuffer& jsonBuffer);
|
||||
```
|
||||
|
||||
you need to replace it with one of the following:
|
||||
|
||||
```c++
|
||||
void myFunction(DynamicJsonBuffer& jsonBuffer);
|
||||
void myFunction(StaticJsonBufferBase& jsonBuffer);
|
||||
template<typename TJsonBuffer> void myFunction(TJsonBuffer& jsonBuffer);
|
||||
```
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> `JsonBuffer::parseObject()` and `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`.
|
||||
>
|
||||
> This means that if you have code like:
|
||||
>
|
||||
> ```c++
|
||||
> void myFunction(JsonBuffer& jsonBuffer);
|
||||
> ```
|
||||
>
|
||||
> you need to replace it with one of the following:
|
||||
>
|
||||
> ```c++
|
||||
> void myFunction(DynamicJsonBuffer& jsonBuffer);
|
||||
> void myFunction(StaticJsonBufferBase& jsonBuffer);
|
||||
> template<typename TJsonBuffer> void myFunction(TJsonBuffer& jsonBuffer);
|
||||
> ```
|
||||
|
||||
v5.7.3
|
||||
------
|
||||
@ -65,27 +249,26 @@ v5.7.0
|
||||
* Added example `StringExample.ino` to show where `String` can be used
|
||||
* Increased default nesting limit to 50 when compiled for a computer (issue #349)
|
||||
|
||||
**BREAKING CHANGES**:
|
||||
|
||||
The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return.
|
||||
|
||||
Old code:
|
||||
|
||||
```c++
|
||||
#define ARDUINOJSON_USE_ARDUINO_STRING 0
|
||||
JsonVariant value1 = myObject.get("myKey");
|
||||
JsonVariant value2 = myArray.get(0);
|
||||
```
|
||||
|
||||
New code:
|
||||
|
||||
```c++
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||
#define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||
JsonVariant value1 = myObject.get<JsonVariant>("myKey");
|
||||
JsonVariant value2 = myArray.get<JsonVariant>(0);
|
||||
```
|
||||
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return.
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> #define ARDUINOJSON_USE_ARDUINO_STRING 0
|
||||
> JsonVariant value1 = myObject.get("myKey");
|
||||
> JsonVariant value2 = myArray.get(0);
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||
> #define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||
> JsonVariant value1 = myObject.get<JsonVariant>("myKey");
|
||||
> JsonVariant value2 = myArray.get<JsonVariant>(0);
|
||||
> ```
|
||||
|
||||
v5.6.7
|
||||
------
|
||||
@ -177,8 +360,9 @@ v5.1.0
|
||||
* Added support of `long long` (issue #171)
|
||||
* Moved all build settings to `ArduinoJson/Configuration.hpp`
|
||||
|
||||
**BREAKING CHANGE**:
|
||||
If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`.
|
||||
> ### BREAKING CHANGE :warning:
|
||||
>
|
||||
> If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`.
|
||||
|
||||
v5.0.8
|
||||
------
|
||||
@ -192,9 +376,10 @@ v5.0.7
|
||||
* Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)`
|
||||
* Changed `String` to be a `typedef` of `std::string` (issues #142 and #161)
|
||||
|
||||
**BREAKING CHANGES**:
|
||||
- `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"`
|
||||
- `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"`
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> - `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"`
|
||||
> - `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"`
|
||||
|
||||
v5.0.6
|
||||
------
|
||||
@ -248,10 +433,11 @@ v5.0.0
|
||||
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66)
|
||||
* Switched to new the library layout (requires Arduino 1.0.6 or above)
|
||||
|
||||
**BREAKING CHANGES**:
|
||||
- `JsonObject::add()` was renamed to `set()`
|
||||
- `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
|
||||
- Number of digits of floating point value are now set with `double_with_n_digits()`
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> - `JsonObject::add()` was renamed to `set()`
|
||||
> - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
|
||||
> - Number of digits of floating point value are now set with `double_with_n_digits()`
|
||||
|
||||
**Personal note about the `String` class**:
|
||||
Support of the `String` class has been added to the library because many people use it in their programs.
|
||||
@ -304,106 +490,6 @@ v4.0
|
||||
* Unified parser and generator API (issue #23)
|
||||
* Updated library layout, now requires Arduino 1.0.6 or newer
|
||||
|
||||
**BREAKING CHANGE**: API changed significantly, see [Migrating code to the new API](https://github.com/bblanchon/ArduinoJson/wiki/Migrating-code-to-the-new-API).
|
||||
|
||||
|
||||
v3.4
|
||||
----
|
||||
|
||||
* Fixed escaped char parsing (issue #16)
|
||||
|
||||
|
||||
v3.3
|
||||
----
|
||||
|
||||
* Added indented output for the JSON generator (issue #11), see example bellow.
|
||||
* Added `IndentedPrint`, a decorator for `Print` to allow indented output
|
||||
|
||||
Example:
|
||||
|
||||
JsonOject<2> json;
|
||||
json["key"] = "value";
|
||||
json.prettyPrintTo(Serial);
|
||||
|
||||
v3.2
|
||||
----
|
||||
|
||||
* Fixed a bug when adding nested object in `JsonArray` (bug introduced in v3.1).
|
||||
|
||||
v3.1
|
||||
----
|
||||
|
||||
* Calling `Generator::JsonObject::add()` twice with the same `key` now replaces the `value`
|
||||
* Added `Generator::JsonObject::operator[]`, see bellow the new API
|
||||
* Added `Generator::JsonObject::remove()` (issue #9)
|
||||
|
||||
Old generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
root.add("sensor", "gps");
|
||||
root.add("time", 1351824120);
|
||||
root.add("data", array);
|
||||
|
||||
New generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
root["data"] = array;
|
||||
|
||||
v3.0
|
||||
----
|
||||
|
||||
* New parser API, see bellow
|
||||
* Renamed `JsonHashTable` into `JsonObject`
|
||||
* Added iterators for `JsonArray` and `JsonObject` (issue #4)
|
||||
|
||||
Old parser API:
|
||||
|
||||
JsonHashTable root = parser.parseHashTable(json);
|
||||
|
||||
char* sensor = root.getString("sensor");
|
||||
long time = root.getLong("time");
|
||||
double latitude = root.getArray("data").getDouble(0);
|
||||
double longitude = root.getArray("data").getDouble(1);
|
||||
|
||||
New parser API:
|
||||
|
||||
JsonObject root = parser.parse(json);
|
||||
|
||||
char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
v2.1
|
||||
----
|
||||
|
||||
* Fixed case `#include "jsmn.cpp"` which caused an error in Linux (issue #6)
|
||||
* Fixed a buffer overrun in JSON Parser (issue #5)
|
||||
|
||||
v2.0
|
||||
----
|
||||
|
||||
* Added JSON encoding (issue #2)
|
||||
* Renamed the library `ArduinoJsonParser` becomes `ArduinoJson`
|
||||
|
||||
**Breaking change**: you need to add the following line at the top of your program.
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
v1.2
|
||||
----
|
||||
|
||||
* Fixed error in JSON parser example (issue #1)
|
||||
|
||||
v1.1
|
||||
----
|
||||
|
||||
* Example: changed `char* json` into `char[] json` so that the bytes are not write protected
|
||||
* Fixed parsing bug when the JSON contains multi-dimensional arrays
|
||||
|
||||
v1.0
|
||||
----
|
||||
|
||||
Initial release
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> API changed significantly since v3, see [Migrating code to the new API](https://arduinojson.org/doc/migration/).
|
||||
|
@ -1,25 +1,16 @@
|
||||
# Copyright Benoit Blanchon 2014-2017
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
#
|
||||
# Arduino JSON library
|
||||
# https://github.com/bblanchon/ArduinoJson
|
||||
# If you like this project, please add a star!
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(ArduinoJson)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
if(${SANITIZE})
|
||||
set(CMAKE_CXX_FLAGS "-fsanitize=address,undefined")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
add_subdirectory(third-party/catch)
|
||||
add_subdirectory(test)
|
||||
|
11
CONTRIBUTING.md
Normal file
11
CONTRIBUTING.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Contribution to ArduinoJson
|
||||
|
||||
First, thank you for taking the time to contribute to this project.
|
||||
|
||||
You can submit changes via GitHub Pull Requests.
|
||||
|
||||
Please:
|
||||
|
||||
1. Unit test every change in behavior
|
||||
2. Use clang-format in "file" mode to format the code
|
||||
3. Consider using the Continuous Integration (Travis and AppVeyor)
|
@ -1,7 +1,7 @@
|
||||
The MIT License (MIT)
|
||||
---------------------
|
||||
|
||||
Copyright © 2014-2017 Benoit BLANCHON
|
||||
Copyright © 2014-2019 Benoit BLANCHON
|
||||
|
||||
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:
|
||||
|
||||
|
149
README.md
149
README.md
@ -1,47 +1,64 @@
|
||||
Arduino JSON library
|
||||
====================
|
||||

|
||||
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master) [](https://github.com/bblanchon/ArduinoJson)
|
||||
---
|
||||
|
||||
*An elegant and efficient JSON library for embedded systems.*
|
||||
[](https://www.ardu-badge.com/ArduinoJson/5.13.5)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master)
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
[](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
|
||||
[](https://github.com/bblanchon/ArduinoJson)
|
||||
|
||||
It's designed to have the most intuitive API, the smallest footprint and is able to work without any allocation on the heap (no malloc).
|
||||
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
|
||||
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
||||
For instance, it supports Aduino's `String` and `Stream`, but also `std::string`, `std::istream` and `std::ostream`.
|
||||
|
||||
Features
|
||||
--------
|
||||
## Features
|
||||
|
||||
* JSON decoding (comments are supported)
|
||||
* JSON encoding (with optional indentation)
|
||||
* Elegant API, very easy to use
|
||||
* Elegant API, easy to use
|
||||
* Fixed memory allocation (zero malloc)
|
||||
* No data duplication (zero copy)
|
||||
* Portable (written in C++98)
|
||||
* Portable (written in C++98, can be used in any C++ project)
|
||||
* Self-contained (no external dependency)
|
||||
* Small footprint
|
||||
* Header-only library
|
||||
* MIT License
|
||||
* Input and output streams
|
||||
* [100% code coverage](https://coveralls.io/github/bblanchon/ArduinoJson)
|
||||
* [Header-only library](https://en.wikipedia.org/wiki/Header-only)
|
||||
* [MIT License](https://en.wikipedia.org/wiki/MIT_License)
|
||||
* [Comprehensive documentation](https://arduinojson.org?utm_source=github&utm_medium=readme)
|
||||
|
||||
Works on
|
||||
--------
|
||||
## Compatibility
|
||||
|
||||
* All Arduino boards (Uno, Due, Mini, Micro, Yun...)
|
||||
* ESP8266
|
||||
* Teensy
|
||||
* Intel Edison and Galileo
|
||||
* PlatformIO
|
||||
* Energia
|
||||
* RedBearLab boards (BLE Nano...)
|
||||
* Computers (Windows, Linux, OSX...)
|
||||
ArduinoJson works on the following hardware:
|
||||
|
||||
See [FAQ: Compatibility issues](https://github.com/bblanchon/ArduinoJson/wiki/Compatibility-issues)
|
||||
* <img src="https://www.arduino.cc/favicon.ico" height="16" width="16"> Arduino boards: [Uno](https://www.arduino.cc/en/Main/ArduinoBoardUno), [Due](https://www.arduino.cc/en/Main/ArduinoBoardDue), [Mini](https://www.arduino.cc/en/Main/ArduinoBoardMini), [Micro](https://www.arduino.cc/en/Main/ArduinoBoardMicro), [Yun](https://www.arduino.cc/en/Main/ArduinoBoardYun)...
|
||||
* <img src="http://espressif.com/sites/all/themes/espressif/favicon.ico" height="16" width="16"> Espressif chips: [ESP8266](https://en.wikipedia.org/wiki/ESP8266), [ESP32](https://en.wikipedia.org/wiki/ESP32)
|
||||
* <img src="https://www.wemos.cc/themes/martin-materialize-parallax/assets/favicon.ico" height="16" width="16"> WeMos boards: [D1](https://wiki.wemos.cc/products:d1:d1), [D1 mini](https://wiki.wemos.cc/products:d1:d1_mini), ...
|
||||
* <img src="http://redbearlab.com/favicon.ico" height="16" width="16"> RedBearLab boards: [BLE Nano](http://redbearlab.com/blenano/), [BLE Mini](http://redbearlab.com/blemini/), [WiFi Micro](https://redbear.cc/product/wifi/wifi-micro.html), [LOLIN32](https://wiki.wemos.cc/products:lolin32:lolin32)...
|
||||
* <img src="https://www.pjrc.com/favicon.ico" height="16" width="16"> [Teensy](https://www.pjrc.com/teensy/) boards
|
||||
* <img src="https://software.intel.com/sites/all/themes/zero/favicon.ico" height="16" width="16"> Intel boards: Edison, Galileo...
|
||||
* <img src="https://www-assets.particle.io/images/favicon.png" height="16" width="16"> Particle boards: [Photon](https://www.particle.io/products/hardware/photon-wifi-dev-kit), [Electron](https://www.particle.io/products/hardware/electron-cellular-dev-kit)...
|
||||
* <img src="http://www.ti.com/favicon.ico" height="16" width="16"> Texas Instruments boards: [MSP430](http://www.ti.com/microcontrollers/msp430-ultra-low-power-mcus/overview/overview.html)...
|
||||
|
||||
Quick start
|
||||
-----------
|
||||
ArduinoJson compiles with zero warning on the following compilers, IDEs, and platforms:
|
||||
|
||||
#### Decoding / Parsing
|
||||
* <img src="https://www.arduino.cc/favicon.ico" height="16" width="16"> [Arduino IDE](https://www.arduino.cc/en/Main/Software)
|
||||
* <img src="http://cdn.platformio.org/favicon.ico" height="16" width="16"> [PlatformIO](http://platformio.org/)
|
||||
* <img src="http://energia.nu/img/favicon.ico" height="16" width="16"> [Energia](http://energia.nu/)
|
||||
* <img src="http://www.visualmicro.com/pics/arduino-visual-studio-ld.png" height="16" width="16"> [Visual Micro](http://www.visualmicro.com/)
|
||||
* <img src="http://www.atmel.com/Images/favicon.ico" height="16" width="16"> [Atmel Studio](http://www.atmel.com/microsite/atmel-studio/)
|
||||
* <img src="https://www.iar.com/favicon.ico" height="16" width="16"> [IAR Embedded Workbench](https://www.iar.com/iar-embedded-workbench/)
|
||||
* <img src="http://www.st.com/etc/clientlibs/st-site/media/app/images/favicon.png" height="16" width="16"> [Atollic TrueSTUDIO](https://atollic.com/truestudio/)
|
||||
* <img src="http://www.keil.com/favicon.ico" height="16" width="16"> [Keil uVision](http://www.keil.com/)
|
||||
* <img src="http://www.microchip.com/favicon.ico" height="16" width="16"> [MPLAB X IDE](http://www.microchip.com/mplab/mplab-x-ide)
|
||||
* <img src="https://gcc.gnu.org/favicon.ico" height="16" width="16"> [GCC](https://gcc.gnu.org/)
|
||||
* <img src="https://clang.llvm.org/favicon.ico" height="16" width="16"> [Clang](https://clang.llvm.org/)
|
||||
* <img src="https://www.visualstudio.com/favicon.ico" height="16" width="16"> [Visual Studio](https://www.visualstudio.com/)
|
||||
|
||||
## Quickstart
|
||||
|
||||
### Deserialization
|
||||
|
||||
Here is a program that parses a JSON document with ArduinoJson.
|
||||
|
||||
```c++
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
@ -56,9 +73,11 @@ double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
```
|
||||
|
||||
[See JsonParserExample.ino](examples/JsonParserExample/JsonParserExample.ino)
|
||||
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme)
|
||||
|
||||
#### Encoding / Generating
|
||||
### Serialization
|
||||
|
||||
Here is a program that generates a JSON document with ArduinoJson:
|
||||
|
||||
```c++
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
@ -68,72 +87,28 @@ root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080, 6); // 6 is the number of decimals to print
|
||||
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
```
|
||||
|
||||
[See JsonGeneratorExample.ino](examples/JsonGeneratorExample/JsonGeneratorExample.ino)
|
||||
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme)
|
||||
|
||||
## Documentation
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
The documentation is available on [arduinojson.org](https://arduinojson.org/?utm_source=github&utm_medium=readme), here are some shortcuts:
|
||||
|
||||
The documentation is available online in the [Arduino JSON wiki](https://github.com/bblanchon/ArduinoJson/wiki)
|
||||
|
||||
Testimonials
|
||||
------------
|
||||
|
||||
From Arduino's Forum user `jflaplante`:
|
||||
> I tried aJson json-arduino before trying your library. I always ran into memory problem after a while.
|
||||
> I have no such problem so far with your library. It is working perfectly with my web services.
|
||||
|
||||
From StackOverflow user `thegreendroid`:
|
||||
> It has a really elegant, simple API and it works like a charm on embedded and Windows/Linux platforms. We recently started using this on an embedded project and I can vouch for its quality.
|
||||
|
||||
From GitHub user `zacsketches`:
|
||||
> Thanks for a great library!!!
|
||||
> I've been watching you consistently develop this library over the past six months, and I used it today for a publish and subscribe architecture designed to help hobbyists move into more advanced robotics. Your library allowed me to implement remote subscription in order to facilitate multi-processor robots.
|
||||
> ArduinoJson saved me a week's worth of time!!
|
||||
|
||||
[From Reddit user `erm_what_`](https://www.reddit.com/r/arduino/comments/3jj6ep/announcing_arduinojson_50/cusjk8c):
|
||||
> This is a great library and I wouldn't be able to do the project I'm doing without it. I completely recommend it.
|
||||
|
||||
[From Reddit user `makerhacks`](https://www.reddit.com/r/arduino/comments/3jj6ep/announcing_arduinojson_50/cusqg7b):
|
||||
> I am just starting an ESP8266 clock project and now I can output JSON from my server script and interpret it painlessly.
|
||||
|
||||
[From Twitter user `@hemalchevli`](https://twitter.com/hemalchevli/status/715788439397011456):
|
||||
> ArduinoJson library should be used as a benchmark/reference for making libraries. Truly elegant.
|
||||
|
||||
[From GitHub user `sticilface`](https://github.com/bblanchon/ArduinoJson/issues/381#issuecomment-260203594):
|
||||
> its a great lib:) and i use it in everything!
|
||||
|
||||
Donators
|
||||
--------
|
||||
|
||||
Special thanks to the following persons and companies who made generous donations to the library author:
|
||||
|
||||
* Robert Murphy <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Surge Communications <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Alex Scott <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'>
|
||||
* Firepick Services LLC <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* A B Doodkorte <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
* Scott Smith <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Johann Stieger <img alt='Austria' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e6-1f1f9.svg' width='18' height='18'>
|
||||
* Gustavo Donizeti Gini <img alt='Brazil' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e7-1f1f7.svg' width='18' height='18'>
|
||||
* Charles-Henri Hallard <img alt='France' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1eb-1f1f7.svg' width='18' height='18'>
|
||||
* Martijn van den Burg <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
* Nick Koumaris <img alt='Greece' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1f7.svg' width='18' height='18'>
|
||||
* Jon Williams <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Kestutis Liaugminas <img alt='Lithuania' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1f9.svg' width='18' height='18'>
|
||||
* Darlington Adibe <img alt='Nigeria' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1ec.svg' width='18' height='18'>
|
||||
* Yoeri Kroon <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
* Andrew Melvin <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'>
|
||||
* Doanh Luong <img alt ='Vietnam' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fb-1f1f3.svg' width='18' height='18'>
|
||||
* The [Examples](https://arduinojson.org/example/?utm_source=github&utm_medium=readme) show how to use the library in various situations.
|
||||
* The [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=readme) contains the description of each class and function.
|
||||
* The [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=readme) has the answer to virtually every question.
|
||||
* The [ArduinoJson Assistant](https://arduinojson.org/assistant/?utm_source=github&utm_medium=readme) writes programs for you!
|
||||
|
||||
---
|
||||
|
||||
Found this library useful? Please star this project or [help me back with a donation!](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile:
|
||||
Do you like this library? Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)!
|
||||
|
||||
What? You don't like it but you *love* it?
|
||||
We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time!
|
||||
|
27
SUPPORT.md
Normal file
27
SUPPORT.md
Normal file
@ -0,0 +1,27 @@
|
||||
# ArduinoJson Support
|
||||
|
||||
First off, thank you very much for using ArduinoJson.
|
||||
|
||||
We'll be very happy to help you, but first please read the following.
|
||||
|
||||
## Before asking for help
|
||||
|
||||
1. Read the [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=support)
|
||||
2. Search in the [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=support)
|
||||
|
||||
If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new).
|
||||
|
||||
It is OK to add a comment to a currently opened issue, but please avoid adding comments to a closed issue.
|
||||
|
||||
## Before hitting the Submit button
|
||||
|
||||
Please provide all the relevant information:
|
||||
|
||||
* Good title
|
||||
* Short description of the problem
|
||||
* Target platform
|
||||
* Compiler model and version
|
||||
* [MVCE](https://stackoverflow.com/help/mcve)
|
||||
* Compiler output
|
||||
|
||||
Good questions get fast answers!
|
16
appveyor.yml
16
appveyor.yml
@ -1,13 +1,15 @@
|
||||
version: 5.8.1.{build}
|
||||
version: 5.13.5.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
- CMAKE_GENERATOR: Visual Studio 12 2013
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
CMAKE_GENERATOR: Visual Studio 12 2013
|
||||
- CMAKE_GENERATOR: Visual Studio 11 2012
|
||||
- CMAKE_GENERATOR: Visual Studio 10 2010
|
||||
# - CMAKE_GENERATOR: MinGW Makefiles
|
||||
# Note: Disabled because of unexplicated error -1073741511
|
||||
# This used to work fine with GCC 4.8.2 then failed after they upgraded to GCC 4.9.3
|
||||
- CMAKE_GENERATOR: MinGW Makefiles
|
||||
configuration: Debug
|
||||
before_build:
|
||||
- set PATH=C:\MinGW\bin;%PATH:C:\Program Files\Git\usr\bin;=% # Workaround for CMake not wanting sh.exe on PATH for MinGW
|
||||
@ -15,4 +17,4 @@ before_build:
|
||||
build_script:
|
||||
- cmake --build . --config %CONFIGURATION%
|
||||
test_script:
|
||||
- ctest -V .
|
||||
- ctest --output-on-failure .
|
||||
|
367
banner.svg
Normal file
367
banner.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 32 KiB |
@ -1,35 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
// wait serial port initialization
|
||||
}
|
||||
|
||||
IndentedPrint serial(Serial);
|
||||
serial.setTabSize(4);
|
||||
|
||||
serial.println("This is at indentation 0");
|
||||
serial.indent();
|
||||
serial.println("This is at indentation 1");
|
||||
serial.println("This is also at indentation 1");
|
||||
serial.indent();
|
||||
serial.println("This is at indentation 2");
|
||||
|
||||
serial.unindent();
|
||||
serial.unindent();
|
||||
serial.println("This is back at indentation 0");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
144
examples/JsonConfigFile/JsonConfigFile.ino
Normal file
144
examples/JsonConfigFile/JsonConfigFile.ino
Normal file
@ -0,0 +1,144 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to store your project configuration in a file.
|
||||
// It uses the SD library but can be easily modified for any other file-system.
|
||||
//
|
||||
// The file contains a JSON document with the following content:
|
||||
// {
|
||||
// "hostname": "examples.com",
|
||||
// "port": 2731
|
||||
// }
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <SD.h>
|
||||
#include <SPI.h>
|
||||
|
||||
// Configuration that we'll store on disk
|
||||
struct Config {
|
||||
char hostname[64];
|
||||
int port;
|
||||
};
|
||||
|
||||
const char *filename = "/config.txt"; // <- SD library uses 8.3 filenames
|
||||
Config config; // <- global configuration object
|
||||
|
||||
// Loads the configuration from a file
|
||||
void loadConfiguration(const char *filename, Config &config) {
|
||||
// Open file for reading
|
||||
File file = SD.open(filename);
|
||||
|
||||
// Allocate the memory pool on the stack.
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<512> jsonBuffer;
|
||||
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.parseObject(file);
|
||||
|
||||
if (!root.success())
|
||||
Serial.println(F("Failed to read file, using default configuration"));
|
||||
|
||||
// Copy values from the JsonObject to the Config
|
||||
config.port = root["port"] | 2731;
|
||||
strlcpy(config.hostname, // <- destination
|
||||
root["hostname"] | "example.com", // <- source
|
||||
sizeof(config.hostname)); // <- destination's capacity
|
||||
|
||||
// Close the file (File's destructor doesn't close the file)
|
||||
file.close();
|
||||
}
|
||||
|
||||
// Saves the configuration to a file
|
||||
void saveConfiguration(const char *filename, const Config &config) {
|
||||
// Delete existing file, otherwise the configuration is appended to the file
|
||||
SD.remove(filename);
|
||||
|
||||
// Open file for writing
|
||||
File file = SD.open(filename, FILE_WRITE);
|
||||
if (!file) {
|
||||
Serial.println(F("Failed to create file"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the memory pool on the stack
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Use https://arduinojson.org/assistant/ to compute the capacity.
|
||||
StaticJsonBuffer<256> jsonBuffer;
|
||||
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.createObject();
|
||||
|
||||
// Set the values
|
||||
root["hostname"] = config.hostname;
|
||||
root["port"] = config.port;
|
||||
|
||||
// Serialize JSON to file
|
||||
if (root.printTo(file) == 0) {
|
||||
Serial.println(F("Failed to write to file"));
|
||||
}
|
||||
|
||||
// Close the file (File's destructor doesn't close the file)
|
||||
file.close();
|
||||
}
|
||||
|
||||
// Prints the content of a file to the Serial
|
||||
void printFile(const char *filename) {
|
||||
// Open file for reading
|
||||
File file = SD.open(filename);
|
||||
if (!file) {
|
||||
Serial.println(F("Failed to read file"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract each characters by one by one
|
||||
while (file.available()) {
|
||||
Serial.print((char)file.read());
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// Close the file (File's destructor doesn't close the file)
|
||||
file.close();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Initialize SD library
|
||||
while (!SD.begin()) {
|
||||
Serial.println(F("Failed to initialize SD library"));
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// Should load default config if run for the first time
|
||||
Serial.println(F("Loading configuration..."));
|
||||
loadConfiguration(filename, config);
|
||||
|
||||
// Create configuration file
|
||||
Serial.println(F("Saving configuration..."));
|
||||
saveConfiguration(filename, config);
|
||||
|
||||
// Dump config file
|
||||
Serial.println(F("Print config file..."));
|
||||
printFile(filename);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization or deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a case study of a project that has
|
||||
// a complex configuration with nested members.
|
||||
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
@ -1,29 +1,27 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize Serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
// wait serial port initialization
|
||||
}
|
||||
while (!Serial) continue;
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// If the JSON object is more complex, you need to increase that value.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
// It's simpler but less efficient.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer;
|
||||
// DynamicJsonBuffer jsonBuffer(200);
|
||||
|
||||
// Create the root of the object tree.
|
||||
//
|
||||
@ -44,8 +42,8 @@ void setup() {
|
||||
// It's also possible to create the array separately and add it to the
|
||||
// JsonObject but it's less efficient.
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(double_with_n_digits(48.756080, 6));
|
||||
data.add(double_with_n_digits(2.302038, 6));
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
@ -68,3 +66,16 @@ void setup() {
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like serializing directly to a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,184 +1,112 @@
|
||||
// Sample Arduino Json Web Client
|
||||
// Downloads and parse http://jsonplaceholder.typicode.com/users/1
|
||||
//
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
// This example shows how to parse a JSON document in an HTTP response.
|
||||
// It uses the Ethernet library, but can be easily adapted for Wifi.
|
||||
//
|
||||
// It performs a GET resquest on arduinojson.org/example.json
|
||||
// Here is the expected response:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [
|
||||
// 48.756080,
|
||||
// 2.302038
|
||||
// ]
|
||||
// }
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
#include <SPI.h>
|
||||
|
||||
EthernetClient client;
|
||||
|
||||
const char* server = "jsonplaceholder.typicode.com"; // server's address
|
||||
const char* resource = "/users/1"; // http resource
|
||||
const unsigned long BAUD_RATE = 9600; // serial connection speed
|
||||
const unsigned long HTTP_TIMEOUT = 10000; // max respone time from server
|
||||
const size_t MAX_CONTENT_SIZE = 512; // max size of the HTTP response
|
||||
|
||||
// The type of data that we want to extract from the page
|
||||
struct UserData {
|
||||
char name[32];
|
||||
char company[32];
|
||||
};
|
||||
|
||||
// ARDUINO entry point #1: runs once when you press reset or power the board
|
||||
void setup() {
|
||||
initSerial();
|
||||
initEthernet();
|
||||
}
|
||||
// Initialize Serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// ARDUINO entry point #2: runs over and over again forever
|
||||
void loop() {
|
||||
if (connect(server)) {
|
||||
if (sendRequest(server, resource) && skipResponseHeaders()) {
|
||||
UserData userData;
|
||||
if (readReponseContent(&userData)) {
|
||||
printUserData(&userData);
|
||||
}
|
||||
}
|
||||
disconnect();
|
||||
}
|
||||
wait();
|
||||
}
|
||||
|
||||
// Initialize Serial port
|
||||
void initSerial() {
|
||||
Serial.begin(BAUD_RATE);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to initialize
|
||||
}
|
||||
Serial.println("Serial ready");
|
||||
}
|
||||
|
||||
// Initialize Ethernet library
|
||||
void initEthernet() {
|
||||
// Initialize Ethernet library
|
||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||
if (!Ethernet.begin(mac)) {
|
||||
Serial.println("Failed to configure Ethernet");
|
||||
Serial.println(F("Failed to configure Ethernet"));
|
||||
return;
|
||||
}
|
||||
Serial.println("Ethernet ready");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// Open connection to the HTTP server
|
||||
bool connect(const char* hostName) {
|
||||
Serial.print("Connect to ");
|
||||
Serial.println(hostName);
|
||||
Serial.println(F("Connecting..."));
|
||||
|
||||
bool ok = client.connect(hostName, 80);
|
||||
// Connect to HTTP server
|
||||
EthernetClient client;
|
||||
client.setTimeout(10000);
|
||||
if (!client.connect("arduinojson.org", 80)) {
|
||||
Serial.println(F("Connection failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println(ok ? "Connected" : "Connection Failed!");
|
||||
return ok;
|
||||
}
|
||||
Serial.println(F("Connected!"));
|
||||
|
||||
// Send the HTTP GET request to the server
|
||||
bool sendRequest(const char* host, const char* resource) {
|
||||
Serial.print("GET ");
|
||||
Serial.println(resource);
|
||||
// Send HTTP request
|
||||
client.println(F("GET /example.json HTTP/1.0"));
|
||||
client.println(F("Host: arduinojson.org"));
|
||||
client.println(F("Connection: close"));
|
||||
if (client.println() == 0) {
|
||||
Serial.println(F("Failed to send request"));
|
||||
return;
|
||||
}
|
||||
|
||||
client.print("GET ");
|
||||
client.print(resource);
|
||||
client.println(" HTTP/1.0");
|
||||
client.print("Host: ");
|
||||
client.println(host);
|
||||
client.println("Connection: close");
|
||||
client.println();
|
||||
// Check HTTP status
|
||||
char status[32] = {0};
|
||||
client.readBytesUntil('\r', status, sizeof(status));
|
||||
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
|
||||
Serial.print(F("Unexpected response: "));
|
||||
Serial.println(status);
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip HTTP headers so that we are at the beginning of the response's body
|
||||
bool skipResponseHeaders() {
|
||||
// HTTP headers end with an empty line
|
||||
// Skip HTTP headers
|
||||
char endOfHeaders[] = "\r\n\r\n";
|
||||
|
||||
client.setTimeout(HTTP_TIMEOUT);
|
||||
bool ok = client.find(endOfHeaders);
|
||||
|
||||
if (!ok) {
|
||||
Serial.println("No response or invalid response!");
|
||||
if (!client.find(endOfHeaders)) {
|
||||
Serial.println(F("Invalid response"));
|
||||
return;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Parse the JSON from the input string and extract the interesting values
|
||||
// Here is the JSON we need to parse
|
||||
// {
|
||||
// "id": 1,
|
||||
// "name": "Leanne Graham",
|
||||
// "username": "Bret",
|
||||
// "email": "Sincere@april.biz",
|
||||
// "address": {
|
||||
// "street": "Kulas Light",
|
||||
// "suite": "Apt. 556",
|
||||
// "city": "Gwenborough",
|
||||
// "zipcode": "92998-3874",
|
||||
// "geo": {
|
||||
// "lat": "-37.3159",
|
||||
// "lng": "81.1496"
|
||||
// }
|
||||
// },
|
||||
// "phone": "1-770-736-8031 x56442",
|
||||
// "website": "hildegard.org",
|
||||
// "company": {
|
||||
// "name": "Romaguera-Crona",
|
||||
// "catchPhrase": "Multi-layered client-server neural-net",
|
||||
// "bs": "harness real-time e-markets"
|
||||
// }
|
||||
// }
|
||||
bool readReponseContent(struct UserData* userData) {
|
||||
// Compute optimal size of the JSON buffer according to what we need to parse.
|
||||
// This is only required if you use StaticJsonBuffer.
|
||||
const size_t BUFFER_SIZE =
|
||||
JSON_OBJECT_SIZE(8) // the root object has 8 elements
|
||||
+ JSON_OBJECT_SIZE(5) // the "address" object has 5 elements
|
||||
+ JSON_OBJECT_SIZE(2) // the "geo" object has 2 elements
|
||||
+ JSON_OBJECT_SIZE(3) // the "company" object has 3 elements
|
||||
+ MAX_CONTENT_SIZE; // additional space for strings
|
||||
|
||||
// Allocate a temporary memory pool
|
||||
DynamicJsonBuffer jsonBuffer(BUFFER_SIZE);
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
|
||||
DynamicJsonBuffer jsonBuffer(capacity);
|
||||
|
||||
// Parse JSON object
|
||||
JsonObject& root = jsonBuffer.parseObject(client);
|
||||
|
||||
if (!root.success()) {
|
||||
Serial.println("JSON parsing failed!");
|
||||
return false;
|
||||
Serial.println(F("Parsing failed!"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Here were copy the strings we're interested in
|
||||
strcpy(userData->name, root["name"]);
|
||||
strcpy(userData->company, root["company"]["name"]);
|
||||
// It's not mandatory to make a copy, you could just use the pointers
|
||||
// Since, they are pointing inside the "content" buffer, so you need to make
|
||||
// sure it's still in memory when you read the string
|
||||
// Extract values
|
||||
Serial.println(F("Response:"));
|
||||
Serial.println(root["sensor"].as<char*>());
|
||||
Serial.println(root["time"].as<char*>());
|
||||
Serial.println(root["data"][0].as<char*>());
|
||||
Serial.println(root["data"][1].as<char*>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Print the data extracted from the JSON
|
||||
void printUserData(const struct UserData* userData) {
|
||||
Serial.print("Name = ");
|
||||
Serial.println(userData->name);
|
||||
Serial.print("Company = ");
|
||||
Serial.println(userData->company);
|
||||
}
|
||||
|
||||
// Close the connection with the HTTP server
|
||||
void disconnect() {
|
||||
Serial.println("Disconnect");
|
||||
// Disconnect
|
||||
client.stop();
|
||||
}
|
||||
|
||||
// Pause for a 1 minute
|
||||
void wait() {
|
||||
Serial.println("Wait 60 seconds");
|
||||
delay(60000);
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization
|
||||
// showing how to parse the response from Yahoo Weather. In the last chapter,
|
||||
// it shows how to parse the huge documents from OpenWeatherMap
|
||||
// and Weather Underground.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,29 +1,27 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
// wait serial port initialization
|
||||
}
|
||||
while (!Serial) continue;
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the pool in bytes,
|
||||
// If the JSON object is more complex, you need to increase that value.
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
// It's simpler but less efficient.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer;
|
||||
// DynamicJsonBuffer jsonBuffer(200);
|
||||
|
||||
// JSON input string.
|
||||
//
|
||||
@ -65,3 +63,16 @@ void setup() {
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like deserializing directly from a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,74 +1,109 @@
|
||||
// Sample Arduino Json Web Server
|
||||
// Created by Benoit Blanchon.
|
||||
// Heavily inspired by "Web Server" from David A. Mellis and Tom Igoe
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to implement an HTTP server that sends JSON document
|
||||
// in the responses.
|
||||
// It uses the Ethernet library but can be easily adapted for Wifi.
|
||||
//
|
||||
// It sends the value of the analog and digital pins.
|
||||
// The JSON document looks like the following:
|
||||
// {
|
||||
// "analog": [ 0, 1, 2, 3, 4, 5 ],
|
||||
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
|
||||
// }
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Ethernet.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
#include <SPI.h>
|
||||
|
||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||
IPAddress ip(192, 168, 0, 177);
|
||||
EthernetServer server(80);
|
||||
|
||||
bool readRequest(EthernetClient& client) {
|
||||
bool currentLineIsBlank = true;
|
||||
while (client.connected()) {
|
||||
if (client.available()) {
|
||||
char c = client.read();
|
||||
if (c == '\n' && currentLineIsBlank) {
|
||||
return true;
|
||||
} else if (c == '\n') {
|
||||
currentLineIsBlank = true;
|
||||
} else if (c != '\r') {
|
||||
currentLineIsBlank = false;
|
||||
}
|
||||
}
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Initialize Ethernet libary
|
||||
if (!Ethernet.begin(mac)) {
|
||||
Serial.println(F("Failed to initialize Ethernet library"));
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
|
||||
// Start to listen
|
||||
server.begin();
|
||||
|
||||
Serial.println(F("Server is ready."));
|
||||
Serial.print(F("Please connect to http://"));
|
||||
Serial.println(Ethernet.localIP());
|
||||
}
|
||||
|
||||
JsonObject& prepareResponse(JsonBuffer& jsonBuffer) {
|
||||
void loop() {
|
||||
// Wait for an incomming connection
|
||||
EthernetClient client = server.available();
|
||||
|
||||
// Do we have a client?
|
||||
if (!client) return;
|
||||
|
||||
Serial.println(F("New client"));
|
||||
|
||||
// Read the request (we ignore the content in this example)
|
||||
while (client.available()) client.read();
|
||||
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
// Read the analog input
|
||||
int value = analogRead(pin);
|
||||
|
||||
// Add the value at the end of the array
|
||||
analogValues.add(value);
|
||||
}
|
||||
|
||||
// Create the "digital" array
|
||||
JsonArray& digitalValues = root.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
// Read the digital input
|
||||
int value = digitalRead(pin);
|
||||
|
||||
// Add the value at the end of the array
|
||||
digitalValues.add(value);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
Serial.print(F("Sending: "));
|
||||
root.printTo(Serial);
|
||||
Serial.println();
|
||||
|
||||
void writeResponse(EthernetClient& client, JsonObject& json) {
|
||||
client.println("HTTP/1.1 200 OK");
|
||||
// Write response headers
|
||||
client.println("HTTP/1.0 200 OK");
|
||||
client.println("Content-Type: application/json");
|
||||
client.println("Connection: close");
|
||||
client.println();
|
||||
|
||||
json.prettyPrintTo(client);
|
||||
// Write JSON document
|
||||
root.prettyPrintTo(client);
|
||||
|
||||
// Disconnect
|
||||
client.stop();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Ethernet.begin(mac, ip);
|
||||
server.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
EthernetClient client = server.available();
|
||||
if (client) {
|
||||
bool success = readRequest(client);
|
||||
if (success) {
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
JsonObject& json = prepareResponse(jsonBuffer);
|
||||
writeResponse(client, json);
|
||||
}
|
||||
delay(1);
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or an HTTP client.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,55 +1,101 @@
|
||||
// Send a JSON object on UDP at regular interval
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// You can easily test this program with netcat:
|
||||
// $ nc -ulp 8888
|
||||
// This example shows how to send a JSON document to a UDP socket.
|
||||
// At regular interval, it sends a UDP packet that contains the status of
|
||||
// analog and digital pins.
|
||||
// The JSON document looks like the following:
|
||||
// {
|
||||
// "analog": [ 0, 1, 2, 3, 4, 5 ],
|
||||
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
|
||||
// }
|
||||
//
|
||||
// by Benoit Blanchon, MIT License 2015-2017
|
||||
// If you want to test this program, you need to be able to receive the UDP
|
||||
// packets.
|
||||
// For example, you can run netcat on your computer
|
||||
// $ ncat -ulp 8888
|
||||
// See https://nmap.org/ncat/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
#include <SPI.h>
|
||||
|
||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||
IPAddress localIp(192, 168, 0, 177);
|
||||
IPAddress remoteIp(192, 168, 0, 109);
|
||||
unsigned int remotePort = 8888;
|
||||
unsigned localPort = 8888;
|
||||
IPAddress remoteIp(192, 168, 0, 108); // <- EDIT!!!!
|
||||
unsigned short remotePort = 8888;
|
||||
unsigned short localPort = 8888;
|
||||
EthernetUDP udp;
|
||||
|
||||
JsonObject& buildJson(JsonBuffer& jsonBuffer) {
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
int value = analogRead(pin);
|
||||
analogValues.add(value);
|
||||
}
|
||||
|
||||
JsonArray& digitalValues = root.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
int value = digitalRead(pin);
|
||||
digitalValues.add(value);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void sendJson(JsonObject& json) {
|
||||
udp.beginPacket(remoteIp, remotePort);
|
||||
json.printTo(udp);
|
||||
udp.println();
|
||||
udp.endPacket();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Ethernet.begin(mac, localIp);
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Initialize Ethernet libary
|
||||
if (!Ethernet.begin(mac)) {
|
||||
Serial.println(F("Failed to initialize Ethernet library"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable UDP
|
||||
udp.begin(localPort);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(1000);
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
|
||||
StaticJsonBuffer<300> jsonBuffer;
|
||||
JsonObject& json = buildJson(jsonBuffer);
|
||||
sendJson(json);
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
// Read the analog input
|
||||
int value = analogRead(pin);
|
||||
|
||||
// Add the value at the end of the array
|
||||
analogValues.add(value);
|
||||
}
|
||||
|
||||
// Create the "digital" array
|
||||
JsonArray& digitalValues = root.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
// Read the digital input
|
||||
int value = digitalRead(pin);
|
||||
|
||||
// Add the value at the end of the array
|
||||
digitalValues.add(value);
|
||||
}
|
||||
|
||||
// Log
|
||||
Serial.print(F("Sending to "));
|
||||
Serial.print(remoteIp);
|
||||
Serial.print(F(" on port "));
|
||||
Serial.println(remotePort);
|
||||
root.printTo(Serial);
|
||||
|
||||
// Send UDP packet
|
||||
udp.beginPacket(remoteIp, remotePort);
|
||||
root.printTo(udp);
|
||||
udp.println();
|
||||
udp.endPacket();
|
||||
|
||||
// Wait
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or any stream.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,21 +1,19 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
// This example shows the different ways you can use Flash strings with
|
||||
// ArduinoJson.
|
||||
//
|
||||
// Use Flash strings sparingly, because ArduinoJson duplicates them in the
|
||||
// JsonBuffer. Prefer plain old char*, as they are more efficient in term of
|
||||
// code size, speed, and memory usage.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
// About
|
||||
// -----
|
||||
// This example shows the different ways you can use PROGMEM with ArduinoJson.
|
||||
// Please don't see this as an invitation to use PROGMEM.
|
||||
// On the contrary, you should always use char[] when possible, it's much more
|
||||
// efficient in term of code size, speed and memory usage.
|
||||
|
||||
void setup() {
|
||||
#ifdef PROGMEM
|
||||
#ifdef PROGMEM // <- check that Flash strings are supported
|
||||
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
// You can use a Flash String as your JSON input.
|
||||
@ -39,6 +37,9 @@ void setup() {
|
||||
// JsonBuffer.
|
||||
root["sensor"] = F("gps");
|
||||
|
||||
// It works with RawJson too:
|
||||
root["sensor"] = RawJson(F("\"gps\""));
|
||||
|
||||
// You can compare the content of a JsonVariant to a Flash String
|
||||
if (root["sensor"] == F("gps")) {
|
||||
// ...
|
||||
@ -54,3 +55,16 @@ void setup() {
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any memory
|
||||
// problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. It also tells why you
|
||||
// should not abuse Flash strings with ArduinoJson.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,19 +1,15 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
// This example shows the different ways you can use String with ArduinoJson.
|
||||
//
|
||||
// Use String objects sparingly, because ArduinoJson duplicates them in the
|
||||
// JsonBuffer. Prefer plain old char[], as they are more efficient in term of
|
||||
// code size, speed, and memory usage.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
// About
|
||||
// -----
|
||||
// This example shows the different ways you can use String with ArduinoJson.
|
||||
// Please don't see this as an invitation to use String.
|
||||
// On the contrary, you should always use char[] when possible, it's much more
|
||||
// efficient in term of code size, speed and memory usage.
|
||||
|
||||
void setup() {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
@ -44,6 +40,9 @@ void setup() {
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
root["sensor"] = sensor;
|
||||
|
||||
// It works with RawJson too:
|
||||
root["sensor"] = RawJson(sensor);
|
||||
|
||||
// You can also concatenate strings
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
root[String("sen") + "sor"] = String("gp") + "s";
|
||||
@ -61,3 +60,15 @@ void setup() {
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. On several occasions, it
|
||||
// shows how you can avoid String in your program.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,13 +1,13 @@
|
||||
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
|
||||
|
||||
CXXFLAGS += -I../include
|
||||
CXXFLAGS += -I../src
|
||||
|
||||
all: \
|
||||
$(OUT)/json_fuzzer \
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/json_fuzzer.options
|
||||
|
||||
$(OUT)/json_fuzzer: fuzzer.cpp
|
||||
$(OUT)/json_fuzzer: fuzzer.cpp $(shell find ../src -type f)
|
||||
$(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE)
|
||||
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip: seed_corpus/*
|
||||
|
@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This script mimics an invocation from https://github.com/google/oss-fuzz
|
||||
|
||||
export CXX='clang++'
|
||||
export CXXFLAGS='-fsanitize-coverage=trace-pc-guard -fsanitize=address'
|
||||
export LIB_FUZZING_ENGINE=-lFuzzer
|
||||
make OUT=.
|
||||
./json_fuzzer my_corpus seed_corpus
|
@ -18,6 +18,9 @@ class memstream : public std::istream {
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
memstream json(data, size);
|
||||
jsonBuffer.parse(json);
|
||||
JsonVariant variant = jsonBuffer.parse(json);
|
||||
if (variant.success()) {
|
||||
variant.as<std::string>(); // <- serialize to JSON
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"sensor": "gps",
|
||||
"time": 1351824120,
|
||||
"data": [
|
||||
48.75608,
|
||||
2.302038
|
||||
]
|
||||
}
|
10
fuzzing/seed_corpus/Comments.json
Normal file
10
fuzzing/seed_corpus/Comments.json
Normal file
@ -0,0 +1,10 @@
|
||||
//comment
|
||||
/*comment*/
|
||||
[ //comment
|
||||
/*comment*/"comment"/*comment*/,//comment
|
||||
/*comment*/{//comment
|
||||
/* comment*/"key"//comment
|
||||
: //comment
|
||||
"value"//comment
|
||||
}/*comment*/
|
||||
]//comment
|
1
fuzzing/seed_corpus/EmptyArray.json
Normal file
1
fuzzing/seed_corpus/EmptyArray.json
Normal file
@ -0,0 +1 @@
|
||||
[]
|
1
fuzzing/seed_corpus/EmptyObject.json
Normal file
1
fuzzing/seed_corpus/EmptyObject.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
1
fuzzing/seed_corpus/ExcessiveNesting.json
Normal file
1
fuzzing/seed_corpus/ExcessiveNesting.json
Normal file
@ -0,0 +1 @@
|
||||
[1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20,[21,[22,[23,[24,[25,[26,[27,[28,[29,[30,[31,[32,[33,[34,[35,[36,[37,[38,[39,[40,[41,[42,[43,[44,[45,[46,[47,[48,[49,[50,[51,[52,[53,[54,[55,[56,[57,[58,[59,[60,[61,[62,[63,[64,[65,[66,[67,[68,[69,[70,[71,[72,[73,[74,[75,[76,[77,[78,[79,[80,[81,[82,[83,[84,[85,[86,[87,[88,[89,[90,[91,[92,[93,[94,[95,[96,[97,[98,[99,[100,[101,[102,[103,[104,[105,[106,[107,[108,[109,[110,[111,[112,[113,[114,[115,[116,[117,[118,[119,[120]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
|
24
fuzzing/seed_corpus/Numbers.json
Normal file
24
fuzzing/seed_corpus/Numbers.json
Normal file
@ -0,0 +1,24 @@
|
||||
[
|
||||
123,
|
||||
-123,
|
||||
123.456,
|
||||
-123.456,
|
||||
12e34,
|
||||
12e-34,
|
||||
12e+34,
|
||||
12E34,
|
||||
12E-34,
|
||||
12E+34,
|
||||
12.34e56,
|
||||
12.34e-56,
|
||||
12.34e+56,
|
||||
12.34E56,
|
||||
12.34E-56,
|
||||
12.34E+56,
|
||||
NaN,
|
||||
-NaN,
|
||||
+NaN,
|
||||
Infinity,
|
||||
+Infinity,
|
||||
-Infinity
|
||||
]
|
8
fuzzing/seed_corpus/Strings.json
Normal file
8
fuzzing/seed_corpus/Strings.json
Normal file
@ -0,0 +1,8 @@
|
||||
[
|
||||
"hello",
|
||||
'hello',
|
||||
hello,
|
||||
{"hello":"world"},
|
||||
{'hello':'world'},
|
||||
{hello:world}
|
||||
]
|
@ -1,9 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include "ArduinoJson.hpp"
|
||||
using namespace ArduinoJson;
|
@ -1,39 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_UNDEFINED, // JsonVariant has not been initialized
|
||||
JSON_UNPARSED, // JsonVariant contains an unparsed string
|
||||
JSON_STRING, // JsonVariant stores a const char*
|
||||
JSON_BOOLEAN, // JsonVariant stores a bool
|
||||
JSON_POSITIVE_INTEGER, // JsonVariant stores an unsigned long
|
||||
JSON_NEGATIVE_INTEGER, // JsonVariant stores an unsigned long that must be
|
||||
// negated
|
||||
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray
|
||||
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
|
||||
|
||||
// The following values are reserved for float values
|
||||
// Multiple values are used for double, depending on the number of decimal
|
||||
// digits that must be printed in the JSON output.
|
||||
// This little trick allow to save one extra member in JsonVariant
|
||||
JSON_FLOAT_0_DECIMALS
|
||||
// JSON_FLOAT_1_DECIMAL
|
||||
// JSON_FLOAT_2_DECIMALS
|
||||
// ...
|
||||
};
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TFloat>
|
||||
TFloat parse(const char *);
|
||||
|
||||
template <>
|
||||
inline float parse<float>(const char *s) {
|
||||
return static_cast<float>(strtod(s, NULL));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline double parse<double>(const char *s) {
|
||||
return strtod(s, NULL);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline long parse<long>(const char *s) {
|
||||
return strtol(s, NULL, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned long parse<unsigned long>(const char *s) {
|
||||
return strtoul(s, NULL, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int parse<int>(const char *s) {
|
||||
return atoi(s);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
template <>
|
||||
inline long long parse<long long>(const char *s) {
|
||||
return strtoll(s, NULL, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned long long parse<unsigned long long>(const char *s) {
|
||||
return strtoull(s, NULL, 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_INT64
|
||||
template <>
|
||||
inline __int64 parse<__int64>(const char *s) {
|
||||
return _strtoi64(s, NULL, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned __int64 parse<unsigned __int64>(const char *s) {
|
||||
return _strtoui64(s, NULL, 10);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TSource, typename Enable = void>
|
||||
struct ValueSetter {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer*, TDestination& destination,
|
||||
const TSource& source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TSource>
|
||||
struct ValueSetter<TSource, typename TypeTraits::EnableIf<StringTraits<
|
||||
TSource>::should_duplicate>::type> {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer* buffer, TDestination& destination,
|
||||
const TSource& source) {
|
||||
const char* copy = buffer->strdup(source);
|
||||
if (!copy) return false;
|
||||
destination = copy;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TInput>
|
||||
void skipSpacesAndComments(TInput& input) {
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
input.move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
switch (input.next()) {
|
||||
// C-style block comment
|
||||
case '*':
|
||||
input.move(); // skip '/'
|
||||
input.move(); // skip '*'
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
case '\0':
|
||||
return;
|
||||
case '*':
|
||||
input.move(); // skip '*'
|
||||
if (input.current() == '/') {
|
||||
input.move(); // skip '/'
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
input.move();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// C++-style line comment
|
||||
case '/':
|
||||
input.move(); // skip '/'
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
case '\0':
|
||||
return;
|
||||
case '\n':
|
||||
input.move();
|
||||
return;
|
||||
default:
|
||||
input.move();
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Parse JSON string to create JsonArrays and JsonObjects
|
||||
// This internal class is not indended to be used directly.
|
||||
// Instead, use JsonBuffer.parseArray() or .parseObject()
|
||||
template <typename TIterator>
|
||||
class StringReader {
|
||||
TIterator _input;
|
||||
char _current, _next;
|
||||
|
||||
public:
|
||||
StringReader(const TIterator& input) : _input(input) {
|
||||
_current = _input.next();
|
||||
_next = _input.next();
|
||||
}
|
||||
|
||||
void move() {
|
||||
_current = _next;
|
||||
_next = _input.next();
|
||||
}
|
||||
|
||||
char current() const {
|
||||
return _current;
|
||||
}
|
||||
|
||||
char next() const {
|
||||
return _next;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class StringWriter {
|
||||
public:
|
||||
class String {
|
||||
public:
|
||||
String(char** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
|
||||
|
||||
void append(char c) {
|
||||
*(*_writePtr)++ = c;
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
*(*_writePtr)++ = 0;
|
||||
return _startPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
char** _writePtr;
|
||||
char* _startPtr;
|
||||
};
|
||||
|
||||
StringWriter(char* buffer) : _ptr(buffer) {}
|
||||
|
||||
String startString() {
|
||||
return String(&_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
char* _ptr;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,335 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonBufferAllocated.hpp"
|
||||
#include "Data/List.hpp"
|
||||
#include "Data/ReferenceType.hpp"
|
||||
#include "Data/ValueSetter.hpp"
|
||||
#include "JsonPair.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsArray.hpp"
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonArray;
|
||||
class JsonBuffer;
|
||||
|
||||
// A dictionary of JsonVariant indexed by string (char*)
|
||||
//
|
||||
// The constructor is private, instances must be created via
|
||||
// JsonBuffer::createObject() or JsonBuffer::parseObject().
|
||||
// A JsonObject can be serialized to a JSON string via JsonObject::printTo().
|
||||
// It can also be deserialized from a JSON string via JsonBuffer::parseObject().
|
||||
class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
public Internals::ReferenceType,
|
||||
public Internals::List<JsonPair>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
public:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not use this constructor directly.
|
||||
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
|
||||
explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
JsonObjectSubscript<const TString&> >::type
|
||||
operator[](const TString& key) {
|
||||
return JsonObjectSubscript<const TString&>(*this, key);
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonObjectSubscript<const TString*> operator[](const TString* key) {
|
||||
return JsonObjectSubscript<const TString*>(*this, key);
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// JsonVariant operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
const JsonVariant operator[](const TString& key) const {
|
||||
return get_impl<const TString&, JsonVariant>(key);
|
||||
}
|
||||
//
|
||||
// JsonVariant operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
const JsonVariant operator[](const TString* key) const {
|
||||
return get_impl<const TString*, JsonVariant>(key);
|
||||
}
|
||||
|
||||
// Sets the specified key with the specified value.
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
template <typename TValue, typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value &&
|
||||
!TypeTraits::IsArray<TValue>::value,
|
||||
bool>::type
|
||||
set(const TString& key, const TValue& value) {
|
||||
return set_impl<const TString&, const TValue&>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TValue, typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
bool>::type
|
||||
set(const TString& key, const TValue* value) {
|
||||
return set_impl<const TString&, const TValue*>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
template <typename TValue, typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TValue>::value, bool>::type
|
||||
set(const TString* key, const TValue& value) {
|
||||
return set_impl<const TString*, const TValue&>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TValue, typename TString>
|
||||
bool set(const TString* key, const TValue* value) {
|
||||
return set_impl<const TString*, const TValue*>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue, uint8_t decimals);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = float, double
|
||||
template <typename TValue, typename TString>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value &&
|
||||
!TypeTraits::IsArray<TString>::value,
|
||||
bool>::type
|
||||
set(const TString& key, TValue value, uint8_t decimals) {
|
||||
return set_impl<const TString&, const JsonVariant&>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue, uint8_t decimals);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = float, double
|
||||
template <typename TValue, typename TString>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value,
|
||||
bool>::type
|
||||
set(const TString* key, TValue value, uint8_t decimals) {
|
||||
return set_impl<const TString*, const JsonVariant&>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// TValue get<TValue>(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
template <typename TValue, typename TString>
|
||||
typename TypeTraits::EnableIf<
|
||||
!TypeTraits::IsArray<TString>::value,
|
||||
typename Internals::JsonVariantAs<TValue>::type>::type
|
||||
get(const TString& key) const {
|
||||
return get_impl<const TString&, TValue>(key);
|
||||
}
|
||||
//
|
||||
// TValue get<TValue>(TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
template <typename TValue, typename TString>
|
||||
typename Internals::JsonVariantAs<TValue>::type get(
|
||||
const TString* key) const {
|
||||
return get_impl<const TString*, TValue>(key);
|
||||
}
|
||||
|
||||
// Checks the type of the value associated with the specified key.
|
||||
//
|
||||
//
|
||||
// bool is<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
template <typename TValue, typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
bool>::type
|
||||
is(const TString& key) const {
|
||||
return is_impl<const TString&, TValue>(key);
|
||||
}
|
||||
//
|
||||
// bool is<TValue>(TKey) const;
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
template <typename TValue, typename TString>
|
||||
bool is(const TString* key) const {
|
||||
return is_impl<const TString*, TValue>(key);
|
||||
}
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
//
|
||||
// JsonArray& createNestedArray(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
JsonArray&>::type
|
||||
createNestedArray(const TString& key) {
|
||||
return createNestedArray_impl<const TString&>(key);
|
||||
}
|
||||
// JsonArray& createNestedArray(TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonArray& createNestedArray(const TString* key) {
|
||||
return createNestedArray_impl<const TString*>(key);
|
||||
}
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
//
|
||||
// JsonObject& createNestedObject(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
JsonObject&>::type
|
||||
createNestedObject(const TString& key) {
|
||||
return createNestedObject_impl<const TString&>(key);
|
||||
}
|
||||
//
|
||||
// JsonObject& createNestedObject(TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonObject& createNestedObject(const TString* key) {
|
||||
return createNestedObject_impl<const TString*>(key);
|
||||
}
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
bool>::type
|
||||
containsKey(const TString& key) const {
|
||||
return findNode<const TString&>(key) != NULL;
|
||||
}
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
bool containsKey(const TString* key) const {
|
||||
return findNode<const TString*>(key) != NULL;
|
||||
}
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
void>::type
|
||||
remove(const TString& key) {
|
||||
removeNode(findNode<const TString&>(key));
|
||||
}
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
void remove(const TString* key) {
|
||||
removeNode(findNode<const TString*>(key));
|
||||
}
|
||||
|
||||
// Returns a reference an invalid JsonObject.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
// This is used when memory allocation or JSON parsing fail.
|
||||
static JsonObject& invalid() {
|
||||
static JsonObject instance(NULL);
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns the list node that matches the specified key.
|
||||
template <typename TStringRef>
|
||||
node_type* findNode(TStringRef key) const {
|
||||
for (node_type* node = _firstNode; node; node = node->next) {
|
||||
if (Internals::StringTraits<TStringRef>::equals(key, node->content.key))
|
||||
return node;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValue>
|
||||
typename Internals::JsonVariantAs<TValue>::type get_impl(
|
||||
TStringRef key) const {
|
||||
node_type* node = findNode<TStringRef>(key);
|
||||
return node ? node->content.value.as<TValue>()
|
||||
: Internals::JsonVariantDefault<TValue>::get();
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValueRef>
|
||||
bool set_impl(TStringRef key, TValueRef value) {
|
||||
node_type* node = findNode<TStringRef>(key);
|
||||
if (!node) {
|
||||
node = addNewNode();
|
||||
if (!node) return false;
|
||||
|
||||
bool key_ok = Internals::ValueSetter<TStringRef>::set(
|
||||
_buffer, node->content.key, key);
|
||||
if (!key_ok) return false;
|
||||
}
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content.value,
|
||||
value);
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValue>
|
||||
bool is_impl(TStringRef key) const {
|
||||
node_type* node = findNode<TStringRef>(key);
|
||||
return node ? node->content.value.is<TValue>() : false;
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
JsonArray& createNestedArray_impl(TStringRef key);
|
||||
|
||||
template <typename TStringRef>
|
||||
JsonObject& createNestedObject_impl(TStringRef key);
|
||||
};
|
||||
|
||||
namespace Internals {
|
||||
template <>
|
||||
struct JsonVariantDefault<JsonObject> {
|
||||
static JsonObject& get() {
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,355 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h> // for uint8_t
|
||||
|
||||
#include "Data/JsonVariantContent.hpp"
|
||||
#include "Data/JsonVariantDefault.hpp"
|
||||
#include "Data/JsonVariantType.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "RawJson.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsIntegral.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
#include "TypeTraits/IsSignedIntegral.hpp"
|
||||
#include "TypeTraits/IsUnsignedIntegral.hpp"
|
||||
#include "TypeTraits/RemoveConst.hpp"
|
||||
#include "TypeTraits/RemoveReference.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
// A variant that can be a any value serializable to a JSON value.
|
||||
//
|
||||
// It can be set to:
|
||||
// - a boolean
|
||||
// - a char, short, int or a long (signed or unsigned)
|
||||
// - a string (const char*)
|
||||
// - a reference to a JsonArray or JsonObject
|
||||
class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
friend void Internals::JsonSerializer::serialize(const JsonVariant &,
|
||||
JsonWriter &);
|
||||
|
||||
public:
|
||||
// Creates an uninitialized JsonVariant
|
||||
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||
|
||||
// Create a JsonVariant containing a boolean value.
|
||||
// It will be serialized as "true" or "false" in JSON.
|
||||
JsonVariant(bool value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_BOOLEAN;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing a floating point value.
|
||||
// The second argument specifies the number of decimal digits to write in
|
||||
// the JSON string.
|
||||
// JsonVariant(double value, uint8_t decimals);
|
||||
// JsonVariant(float value, uint8_t decimals);
|
||||
template <typename T>
|
||||
JsonVariant(T value, uint8_t decimals = 2,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
||||
using namespace Internals;
|
||||
_type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals);
|
||||
_content.asFloat = static_cast<JsonFloat>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing an integer value.
|
||||
// JsonVariant(signed short)
|
||||
// JsonVariant(signed int)
|
||||
// JsonVariant(signed long)
|
||||
template <typename T>
|
||||
JsonVariant(T value,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSignedIntegral<T>::value>::type * = 0) {
|
||||
using namespace Internals;
|
||||
if (value >= 0) {
|
||||
_type = JSON_POSITIVE_INTEGER;
|
||||
_content.asInteger = static_cast<JsonUInt>(value);
|
||||
} else {
|
||||
_type = JSON_NEGATIVE_INTEGER;
|
||||
_content.asInteger = static_cast<JsonUInt>(-value);
|
||||
}
|
||||
}
|
||||
// JsonVariant(unsigned short)
|
||||
// JsonVariant(unsigned int)
|
||||
// JsonVariant(unsigned long)
|
||||
template <typename T>
|
||||
JsonVariant(T value,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsUnsignedIntegral<T>::value>::type * = 0) {
|
||||
using namespace Internals;
|
||||
_type = JSON_POSITIVE_INTEGER;
|
||||
_content.asInteger = static_cast<JsonUInt>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing a string.
|
||||
JsonVariant(const char *value) {
|
||||
_type = Internals::JSON_STRING;
|
||||
_content.asString = value;
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing an unparsed string
|
||||
JsonVariant(RawJson value) {
|
||||
_type = Internals::JSON_UNPARSED;
|
||||
_content.asString = value;
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing a reference to an array.
|
||||
// CAUTION: we are lying about constness, because the array can be modified if
|
||||
// the variant is converted back to a JsonArray&
|
||||
JsonVariant(const JsonArray &array);
|
||||
|
||||
// Create a JsonVariant containing a reference to an object.
|
||||
// CAUTION: we are lying about constness, because the object can be modified
|
||||
// if the variant is converted back to a JsonObject&
|
||||
JsonVariant(const JsonObject &object);
|
||||
|
||||
// Get the variant as the specified type.
|
||||
//
|
||||
// short as<signed short>() const;
|
||||
// int as<signed int>() const;
|
||||
// long as<signed long>() const;
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsSignedIntegral<T>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return static_cast<T>(asInteger());
|
||||
}
|
||||
//
|
||||
// short as<unsigned short>() const;
|
||||
// int as<unsigned int>() const;
|
||||
// long as<unsigned long>() const;
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsUnsignedIntegral<T>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return static_cast<T>(asUnsignedInteger());
|
||||
}
|
||||
//
|
||||
// double as<double>() const;
|
||||
// float as<float>() const;
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return static_cast<T>(asFloat());
|
||||
}
|
||||
//
|
||||
// const char* as<const char*>() const;
|
||||
// const char* as<char*>() const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value ||
|
||||
TypeTraits::IsSame<T, char *>::value,
|
||||
const char *>::type
|
||||
as() const {
|
||||
return asString();
|
||||
}
|
||||
//
|
||||
// std::string as<std::string>() const;
|
||||
// String as<String>() const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<Internals::StringTraits<T>::has_append, T>::type
|
||||
as() const {
|
||||
const char *cstr = asString();
|
||||
if (cstr) return T(cstr);
|
||||
T s;
|
||||
printTo(s);
|
||||
return s;
|
||||
}
|
||||
//
|
||||
// const bool as<bool>() const
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return asInteger() != 0;
|
||||
}
|
||||
//
|
||||
// JsonArray& as<JsonArray> const;
|
||||
// JsonArray& as<JsonArray&> const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
|
||||
JsonArray>::value,
|
||||
JsonArray &>::type
|
||||
as() const {
|
||||
return asArray();
|
||||
}
|
||||
//
|
||||
// const JsonArray& as<const JsonArray&> const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
|
||||
const JsonArray>::value,
|
||||
const JsonArray &>::type
|
||||
as() const {
|
||||
return asArray();
|
||||
}
|
||||
//
|
||||
// JsonObject& as<JsonObject> const;
|
||||
// JsonObject& as<JsonObject&> const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
|
||||
JsonObject>::value,
|
||||
JsonObject &>::type
|
||||
as() const {
|
||||
return asObject();
|
||||
}
|
||||
//
|
||||
// JsonObject& as<const JsonObject> const;
|
||||
// JsonObject& as<const JsonObject&> const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
|
||||
const JsonObject>::value,
|
||||
const JsonObject &>::type
|
||||
as() const {
|
||||
return asObject();
|
||||
}
|
||||
//
|
||||
// JsonVariant as<JsonVariant> const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, JsonVariant>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Tells weither the variant has the specified type.
|
||||
// Returns true if the variant has type type T, false otherwise.
|
||||
//
|
||||
// short as<short>() const;
|
||||
// int as<int>() const;
|
||||
// long as<long>() const;
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value &&
|
||||
!TypeTraits::IsSame<T, bool>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isInteger();
|
||||
}
|
||||
//
|
||||
// double is<double>() const;
|
||||
// float is<float>() const;
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isFloat();
|
||||
}
|
||||
//
|
||||
// const bool is<bool>() const
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isBoolean();
|
||||
}
|
||||
//
|
||||
// bool is<const char*>() const;
|
||||
// bool is<char*>() const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value ||
|
||||
TypeTraits::IsSame<T, char *>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isString();
|
||||
}
|
||||
//
|
||||
// bool is<JsonArray> const;
|
||||
// bool is<JsonArray&> const;
|
||||
// bool is<const JsonArray&> const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSame<
|
||||
typename TypeTraits::RemoveConst<
|
||||
typename TypeTraits::RemoveReference<T>::type>::type,
|
||||
JsonArray>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isArray();
|
||||
}
|
||||
//
|
||||
// bool is<JsonObject> const;
|
||||
// bool is<JsonObject&> const;
|
||||
// bool is<const JsonObject&> const;
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSame<
|
||||
typename TypeTraits::RemoveConst<
|
||||
typename TypeTraits::RemoveReference<T>::type>::type,
|
||||
JsonObject>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isObject();
|
||||
}
|
||||
|
||||
// Returns true if the variant has a value
|
||||
bool success() const {
|
||||
return _type != Internals::JSON_UNDEFINED;
|
||||
}
|
||||
|
||||
// DEPRECATED: use as<char*>() instead
|
||||
const char *asString() const;
|
||||
|
||||
// DEPRECATED: use as<JsonArray>() instead
|
||||
JsonArray &asArray() const;
|
||||
|
||||
// DEPRECATED: use as<JsonObject>() instead
|
||||
JsonObject &asObject() const;
|
||||
|
||||
private:
|
||||
// It's not allowed to store a char
|
||||
template <typename T>
|
||||
JsonVariant(T value, typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSame<T, char>::value>::type * = 0);
|
||||
|
||||
Internals::JsonFloat asFloat() const;
|
||||
Internals::JsonInteger asInteger() const;
|
||||
Internals::JsonUInt asUnsignedInteger() const;
|
||||
bool isBoolean() const;
|
||||
bool isFloat() const;
|
||||
bool isInteger() const;
|
||||
bool isArray() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
bool isObject() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
bool isString() const {
|
||||
return _type == Internals::JSON_STRING ||
|
||||
(_type == Internals::JSON_UNPARSED && _content.asString &&
|
||||
!strcmp("null", _content.asString));
|
||||
}
|
||||
|
||||
// The current type of the variant
|
||||
Internals::JsonVariantType _type;
|
||||
|
||||
// The various alternatives for the value of the variant.
|
||||
Internals::JsonVariantContent _content;
|
||||
};
|
||||
|
||||
inline JsonVariant float_with_n_digits(float value, uint8_t digits) {
|
||||
return JsonVariant(value, digits);
|
||||
}
|
||||
|
||||
inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
|
||||
return JsonVariant(value, digits);
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArraySubscript;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||
public:
|
||||
// DEPRECATED: use as<char*>() instead
|
||||
FORCE_INLINE const char *asString() const {
|
||||
return as<const char *>();
|
||||
}
|
||||
|
||||
// Gets the variant as an array.
|
||||
// Returns a reference to the JsonArray or JsonArray::invalid() if the
|
||||
// variant
|
||||
// is not an array.
|
||||
FORCE_INLINE operator JsonArray &() const {
|
||||
return as<JsonArray &>();
|
||||
}
|
||||
|
||||
// DEPRECATED: use as<JsonArray>() instead
|
||||
FORCE_INLINE JsonArray &asArray() const {
|
||||
return as<JsonArray &>();
|
||||
}
|
||||
|
||||
// Gets the variant as an object.
|
||||
// Returns a reference to the JsonObject or JsonObject::invalid() if the
|
||||
// variant is not an object.
|
||||
FORCE_INLINE operator JsonObject &() const {
|
||||
return as<JsonObject &>();
|
||||
}
|
||||
|
||||
// DEPRECATED: use as<JsonObject>() instead
|
||||
FORCE_INLINE JsonObject &asObject() const {
|
||||
return as<JsonObject &>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE operator T() const {
|
||||
return as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE const typename Internals::JsonVariantAs<T>::type as() const {
|
||||
return impl()->template as<T>();
|
||||
}
|
||||
|
||||
// Mimics an array or an object.
|
||||
// Returns the size of the array or object if the variant has that type.
|
||||
// Returns 0 if the variant is neither an array nor an object
|
||||
size_t size() const {
|
||||
return asArray().size() + asObject().size();
|
||||
}
|
||||
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
// Returns JsonVariant::invalid() if the variant is not an array.
|
||||
FORCE_INLINE const JsonArraySubscript operator[](int index) const;
|
||||
FORCE_INLINE JsonArraySubscript operator[](int index);
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is
|
||||
// an object.
|
||||
// Return JsonVariant::invalid() if the variant is not an object.
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString>::has_equals,
|
||||
const JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString>::has_equals,
|
||||
JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) {
|
||||
return asObject()[key];
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString *>::has_equals,
|
||||
JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) {
|
||||
return asObject()[key];
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString *>::has_equals,
|
||||
const JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
template <typename TVariant, typename TComparand, typename Enable = void>
|
||||
struct JsonVariantComparer {
|
||||
static bool equals(const TVariant &variant, const TComparand &comparand) {
|
||||
return variant.template as<TComparand>() == comparand;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TVariant, typename TString>
|
||||
struct JsonVariantComparer<
|
||||
TVariant, TString, typename TypeTraits::EnableIf<Internals::StringTraits<
|
||||
TString>::has_equals>::type> {
|
||||
static bool equals(const TVariant &variant, const TString &comparand) {
|
||||
const char *value = variant.template as<const char *>();
|
||||
return Internals::StringTraits<TString>::equals(comparand, value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator==(const JsonVariantBase<TImpl> &variant,
|
||||
TComparand comparand) {
|
||||
typedef JsonVariantBase<TImpl> TVariant;
|
||||
return JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand);
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator==(TComparand comparand,
|
||||
const JsonVariantBase<TImpl> &variant) {
|
||||
typedef JsonVariantBase<TImpl> TVariant;
|
||||
return JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand);
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator!=(const JsonVariantBase<TImpl> &variant,
|
||||
TComparand comparand) {
|
||||
typedef JsonVariantBase<TImpl> TVariant;
|
||||
return !JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand);
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator!=(TComparand comparand,
|
||||
const JsonVariantBase<TImpl> &variant) {
|
||||
typedef JsonVariantBase<TImpl> TVariant;
|
||||
return !JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand);
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<=(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() <= right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<=(TComparand comparand,
|
||||
const JsonVariantBase<TImpl> &variant) {
|
||||
return comparand <= variant.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>=(const JsonVariantBase<TImpl> &variant,
|
||||
TComparand comparand) {
|
||||
return variant.template as<TComparand>() >= comparand;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>=(TComparand comparand,
|
||||
const JsonVariantBase<TImpl> &variant) {
|
||||
return comparand >= variant.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<(const JsonVariantBase<TImpl> &varian,
|
||||
TComparand comparand) {
|
||||
return varian.template as<TComparand>() < comparand;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<(TComparand comparand,
|
||||
const JsonVariantBase<TImpl> &variant) {
|
||||
return comparand < variant.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>(const JsonVariantBase<TImpl> &variant,
|
||||
TComparand comparand) {
|
||||
return variant.template as<TComparand>() > comparand;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>(TComparand comparand,
|
||||
const JsonVariantBase<TImpl> &variant) {
|
||||
return comparand > variant.template as<TComparand>();
|
||||
}
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "Data/Parse.hpp"
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
#include <errno.h> // for errno
|
||||
#include <stdlib.h> // for strtol, strtod
|
||||
#include <string.h> // for strcmp
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonVariant::JsonVariant(const JsonArray &array) {
|
||||
if (array.success()) {
|
||||
_type = Internals::JSON_ARRAY;
|
||||
_content.asArray = const_cast<JsonArray *>(&array);
|
||||
} else {
|
||||
_type = Internals::JSON_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(const JsonObject &object) {
|
||||
if (object.success()) {
|
||||
_type = Internals::JSON_OBJECT;
|
||||
_content.asObject = const_cast<JsonObject *>(&object);
|
||||
} else {
|
||||
_type = Internals::JSON_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
inline JsonArray &JsonVariant::asArray() const {
|
||||
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
inline JsonObject &JsonVariant::asObject() const {
|
||||
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
inline Internals::JsonInteger JsonVariant::asInteger() const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
return 0;
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return _content.asInteger;
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return -static_cast<Internals::JsonInteger>(_content.asInteger);
|
||||
case JSON_STRING:
|
||||
case JSON_UNPARSED:
|
||||
if (!_content.asString) return 0;
|
||||
if (!strcmp("true", _content.asString)) return 1;
|
||||
return parse<Internals::JsonInteger>(_content.asString);
|
||||
default:
|
||||
return static_cast<Internals::JsonInteger>(_content.asFloat);
|
||||
}
|
||||
}
|
||||
|
||||
inline Internals::JsonUInt JsonVariant::asUnsignedInteger() const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
return 0;
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return _content.asInteger;
|
||||
case JSON_STRING:
|
||||
case JSON_UNPARSED:
|
||||
if (!_content.asString) return 0;
|
||||
if (!strcmp("true", _content.asString)) return 1;
|
||||
return parse<Internals::JsonUInt>(_content.asString);
|
||||
default:
|
||||
return static_cast<Internals::JsonUInt>(_content.asFloat);
|
||||
}
|
||||
}
|
||||
|
||||
inline const char *JsonVariant::asString() const {
|
||||
using namespace Internals;
|
||||
if (_type == JSON_UNPARSED && _content.asString &&
|
||||
!strcmp("null", _content.asString))
|
||||
return NULL;
|
||||
if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline Internals::JsonFloat JsonVariant::asFloat() const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
return 0;
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return static_cast<JsonFloat>(_content.asInteger);
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return -static_cast<JsonFloat>(_content.asInteger);
|
||||
case JSON_STRING:
|
||||
case JSON_UNPARSED:
|
||||
return _content.asString ? parse<JsonFloat>(_content.asString) : 0;
|
||||
default:
|
||||
return _content.asFloat;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool JsonVariant::isBoolean() const {
|
||||
using namespace Internals;
|
||||
if (_type == JSON_BOOLEAN) return true;
|
||||
|
||||
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
||||
|
||||
return !strcmp(_content.asString, "true") ||
|
||||
!strcmp(_content.asString, "false");
|
||||
}
|
||||
|
||||
inline bool JsonVariant::isInteger() const {
|
||||
using namespace Internals;
|
||||
if (_type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER)
|
||||
return true;
|
||||
|
||||
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
||||
|
||||
char *end;
|
||||
errno = 0;
|
||||
strtol(_content.asString, &end, 10);
|
||||
|
||||
return *end == '\0' && errno == 0;
|
||||
}
|
||||
|
||||
inline bool JsonVariant::isFloat() const {
|
||||
using namespace Internals;
|
||||
if (_type >= JSON_FLOAT_0_DECIMALS) return true;
|
||||
|
||||
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
||||
|
||||
char *end;
|
||||
errno = 0;
|
||||
strtod(_content.asString, &end);
|
||||
|
||||
return *end == '\0' && errno == 0 && !is<long>();
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
@ -1,16 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FORCE_INLINE __forceinline
|
||||
#define NO_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define FORCE_INLINE __attribute__((always_inline))
|
||||
#define NO_INLINE __attribute__((noinline))
|
||||
#endif
|
@ -1,111 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
// If Visual Studo <= 2012
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
|
||||
#include <float.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Polyfills {
|
||||
template <typename T>
|
||||
bool isNaN(T x) {
|
||||
return _isnan(x) != 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool isInfinity(T x) {
|
||||
return !_finite(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// GCC warning: "conversion to 'float' from 'double' may alter its value"
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||
#pragma GCC diagnostic ignored "-Wfloat-conversion"
|
||||
#else
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Workaround for libs that #undef isnan or isinf
|
||||
// https://github.com/bblanchon/ArduinoJson/issues/284
|
||||
#if !defined(isnan) || !defined(isinf)
|
||||
namespace std {}
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Polyfills {
|
||||
|
||||
template <typename T>
|
||||
bool isNaN(T x) {
|
||||
// Workaround for libs that #undef isnan
|
||||
// https://github.com/bblanchon/ArduinoJson/issues/284
|
||||
#ifndef isnan
|
||||
using namespace std;
|
||||
#endif
|
||||
|
||||
return isnan(x);
|
||||
}
|
||||
|
||||
#if defined(_GLIBCXX_HAVE_ISNANL) && _GLIBCXX_HAVE_ISNANL
|
||||
template <>
|
||||
inline bool isNaN<double>(double x) {
|
||||
return isnanl(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_GLIBCXX_HAVE_ISNANF) && _GLIBCXX_HAVE_ISNANF
|
||||
template <>
|
||||
inline bool isNaN<float>(float x) {
|
||||
return isnanf(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
bool isInfinity(T x) {
|
||||
// Workaround for libs that #undef isinf
|
||||
// https://github.com/bblanchon/ArduinoJson/issues/284
|
||||
#ifndef isinf
|
||||
using namespace std;
|
||||
#endif
|
||||
|
||||
return isinf(x);
|
||||
}
|
||||
|
||||
#if defined(_GLIBCXX_HAVE_ISINFL) && _GLIBCXX_HAVE_ISINFL
|
||||
template <>
|
||||
inline bool isInfinity<double>(double x) {
|
||||
return isinfl(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_GLIBCXX_HAVE_ISINFF) && _GLIBCXX_HAVE_ISINFF
|
||||
template <>
|
||||
inline bool isInfinity<float>(float x) {
|
||||
return isinff(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,47 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Polyfills {
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
// on embedded platform, favor code size over speed
|
||||
|
||||
template <typename T>
|
||||
short normalize(T& value) {
|
||||
short powersOf10 = 0;
|
||||
while (value && value < 1) {
|
||||
powersOf10--;
|
||||
value *= 10;
|
||||
}
|
||||
while (value > 10) {
|
||||
powersOf10++;
|
||||
value /= 10;
|
||||
}
|
||||
return powersOf10;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// on non-embedded platform, favor speed over code size
|
||||
|
||||
template <typename T>
|
||||
short normalize(T& value) {
|
||||
if (value == 0.0) return 0;
|
||||
|
||||
short powersOf10 = static_cast<short>(floor(log10(value)));
|
||||
value /= pow(T(10), powersOf10);
|
||||
|
||||
return powersOf10;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
// This class reproduces Arduino's Print class
|
||||
class Print {
|
||||
public:
|
||||
virtual ~Print() {}
|
||||
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
|
||||
size_t print(const char* s) {
|
||||
size_t n = 0;
|
||||
while (*s) {
|
||||
n += write(static_cast<uint8_t>(*s++));
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t println() {
|
||||
size_t n = 0;
|
||||
n += write('\r');
|
||||
n += write('\n');
|
||||
return n;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <Print.h>
|
||||
|
||||
#endif
|
@ -1,23 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// A special type of data that can be used to insert pregenerated JSON portions.
|
||||
class RawJson {
|
||||
public:
|
||||
explicit RawJson(const char* str) : _str(str) {}
|
||||
operator const char*() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* _str;
|
||||
};
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A dummy Print implementation used in JsonPrintable::measureLength()
|
||||
class DummyPrint : public Print {
|
||||
public:
|
||||
virtual size_t write(uint8_t) {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class JsonArray;
|
||||
class JsonArraySubscript;
|
||||
class JsonObject;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
class JsonVariant;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
class JsonSerializer {
|
||||
public:
|
||||
static void serialize(const JsonArray &, JsonWriter &);
|
||||
static void serialize(const JsonArraySubscript &, JsonWriter &);
|
||||
static void serialize(const JsonObject &, JsonWriter &);
|
||||
template <typename TKey>
|
||||
static void serialize(const JsonObjectSubscript<TKey> &, JsonWriter &);
|
||||
static void serialize(const JsonVariant &, JsonWriter &);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Data/Encoding.hpp"
|
||||
#include "../Data/JsonFloat.hpp"
|
||||
#include "../Data/JsonInteger.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
#include "../Polyfills/math.hpp"
|
||||
#include "../Polyfills/normalize.hpp"
|
||||
#include "../Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Writes the JSON tokens to a Print implementation
|
||||
// This class is used by:
|
||||
// - JsonArray::writeTo()
|
||||
// - JsonObject::writeTo()
|
||||
// - JsonVariant::writeTo()
|
||||
// Its derived by PrettyJsonWriter that overrides some members to add
|
||||
// indentation.
|
||||
class JsonWriter {
|
||||
public:
|
||||
explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {}
|
||||
|
||||
// Returns the number of bytes sent to the Print implementation.
|
||||
// This is very handy for implementations of printTo() that must return the
|
||||
// number of bytes written.
|
||||
size_t bytesWritten() const {
|
||||
return _length;
|
||||
}
|
||||
|
||||
void beginArray() {
|
||||
writeRaw('[');
|
||||
}
|
||||
void endArray() {
|
||||
writeRaw(']');
|
||||
}
|
||||
|
||||
void beginObject() {
|
||||
writeRaw('{');
|
||||
}
|
||||
void endObject() {
|
||||
writeRaw('}');
|
||||
}
|
||||
|
||||
void writeColon() {
|
||||
writeRaw(':');
|
||||
}
|
||||
void writeComma() {
|
||||
writeRaw(',');
|
||||
}
|
||||
|
||||
void writeBoolean(bool value) {
|
||||
writeRaw(value ? "true" : "false");
|
||||
}
|
||||
|
||||
void writeString(const char *value) {
|
||||
if (!value) {
|
||||
writeRaw("null");
|
||||
} else {
|
||||
writeRaw('\"');
|
||||
while (*value) writeChar(*value++);
|
||||
writeRaw('\"');
|
||||
}
|
||||
}
|
||||
|
||||
void writeChar(char c) {
|
||||
char specialChar = Encoding::escapeChar(c);
|
||||
if (specialChar) {
|
||||
writeRaw('\\');
|
||||
writeRaw(specialChar);
|
||||
} else {
|
||||
writeRaw(c);
|
||||
}
|
||||
}
|
||||
|
||||
void writeFloat(JsonFloat value, uint8_t digits = 2) {
|
||||
if (Polyfills::isNaN(value)) return writeRaw("NaN");
|
||||
|
||||
if (value < 0.0) {
|
||||
writeRaw('-');
|
||||
value = -value;
|
||||
}
|
||||
|
||||
if (Polyfills::isInfinity(value)) return writeRaw("Infinity");
|
||||
|
||||
short powersOf10;
|
||||
if (value > 1000 || value < 0.001) {
|
||||
powersOf10 = Polyfills::normalize(value);
|
||||
} else {
|
||||
powersOf10 = 0;
|
||||
}
|
||||
|
||||
// Round up last digit (so that print(1.999, 2) prints as "2.00")
|
||||
value += getRoundingBias(digits);
|
||||
|
||||
// Extract the integer part of the value and print it
|
||||
JsonUInt int_part = static_cast<JsonUInt>(value);
|
||||
JsonFloat remainder = value - static_cast<JsonFloat>(int_part);
|
||||
writeInteger(int_part);
|
||||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if (digits > 0) {
|
||||
writeRaw('.');
|
||||
}
|
||||
|
||||
// Extract digits from the remainder one at a time
|
||||
while (digits-- > 0) {
|
||||
// Extract digit
|
||||
remainder *= 10.0;
|
||||
char currentDigit = char(remainder);
|
||||
remainder -= static_cast<JsonFloat>(currentDigit);
|
||||
|
||||
// Print
|
||||
writeRaw(char('0' + currentDigit));
|
||||
}
|
||||
|
||||
if (powersOf10 < 0) {
|
||||
writeRaw("e-");
|
||||
writeInteger(-powersOf10);
|
||||
}
|
||||
|
||||
if (powersOf10 > 0) {
|
||||
writeRaw('e');
|
||||
writeInteger(powersOf10);
|
||||
}
|
||||
}
|
||||
|
||||
void writeInteger(JsonUInt value) {
|
||||
char buffer[22];
|
||||
char *ptr = buffer + sizeof(buffer) - 1;
|
||||
|
||||
*ptr = 0;
|
||||
do {
|
||||
*--ptr = static_cast<char>(value % 10 + '0');
|
||||
value /= 10;
|
||||
} while (value);
|
||||
|
||||
writeRaw(ptr);
|
||||
}
|
||||
|
||||
void writeRaw(const char *s) {
|
||||
_length += _sink.print(s);
|
||||
}
|
||||
void writeRaw(char c) {
|
||||
_length += _sink.write(c);
|
||||
}
|
||||
|
||||
protected:
|
||||
Print &_sink;
|
||||
size_t _length;
|
||||
|
||||
private:
|
||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||
|
||||
static JsonFloat getLastDigit(uint8_t digits) {
|
||||
// Designed as a compromise between code size and speed
|
||||
switch (digits) {
|
||||
case 0:
|
||||
return 1e-0;
|
||||
case 1:
|
||||
return 1e-1;
|
||||
case 2:
|
||||
return 1e-2;
|
||||
case 3:
|
||||
return 1e-3;
|
||||
default:
|
||||
return getLastDigit(uint8_t(digits - 4)) * 1e-4;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE static JsonFloat getRoundingBias(uint8_t digits) {
|
||||
return 0.5 * getLastDigit(digits);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A Print implementation that allows to write in a char[]
|
||||
class StaticStringBuilder : public Print {
|
||||
public:
|
||||
StaticStringBuilder(char *buf, size_t size)
|
||||
: buffer(buf), capacity(size - 1), length(0) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
if (length >= capacity) return 0;
|
||||
|
||||
buffer[length++] = c;
|
||||
buffer[length] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
char *buffer;
|
||||
size_t capacity;
|
||||
size_t length;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
#include "../TypeTraits/IsBaseOf.hpp"
|
||||
#include "../TypeTraits/RemoveReference.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct ArduinoStreamTraits {
|
||||
class Iterator {
|
||||
Stream& _stream;
|
||||
|
||||
public:
|
||||
Iterator(Stream& stream) : _stream(stream) {}
|
||||
|
||||
char next() {
|
||||
int n = _stream.read();
|
||||
return n >= 0 ? static_cast<char>(n) : '\0';
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename TStream>
|
||||
struct StringTraits<TStream,
|
||||
// match any type that is derived from Stream:
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsBaseOf<
|
||||
Stream, typename TypeTraits::RemoveReference<
|
||||
TStream>::type>::value>::type>
|
||||
: ArduinoStreamTraits {};
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct CharPointerTraits {
|
||||
class Iterator {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
Iterator(const char* ptr) : _ptr(ptr ? ptr : "") {}
|
||||
|
||||
char next() {
|
||||
char c = *_ptr;
|
||||
if (c) ++_ptr;
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
static bool equals(const char* str, const char* expected) {
|
||||
return strcmp(str, expected) == 0;
|
||||
}
|
||||
|
||||
template <typename Buffer>
|
||||
static char* duplicate(const char* str, Buffer* buffer) {
|
||||
if (!str) return NULL;
|
||||
size_t size = strlen(str) + 1;
|
||||
void* dup = buffer->alloc(size);
|
||||
if (dup != NULL) memcpy(dup, str, size);
|
||||
return static_cast<char*>(dup);
|
||||
}
|
||||
|
||||
static const bool has_append = false;
|
||||
static const bool has_equals = true;
|
||||
static const bool should_duplicate = false;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StringTraits<const char*, void> : CharPointerTraits {};
|
||||
|
||||
template <>
|
||||
struct StringTraits<char*, void> : CharPointerTraits {};
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <>
|
||||
struct StringTraits<const __FlashStringHelper*, void> {
|
||||
class Iterator {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
Iterator(const __FlashStringHelper* ptr)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||
|
||||
char next() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
};
|
||||
|
||||
static bool equals(const __FlashStringHelper* str, const char* expected) {
|
||||
return strcmp_P(expected, (PGM_P)str) == 0;
|
||||
}
|
||||
|
||||
template <typename Buffer>
|
||||
static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
|
||||
if (!str) return NULL;
|
||||
size_t size = strlen_P((PGM_P)str) + 1;
|
||||
void* dup = buffer->alloc(size);
|
||||
if (dup != NULL) memcpy_P(dup, (PGM_P)str, size);
|
||||
return static_cast<char*>(dup);
|
||||
}
|
||||
|
||||
static const bool has_append = false;
|
||||
static const bool has_equals = true;
|
||||
static const bool should_duplicate = true;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <istream>
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
#include "../TypeTraits/IsBaseOf.hpp"
|
||||
#include "../TypeTraits/RemoveReference.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct StdStreamTraits {
|
||||
class Iterator {
|
||||
std::istream& _stream;
|
||||
|
||||
public:
|
||||
Iterator(std::istream& stream) : _stream(stream) {}
|
||||
|
||||
char next() {
|
||||
return _stream.eof() ? '\0' : static_cast<char>(_stream.get());
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator& operator=(const Iterator&); // Visual Studio C4512
|
||||
};
|
||||
};
|
||||
|
||||
template <typename TStream>
|
||||
struct StringTraits<TStream,
|
||||
// match any type that is derived from std::istream:
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsBaseOf<
|
||||
std::istream, typename TypeTraits::RemoveReference<
|
||||
TStream>::type>::value>::type>
|
||||
: StdStreamTraits {};
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IsSame.hpp"
|
||||
#include "IsSignedIntegral.hpp"
|
||||
#include "IsUnsignedIntegral.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace TypeTraits {
|
||||
|
||||
// A meta-function that returns true if T is an integral type.
|
||||
template <typename T>
|
||||
struct IsIntegral {
|
||||
static const bool value = TypeTraits::IsSignedIntegral<T>::value ||
|
||||
TypeTraits::IsUnsignedIntegral<T>::value ||
|
||||
TypeTraits::IsSame<T, char>::value ||
|
||||
TypeTraits::IsSame<T, bool>::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IsIntegral<const T> : IsIntegral<T> {};
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "IsSame.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace TypeTraits {
|
||||
|
||||
// A meta-function that returns true if T is an integral type.
|
||||
template <typename T>
|
||||
struct IsSignedIntegral {
|
||||
static const bool value = TypeTraits::IsSame<T, signed char>::value ||
|
||||
TypeTraits::IsSame<T, signed short>::value ||
|
||||
TypeTraits::IsSame<T, signed int>::value ||
|
||||
TypeTraits::IsSame<T, signed long>::value ||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
TypeTraits::IsSame<T, signed long long>::value ||
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_INT64
|
||||
TypeTraits::IsSame<T, signed __int64>::value ||
|
||||
#endif
|
||||
false;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "IsSame.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace TypeTraits {
|
||||
|
||||
// A meta-function that returns true if T is an integral type.
|
||||
template <typename T>
|
||||
struct IsUnsignedIntegral {
|
||||
static const bool value = TypeTraits::IsSame<T, unsigned char>::value ||
|
||||
TypeTraits::IsSame<T, unsigned short>::value ||
|
||||
TypeTraits::IsSame<T, unsigned int>::value ||
|
||||
TypeTraits::IsSame<T, unsigned long>::value ||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
TypeTraits::IsSame<T, unsigned long long>::value ||
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_INT64
|
||||
TypeTraits::IsSame<T, unsigned __int64>::value ||
|
||||
#endif
|
||||
false;
|
||||
};
|
||||
}
|
||||
}
|
@ -2,18 +2,19 @@
|
||||
"name": "ArduinoJson",
|
||||
"keywords": "json, rest, http, web",
|
||||
"description": "An elegant and efficient JSON library for embedded systems",
|
||||
"homepage": "https://arduinojson.org/?utm_source=meta&utm_medium=library.json",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"version": "5.8.1",
|
||||
"version": "5.13.5",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "http://blog.benoitblanchon.fr"
|
||||
"url": "https://blog.benoitblanchon.fr"
|
||||
},
|
||||
"exclude": [
|
||||
"fuzzing",
|
||||
"scripts",
|
||||
"src/ArduinoJson.h",
|
||||
"test",
|
||||
"third-party"
|
||||
],
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=ArduinoJson
|
||||
version=5.8.1
|
||||
version=5.13.5
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
paragraph=Like this project? Please star it on GitHub!
|
||||
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ fixed allocation, ✔ zero-copy, ✔ streams, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
||||
category=Data Processing
|
||||
url=https://github.com/bblanchon/ArduinoJson
|
||||
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
|
||||
architectures=*
|
||||
repository=https://github.com/bblanchon/ArduinoJson.git
|
||||
license=MIT
|
||||
|
@ -12,7 +12,7 @@ rm -f $OUTPUT
|
||||
7z a $OUTPUT \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/include \
|
||||
ArduinoJson/src \
|
||||
ArduinoJson/keywords.txt \
|
||||
ArduinoJson/library.properties \
|
||||
ArduinoJson/LICENSE.md \
|
||||
|
53
scripts/build-single-header.sh
Normal file
53
scripts/build-single-header.sh
Normal file
@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
|
||||
TAG=$(git describe)
|
||||
RE_INCLUDE='^#include[[:space:]]*["<](.*)[">]'
|
||||
RE_EMPTY='^(#pragma[[:space:]]+once)?[[:space:]]*(//.*)?$'
|
||||
|
||||
declare -A INCLUDED
|
||||
|
||||
process()
|
||||
{
|
||||
local PARENT=$1
|
||||
local FOLDER=$(dirname $1)
|
||||
local SHOW_COMMENT=$2
|
||||
while IFS= read -r LINE; do
|
||||
if [[ $LINE =~ $RE_INCLUDE ]]; then
|
||||
local CHILD=${BASH_REMATCH[1]}
|
||||
pushd "$FOLDER" > /dev/null
|
||||
if [[ -e $CHILD ]]; then
|
||||
local CHILD_PATH=$(realpath $CHILD)
|
||||
if [[ ! ${INCLUDED[$CHILD_PATH]} ]]; then
|
||||
#echo "// $PARENT -> $CHILD"
|
||||
INCLUDED[$CHILD_PATH]=true
|
||||
process "$CHILD" false
|
||||
fi
|
||||
else
|
||||
if [[ ! ${INCLUDED[$CHILD]} ]]; then
|
||||
echo "$LINE"
|
||||
INCLUDED[$CHILD]=true
|
||||
fi
|
||||
fi
|
||||
popd > /dev/null
|
||||
elif [[ "${SHOW_COMMENT}" = "true" ]] ; then
|
||||
echo "$LINE"
|
||||
elif [[ ! $LINE =~ $RE_EMPTY ]]; then
|
||||
echo "$LINE"
|
||||
fi
|
||||
done < $PARENT
|
||||
}
|
||||
|
||||
cd $(dirname $0)/../
|
||||
INCLUDED=()
|
||||
process src/ArduinoJson.h true > ../ArduinoJson-$TAG.h
|
||||
g++ -x c++ -c -o ../smoketest.o - <<END
|
||||
#include "../ArduinoJson-$TAG.h"
|
||||
int main() {}
|
||||
END
|
||||
|
||||
INCLUDED=()
|
||||
process src/ArduinoJson.hpp true > ../ArduinoJson-$TAG.hpp
|
||||
g++ -x c++ -c -o ../smoketest.o - <<END
|
||||
#include "../ArduinoJson-$TAG.hpp"
|
||||
int main() {}
|
||||
END
|
@ -1,5 +0,0 @@
|
||||
CPPLINT="python third-party/cpplint/cpplint.py"
|
||||
FLAGS="--filter=-runtime/printf,-runtime/int,-readability/todo,-build/namespace,-runtime/references,-readability/streams"
|
||||
|
||||
cd ..
|
||||
$CPPLINT $FLAGS $(find include src test -regex ".*\.[hc]pp$")
|
@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
OUTPUT="$(pwd)/sizes.csv"
|
||||
|
||||
echo "Tag;Date;Parser;Generator" > $OUTPUT
|
||||
|
||||
cd $(dirname $(dirname $0))
|
||||
|
||||
git tag | while read TAG
|
||||
do
|
||||
|
||||
git checkout -q tags/$TAG
|
||||
|
||||
DATE=$(git log -1 --date=short --pretty=format:%cd)
|
||||
PARSER_SIZE=$(arduino --verify examples/JsonParserExample/JsonParserExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
|
||||
if [ -e 'examples/JsonGeneratorExample/JsonGeneratorExample.ino' ]; then
|
||||
GENERATOR_SIZE=$(arduino --verify examples/JsonGeneratorExample/JsonGeneratorExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
else
|
||||
GENERATOR_SIZE=""
|
||||
fi
|
||||
|
||||
echo $TAG
|
||||
if [ ! -z "$PARSER_SIZE" ]
|
||||
then
|
||||
echo "JsonParserExample = $PARSER_SIZE bytes"
|
||||
else
|
||||
echo "JsonParserExample compilation failed."
|
||||
fi
|
||||
|
||||
if [ ! -z "$GENERATOR_SIZE" ]
|
||||
then
|
||||
echo "JsonGeneratorExample = $GENERATOR_SIZE bytes"
|
||||
else
|
||||
echo "JsonGeneratorExample compilation failed."
|
||||
fi
|
||||
|
||||
echo "$TAG;$DATE;$PARSER_SIZE;$GENERATOR_SIZE" >> $OUTPUT
|
||||
|
||||
done
|
@ -1,7 +0,0 @@
|
||||
cd ..
|
||||
FILES=$(find include src test -regex ".*\.[ch]pp$")
|
||||
|
||||
clang-format -style=Google -i $FILES
|
||||
|
||||
# insert newline at end of file
|
||||
sed -i -e '$a\' $FILES
|
3
scripts/oss-fuzz/Vagrantfile
vendored
3
scripts/oss-fuzz/Vagrantfile
vendored
@ -26,5 +26,8 @@ Vagrant.configure(2) do |config|
|
||||
echo "export PROJECT_NAME='arduinojson'" >> $HOME/.profile
|
||||
echo "export CC='clang'" >> $HOME/.profile
|
||||
echo "export CXX='clang++'" >> $HOME/.profile
|
||||
echo "export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/" >> $HOME/.profile
|
||||
|
||||
echo "Run /host/ArduinoJson/fuzzing/fuzz.sh" | sudo tee /etc/motd
|
||||
SHELL
|
||||
end
|
||||
|
18
scripts/publish-particle-library.sh
Normal file
18
scripts/publish-particle-library.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
SOURCE_DIR="$(dirname "$0")/.."
|
||||
WORK_DIR=$(mktemp -d)
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
cp "$SOURCE_DIR/README.md" "$WORK_DIR/README.md"
|
||||
cp "$SOURCE_DIR/CHANGELOG.md" "$WORK_DIR/CHANGELOG.md"
|
||||
cp "$SOURCE_DIR/library.properties" "$WORK_DIR/library.properties"
|
||||
cp "$SOURCE_DIR/LICENSE.md" "$WORK_DIR/LICENSE.txt"
|
||||
cp -r "$SOURCE_DIR/src" "$WORK_DIR/"
|
||||
cp -r "$SOURCE_DIR/examples" "$WORK_DIR/"
|
||||
|
||||
cd "$WORK_DIR"
|
||||
particle library upload
|
||||
particle library publish
|
@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
FILE=../bin/ArduinoJsonTests.exe
|
||||
MD5=""
|
||||
|
||||
file_changed() {
|
||||
[[ ! -f "$FILE" ]] && return 1
|
||||
NEW_MD5=$(md5sum $FILE)
|
||||
[[ "$MD5" == "$NEW_MD5" ]] && return 1
|
||||
MD5=$NEW_MD5
|
||||
return 0
|
||||
}
|
||||
|
||||
test_succeed() {
|
||||
echo -en "\007"{,}
|
||||
}
|
||||
|
||||
test_failed() {
|
||||
echo -en "\007"{,,,,,,,,,,,}
|
||||
}
|
||||
|
||||
run_tests() {
|
||||
$FILE
|
||||
case $? in
|
||||
0)
|
||||
test_succeed
|
||||
;;
|
||||
1)
|
||||
test_failed
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
while true
|
||||
do
|
||||
if file_changed
|
||||
then
|
||||
run_tests
|
||||
else
|
||||
sleep 2
|
||||
fi
|
||||
done
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Darwin-x86_64.tar.gz
|
||||
|
||||
curl -sS $URL | tar xz -C /tmp --strip 1
|
||||
|
||||
/tmp/CMake.app/Contents/bin/cmake .
|
||||
make
|
||||
make test
|
@ -1,9 +1,33 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.tar.gz
|
||||
#!/bin/sh -ex
|
||||
|
||||
if [ "$(uname)" = 'Darwin' ]; then
|
||||
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Darwin-x86_64.tar.gz
|
||||
CMAKE=/tmp/CMake.app/Contents/bin/cmake
|
||||
CTEST=/tmp/CMake.app/Contents/bin/ctest
|
||||
else
|
||||
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.tar.gz
|
||||
CMAKE=/tmp/bin/cmake
|
||||
CTEST=/tmp/bin/ctest
|
||||
fi
|
||||
curl -sS $URL | tar xz -C /tmp --strip 1
|
||||
|
||||
/tmp/bin/cmake -DCMAKE_CXX_COMPILER=$CMAKE_CXX_COMPILER .
|
||||
make
|
||||
make test
|
||||
if [ -n "$GCC" ]; then
|
||||
export CC="gcc-$GCC"
|
||||
export CXX="g++-$GCC"
|
||||
fi
|
||||
|
||||
if [ -n "$CLANG" ]; then
|
||||
export CC="clang-$CLANG"
|
||||
export CXX="clang++-$CLANG"
|
||||
fi
|
||||
|
||||
if [ -n "$SANITIZE" ]; then
|
||||
export CXXFLAGS="-fsanitize=$SANITIZE"
|
||||
BUILD_TYPE="Debug"
|
||||
else
|
||||
BUILD_TYPE="Release"
|
||||
fi
|
||||
|
||||
$CMAKE -DCMAKE_BUILD_TYPE=$BUILD_TYPE .
|
||||
$CMAKE --build .
|
||||
$CTEST --output-on-failure .
|
||||
|
20
scripts/travis/fuzz.sh
Executable file
20
scripts/travis/fuzz.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash -eux
|
||||
|
||||
ROOT_DIR=$(dirname $0)/../../
|
||||
INCLUDE_DIR=$ROOT_DIR/src/
|
||||
FUZZING_DIR=$ROOT_DIR/fuzzing/
|
||||
JSON_CORPUS_DIR=$FUZZING_DIR/my_corpus
|
||||
JSON_SEED_CORPUS_DIR=$FUZZING_DIR/seed_corpus
|
||||
|
||||
CXX="clang++-$CLANG"
|
||||
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,fuzzer"
|
||||
|
||||
$CXX $CXXFLAGS -o json_fuzzer -I$INCLUDE_DIR $FUZZING_DIR/fuzzer.cpp
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="json_fuzzer.profraw"
|
||||
./json_fuzzer "$JSON_CORPUS_DIR" "$JSON_SEED_CORPUS_DIR" -max_total_time=60
|
||||
|
||||
llvm-profdata-$CLANG merge -sparse json_fuzzer.profraw -o json_fuzzer.profdata
|
||||
|
||||
llvm-cov-$CLANG report ./json_fuzzer -instr-profile=json_fuzzer.profdata
|
@ -1,7 +0,0 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
curl https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | tar xz -C /tmp --strip 1
|
||||
|
||||
/tmp/bin/cmake -DSANITIZE=true .
|
||||
cmake --build .
|
||||
ctest -VV .
|
17
src/ArduinoJson.h
Normal file
17
src/ArduinoJson.h
Normal file
@ -0,0 +1,17 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "ArduinoJson.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
|
||||
#else
|
||||
|
||||
#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp
|
||||
|
||||
#endif
|
@ -1,16 +1,14 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/version.hpp"
|
||||
|
||||
#include "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/JsonVariantComparisons.hpp"
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
|
||||
@ -20,4 +18,4 @@
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
#include "ArduinoJson/compatibility.hpp"
|
@ -1,20 +1,27 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef ARDUINO // assume this is an embedded platform
|
||||
// Small or big machine?
|
||||
#ifndef ARDUINOJSON_EMBEDDED_MODE
|
||||
#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
|
||||
defined(__ARMCC_VERSION)
|
||||
#define ARDUINOJSON_EMBEDDED_MODE 1
|
||||
#else
|
||||
#define ARDUINOJSON_EMBEDDED_MODE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// store using float instead of double to reduce the memory usage (issue #134)
|
||||
#if ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
// Store floats by default to reduce the memory usage (issue #134)
|
||||
#ifndef ARDUINOJSON_USE_DOUBLE
|
||||
#define ARDUINOJSON_USE_DOUBLE 0
|
||||
#endif
|
||||
|
||||
// store using a long because it usually match the size of a float.
|
||||
// Store longs by default, because they usually match the size of a float.
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
@ -22,57 +29,29 @@
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
|
||||
// Arduino has its own implementation of String to replace std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
|
||||
#endif
|
||||
|
||||
// On AVR archiecture, we can use PROGMEM
|
||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||
#ifdef PROGMEM
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 1
|
||||
#else
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Arduino doesn't have std::string
|
||||
// Embedded systems usually don't have std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
#define ARDUINOJSON_ENABLE_STD_STRING 0
|
||||
#endif
|
||||
|
||||
// Arduino doesn't support STL stream
|
||||
// Embedded systems usually don't have std::stream
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM 0
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
// alignment isn't needed for 8-bit AVR
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
|
||||
#else
|
||||
// but must processor needs pointer to be align on word size
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// low value to prevent stack overflow
|
||||
// Limit nesting as the stack is likely to be small
|
||||
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
|
||||
#endif
|
||||
|
||||
#else // assume this is a computer
|
||||
#else // ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
// on a computer we have plenty of memory so we can use doubles
|
||||
// On a computer we have plenty of memory so we can use doubles
|
||||
#ifndef ARDUINOJSON_USE_DOUBLE
|
||||
#define ARDUINOJSON_USE_DOUBLE 1
|
||||
#endif
|
||||
|
||||
// use long long when available
|
||||
// Use long long when available
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#define ARDUINOJSON_USE_LONG_LONG 1
|
||||
@ -81,7 +60,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// use _int64 on old versions of Visual Studio
|
||||
// Use _int64 on old versions of Visual Studio
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
#define ARDUINOJSON_USE_INT64 1
|
||||
@ -90,41 +69,81 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// on a computer, we can use std::string
|
||||
// On a computer, we can use std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
#define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||
#endif
|
||||
|
||||
// on a computer, there is no reason to beleive Arduino String is available
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||
#endif
|
||||
|
||||
// PROGMEM is only available on AVR architecture
|
||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||
#endif
|
||||
|
||||
// on a computer, we can assume that the STL is there
|
||||
// On a computer, we can assume std::stream
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM 1
|
||||
#endif
|
||||
|
||||
// on a computer, there is no reason to beleive Arduino Stream is available
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
// even if not required, most cpu's are faster with aligned pointers
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
// on a computer, we should have a lot of space on the stack
|
||||
// On a computer, the stack is large so we can increase nesting limit
|
||||
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
|
||||
#endif
|
||||
|
||||
#endif // ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
// Enable support for Arduino String
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||
#endif
|
||||
|
||||
// Enable support for Arduino Stream
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
|
||||
#endif
|
||||
|
||||
#else // ARDUINO
|
||||
|
||||
// Disable support for Arduino String
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||
#endif
|
||||
|
||||
// Disable support for Arduino Stream
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
|
||||
#endif
|
||||
|
||||
#endif // ARDUINO
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||
#ifdef PROGMEM
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 1
|
||||
#else
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
// alignment isn't needed for 8-bit AVR
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
|
||||
#else
|
||||
// but most processors need pointers to be align on word size
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Enable deprecated functions by default
|
||||
#ifndef ARDUINOJSON_ENABLE_DEPRECATED
|
||||
#define ARDUINOJSON_ENABLE_DEPRECATED 1
|
||||
#endif
|
||||
|
||||
// Control the exponentiation threshold for big numbers
|
||||
// CAUTION: cannot be more that 1e9 !!!!
|
||||
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
|
||||
#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
|
||||
#endif
|
||||
|
||||
// Control the exponentiation threshold for small numbers
|
||||
#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
|
||||
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
|
@ -1,14 +1,9 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
@ -38,5 +33,5 @@ class Encoding {
|
||||
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -19,7 +16,7 @@ class JsonBufferAllocated {
|
||||
return jsonBuffer->alloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *, JsonBuffer *)throw() {}
|
||||
void operator delete(void *, JsonBuffer *)throw();
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -17,5 +14,5 @@ typedef double JsonFloat;
|
||||
#else
|
||||
typedef float JsonFloat;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -22,5 +19,5 @@ typedef unsigned _int64 JsonUInt;
|
||||
typedef long JsonInteger;
|
||||
typedef unsigned long JsonUInt;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -41,5 +38,5 @@ template <>
|
||||
struct JsonVariantAs<const JsonObject> {
|
||||
typedef const JsonObject& type;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -26,5 +23,5 @@ union JsonVariantContent {
|
||||
JsonArray* asArray; // asArray cannot be null
|
||||
JsonObject* asObject; // asObject cannot be null
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -22,5 +19,5 @@ struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
27
src/ArduinoJson/Data/JsonVariantType.hpp
Normal file
27
src/ArduinoJson/Data/JsonVariantType.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_UNDEFINED, // JsonVariant has not been initialized
|
||||
JSON_UNPARSED, // JsonVariant contains an unparsed string
|
||||
JSON_STRING, // JsonVariant stores a const char*
|
||||
JSON_BOOLEAN, // JsonVariant stores a bool
|
||||
JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt
|
||||
JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated
|
||||
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray
|
||||
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
|
||||
JSON_FLOAT // JsonVariant stores a JsonFloat
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -48,6 +45,20 @@ class List {
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
iterator add() {
|
||||
node_type *newNode = new (_buffer) node_type();
|
||||
|
||||
if (_firstNode) {
|
||||
node_type *lastNode = _firstNode;
|
||||
while (lastNode->next) lastNode = lastNode->next;
|
||||
lastNode->next = newNode;
|
||||
} else {
|
||||
_firstNode = newNode;
|
||||
}
|
||||
|
||||
return iterator(newNode);
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return iterator(_firstNode);
|
||||
}
|
||||
@ -62,22 +73,8 @@ class List {
|
||||
return const_iterator(NULL);
|
||||
}
|
||||
|
||||
protected:
|
||||
node_type *addNewNode() {
|
||||
node_type *newNode = new (_buffer) node_type();
|
||||
|
||||
if (_firstNode) {
|
||||
node_type *lastNode = _firstNode;
|
||||
while (lastNode->next) lastNode = lastNode->next;
|
||||
lastNode->next = newNode;
|
||||
} else {
|
||||
_firstNode = newNode;
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
void removeNode(node_type *nodeToRemove) {
|
||||
void remove(iterator it) {
|
||||
node_type *nodeToRemove = it._node;
|
||||
if (!nodeToRemove) return;
|
||||
if (nodeToRemove == _firstNode) {
|
||||
_firstNode = nodeToRemove->next;
|
||||
@ -87,8 +84,11 @@ class List {
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonBuffer *_buffer;
|
||||
|
||||
private:
|
||||
node_type *_firstNode;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -38,8 +35,16 @@ class ListConstIterator {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -13,9 +10,14 @@
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename T>
|
||||
class List;
|
||||
|
||||
// A read-write forward iterator for List<T>
|
||||
template <typename T>
|
||||
class ListIterator {
|
||||
friend class List<T>;
|
||||
|
||||
public:
|
||||
explicit ListIterator(ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
@ -39,6 +41,14 @@ class ListIterator {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator ListConstIterator<T>() const {
|
||||
return ListConstIterator<T>(_node);
|
||||
}
|
||||
@ -46,5 +56,5 @@ class ListIterator {
|
||||
private:
|
||||
ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -18,10 +15,10 @@ namespace Internals {
|
||||
// Used by List<T> and its iterators.
|
||||
template <typename T>
|
||||
struct ListNode : public Internals::JsonBufferAllocated {
|
||||
ListNode() : next(NULL) {}
|
||||
ListNode() throw() : next(NULL) {}
|
||||
|
||||
ListNode<T> *next;
|
||||
T content;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
23
src/ArduinoJson/Data/NonCopyable.hpp
Normal file
23
src/ArduinoJson/Data/NonCopyable.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A type that cannot be copied
|
||||
class NonCopyable {
|
||||
protected:
|
||||
NonCopyable() {}
|
||||
|
||||
private:
|
||||
// copy constructor is private
|
||||
NonCopyable(const NonCopyable&);
|
||||
|
||||
// copy operator is private
|
||||
NonCopyable& operator=(const NonCopyable&);
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -22,16 +19,6 @@ class ReferenceType {
|
||||
bool operator!=(const ReferenceType& other) const {
|
||||
return this != &other;
|
||||
}
|
||||
|
||||
protected:
|
||||
ReferenceType() {}
|
||||
|
||||
private:
|
||||
// copy constructor is private
|
||||
ReferenceType(const ReferenceType&);
|
||||
|
||||
// copy operator is private
|
||||
ReferenceType& operator=(const ReferenceType&);
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
52
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
52
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename Source, typename Enable = void>
|
||||
struct ValueSaver {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& destination, Source source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
struct ValueSaver<
|
||||
Source, typename EnableIf<StringTraits<Source>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer* buffer, Destination& dest, Source source) {
|
||||
if (!StringTraits<Source>::is_null(source)) {
|
||||
typename StringTraits<Source>::duplicate_t dup =
|
||||
StringTraits<Source>::duplicate(source, buffer);
|
||||
if (!dup) return false;
|
||||
dest = dup;
|
||||
} else {
|
||||
dest = reinterpret_cast<const char*>(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// const char*, const signed char*, const unsigned char*
|
||||
template <typename Char>
|
||||
struct ValueSaver<
|
||||
Char*, typename EnableIf<!StringTraits<Char*>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& dest, Char* source) {
|
||||
dest = reinterpret_cast<const char*>(source);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
61
src/ArduinoJson/Deserialization/Comments.hpp
Normal file
61
src/ArduinoJson/Deserialization/Comments.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TInput>
|
||||
void skipSpacesAndComments(TInput& input) {
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
input.move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
switch (input.next()) {
|
||||
// C-style block comment
|
||||
case '*':
|
||||
input.move(); // skip '/'
|
||||
// no need to skip '*'
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '*' && input.next() == '/') {
|
||||
input.move(); // skip '*'
|
||||
input.move(); // skip '/'
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// C++-style line comment
|
||||
case '/':
|
||||
// not need to skip "//"
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '\n') break;
|
||||
}
|
||||
break;
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,15 +1,12 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "StringReader.hpp"
|
||||
#include "../TypeTraits/IsConst.hpp"
|
||||
#include "StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
@ -47,19 +44,18 @@ class JsonParser {
|
||||
|
||||
const char *parseString();
|
||||
bool parseAnythingTo(JsonVariant *destination);
|
||||
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
|
||||
|
||||
inline bool parseArrayTo(JsonVariant *destination);
|
||||
inline bool parseObjectTo(JsonVariant *destination);
|
||||
inline bool parseStringTo(JsonVariant *destination);
|
||||
|
||||
static inline bool isInRange(char c, char min, char max) {
|
||||
static inline bool isBetween(char c, char min, char max) {
|
||||
return min <= c && c <= max;
|
||||
}
|
||||
|
||||
static inline bool isLetterOrNumber(char c) {
|
||||
return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
|
||||
isInRange(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
|
||||
static inline bool canBeInNonQuotedString(char c) {
|
||||
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
|
||||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) {
|
||||
@ -72,25 +68,27 @@ class JsonParser {
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString>
|
||||
template <typename TJsonBuffer, typename TString, typename Enable = void>
|
||||
struct JsonParserBuilder {
|
||||
typedef typename Internals::StringTraits<TString>::Iterator InputIterator;
|
||||
typedef JsonParser<StringReader<InputIterator>, TJsonBuffer &> TParser;
|
||||
typedef typename StringTraits<TString>::Reader InputReader;
|
||||
typedef JsonParser<InputReader, TJsonBuffer &> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TString &json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputIterator(json), *buffer, nestingLimit);
|
||||
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer>
|
||||
struct JsonParserBuilder<TJsonBuffer, char *> {
|
||||
typedef typename Internals::StringTraits<char *>::Iterator InputIterator;
|
||||
typedef JsonParser<StringReader<InputIterator>, StringWriter> TParser;
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct JsonParserBuilder<TJsonBuffer, TChar *,
|
||||
typename EnableIf<!IsConst<TChar>::value>::type> {
|
||||
typedef typename StringTraits<TChar *>::Reader TReader;
|
||||
typedef StringWriter<TChar> TWriter;
|
||||
typedef JsonParser<TReader, TWriter> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, char *json,
|
||||
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputIterator(json), json, nestingLimit);
|
||||
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
@ -100,5 +98,5 @@ inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
|
||||
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
|
||||
nestingLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -16,7 +13,6 @@ inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
|
||||
skipSpacesAndComments(reader);
|
||||
if (reader.current() != charToSkip) return false;
|
||||
reader.move();
|
||||
skipSpacesAndComments(reader);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -24,17 +20,6 @@ template <typename TReader, typename TWriter>
|
||||
inline bool
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingTo(
|
||||
JsonVariant *destination) {
|
||||
if (_nestingLimit == 0) return false;
|
||||
_nestingLimit--;
|
||||
bool success = parseAnythingToUnsafe(destination);
|
||||
_nestingLimit++;
|
||||
return success;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingToUnsafe(
|
||||
JsonVariant *destination) {
|
||||
skipSpacesAndComments(_reader);
|
||||
|
||||
switch (_reader.current()) {
|
||||
@ -52,6 +37,9 @@ ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingToUnsafe(
|
||||
template <typename TReader, typename TWriter>
|
||||
inline ArduinoJson::JsonArray &
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray() {
|
||||
if (_nestingLimit == 0) return JsonArray::invalid();
|
||||
_nestingLimit--;
|
||||
|
||||
// Create an empty array
|
||||
JsonArray &array = _buffer->createArray();
|
||||
|
||||
@ -73,6 +61,7 @@ ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray() {
|
||||
|
||||
SUCCESS_EMPTY_ARRAY:
|
||||
SUCCES_NON_EMPTY_ARRAY:
|
||||
_nestingLimit++;
|
||||
return array;
|
||||
|
||||
ERROR_INVALID_VALUE:
|
||||
@ -95,6 +84,9 @@ inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArrayTo(
|
||||
template <typename TReader, typename TWriter>
|
||||
inline ArduinoJson::JsonObject &
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject() {
|
||||
if (_nestingLimit == 0) return JsonObject::invalid();
|
||||
_nestingLimit--;
|
||||
|
||||
// Create an empty object
|
||||
JsonObject &object = _buffer->createObject();
|
||||
|
||||
@ -121,6 +113,7 @@ ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject() {
|
||||
|
||||
SUCCESS_EMPTY_OBJECT:
|
||||
SUCCESS_NON_EMPTY_OBJECT:
|
||||
_nestingLimit++;
|
||||
return object;
|
||||
|
||||
ERROR_INVALID_KEY:
|
||||
@ -145,9 +138,9 @@ inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObjectTo(
|
||||
template <typename TReader, typename TWriter>
|
||||
inline const char *
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
|
||||
typename TypeTraits::RemoveReference<TWriter>::type::String str =
|
||||
_writer.startString();
|
||||
typename RemoveReference<TWriter>::type::String str = _writer.startString();
|
||||
|
||||
skipSpacesAndComments(_reader);
|
||||
char c = _reader.current();
|
||||
|
||||
if (isQuote(c)) { // quotes
|
||||
@ -171,7 +164,7 @@ ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
|
||||
}
|
||||
} else { // no quotes
|
||||
for (;;) {
|
||||
if (!isLetterOrNumber(c)) break;
|
||||
if (!canBeInNonQuotedString(c)) break;
|
||||
_reader.move();
|
||||
str.append(c);
|
||||
c = _reader.current();
|
41
src/ArduinoJson/Deserialization/StringWriter.hpp
Normal file
41
src/ArduinoJson/Deserialization/StringWriter.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TChar>
|
||||
class StringWriter {
|
||||
public:
|
||||
class String {
|
||||
public:
|
||||
String(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
|
||||
|
||||
void append(char c) {
|
||||
*(*_writePtr)++ = TChar(c);
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
*(*_writePtr)++ = 0;
|
||||
return reinterpret_cast<const char*>(_startPtr);
|
||||
}
|
||||
|
||||
private:
|
||||
TChar** _writePtr;
|
||||
TChar* _startPtr;
|
||||
};
|
||||
|
||||
StringWriter(TChar* buffer) : _ptr(buffer) {}
|
||||
|
||||
String startString() {
|
||||
return String(&_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
TChar* _ptr;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -22,6 +19,7 @@
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class DefaultAllocator {
|
||||
public:
|
||||
void* allocate(size_t size) {
|
||||
@ -46,30 +44,41 @@ class DynamicJsonBufferBase
|
||||
};
|
||||
|
||||
public:
|
||||
enum { EmptyBlockSize = sizeof(EmptyBlock) };
|
||||
|
||||
DynamicJsonBufferBase(size_t initialSize = 256)
|
||||
: _head(NULL), _nextBlockCapacity(initialSize) {}
|
||||
|
||||
~DynamicJsonBufferBase() {
|
||||
Block* currentBlock = _head;
|
||||
|
||||
while (currentBlock != NULL) {
|
||||
Block* nextBlock = currentBlock->next;
|
||||
_allocator.deallocate(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
// Gets the number of bytes occupied in the buffer
|
||||
size_t size() const {
|
||||
size_t total = 0;
|
||||
for (const Block* b = _head; b; b = b->next) total += b->size;
|
||||
return total;
|
||||
}
|
||||
|
||||
// Allocates the specified amount of bytes in the buffer
|
||||
virtual void* alloc(size_t bytes) {
|
||||
alignNextAlloc();
|
||||
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
|
||||
}
|
||||
|
||||
// Resets the buffer.
|
||||
// USE WITH CAUTION: this invalidates all previously allocated data
|
||||
void clear() {
|
||||
Block* currentBlock = _head;
|
||||
while (currentBlock != NULL) {
|
||||
_nextBlockCapacity = currentBlock->capacity;
|
||||
Block* nextBlock = currentBlock->next;
|
||||
_allocator.deallocate(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
}
|
||||
_head = 0;
|
||||
}
|
||||
|
||||
class String {
|
||||
public:
|
||||
String(DynamicJsonBufferBase* parent)
|
||||
@ -84,7 +93,7 @@ class DynamicJsonBufferBase
|
||||
char* newStart =
|
||||
static_cast<char*>(_parent->allocInNewBlock(_length + 1));
|
||||
if (_start && newStart) memcpy(newStart, _start, _length);
|
||||
newStart[_length] = c;
|
||||
if (newStart) newStart[_length] = c;
|
||||
_start = newStart;
|
||||
}
|
||||
_length++;
|
||||
@ -98,7 +107,7 @@ class DynamicJsonBufferBase
|
||||
private:
|
||||
DynamicJsonBufferBase* _parent;
|
||||
char* _start;
|
||||
int _length;
|
||||
size_t _length;
|
||||
};
|
||||
|
||||
String startString() {
|
||||
@ -129,7 +138,7 @@ class DynamicJsonBufferBase
|
||||
}
|
||||
|
||||
bool addNewBlock(size_t capacity) {
|
||||
size_t bytes = sizeof(EmptyBlock) + capacity;
|
||||
size_t bytes = EmptyBlockSize + capacity;
|
||||
Block* block = static_cast<Block*>(_allocator.allocate(bytes));
|
||||
if (block == NULL) return false;
|
||||
block->capacity = capacity;
|
||||
@ -143,6 +152,7 @@ class DynamicJsonBufferBase
|
||||
Block* _head;
|
||||
size_t _nextBlockCapacity;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
@ -155,5 +165,6 @@ class DynamicJsonBufferBase
|
||||
// Implements a JsonBuffer with dynamic memory allocation.
|
||||
// You are strongly encouraged to consider using StaticJsonBuffer which is much
|
||||
// more suitable for embedded systems.
|
||||
typedef DynamicJsonBufferBase<DefaultAllocator> DynamicJsonBuffer;
|
||||
}
|
||||
typedef Internals::DynamicJsonBufferBase<Internals::DefaultAllocator>
|
||||
DynamicJsonBuffer;
|
||||
} // namespace ArduinoJson
|
@ -1,16 +1,13 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonBufferAllocated.hpp"
|
||||
#include "Data/List.hpp"
|
||||
#include "Data/ReferenceType.hpp"
|
||||
#include "Data/ValueSetter.hpp"
|
||||
#include "Data/ValueSaver.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
@ -29,7 +26,9 @@ namespace ArduinoJson {
|
||||
// Forward declarations
|
||||
class JsonObject;
|
||||
class JsonBuffer;
|
||||
namespace Internals {
|
||||
class JsonArraySubscript;
|
||||
}
|
||||
|
||||
// An array of JsonVariant.
|
||||
//
|
||||
@ -39,73 +38,68 @@ class JsonArraySubscript;
|
||||
// It can also be deserialized from a JSON string via JsonBuffer::parseArray().
|
||||
class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
public Internals::ReferenceType,
|
||||
public Internals::NonCopyable,
|
||||
public Internals::List<JsonVariant>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
public:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not call this constructor directly.
|
||||
// Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray().
|
||||
explicit JsonArray(JsonBuffer *buffer)
|
||||
explicit JsonArray(JsonBuffer *buffer) throw()
|
||||
: Internals::List<JsonVariant>(buffer) {}
|
||||
|
||||
// Gets the value at the specified index
|
||||
JsonVariant operator[](size_t index) const {
|
||||
return get<JsonVariant>(index);
|
||||
}
|
||||
const Internals::JsonArraySubscript operator[](size_t index) const;
|
||||
|
||||
// Gets or sets the value at specified index
|
||||
JsonArraySubscript operator[](size_t index);
|
||||
Internals::JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type add(
|
||||
const T &value) {
|
||||
bool add(const T &value) {
|
||||
return add_impl<const T &>(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool add(const T *value) {
|
||||
return add_impl<const T *>(value);
|
||||
bool add(T *value) {
|
||||
return add_impl<T *>(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue value, uint8_t decimals);
|
||||
// TValue = float, double
|
||||
template <typename T>
|
||||
bool add(T value, uint8_t decimals) {
|
||||
return add_impl<const JsonVariant &>(JsonVariant(value, decimals));
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
bool add(T value, uint8_t) {
|
||||
return add_impl<const JsonVariant &>(JsonVariant(value));
|
||||
}
|
||||
|
||||
// Sets the value at specified index.
|
||||
//
|
||||
// bool add(size_t index, TValue);
|
||||
// bool add(size_t index, const TValue&);
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type set(
|
||||
size_t index, const T &value) {
|
||||
bool set(size_t index, const T &value) {
|
||||
return set_impl<const T &>(index, value);
|
||||
}
|
||||
//
|
||||
// bool add(size_t index, TValue);
|
||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool set(size_t index, const T *value) {
|
||||
return set_impl<const T *>(index, value);
|
||||
bool set(size_t index, T *value) {
|
||||
return set_impl<T *>(index, value);
|
||||
}
|
||||
//
|
||||
// bool set(size_t index, TValue value, uint8_t decimals);
|
||||
// TValue = float, double
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||
bool>::type
|
||||
typename Internals::EnableIf<Internals::IsFloatingPoint<T>::value, bool>::type
|
||||
set(size_t index, T value, uint8_t decimals) {
|
||||
return set_impl<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||
}
|
||||
@ -113,16 +107,15 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
// Gets the value at the specified index.
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
|
||||
node_type *node = findNode(index);
|
||||
return node ? node->content.as<T>()
|
||||
: Internals::JsonVariantDefault<T>::get();
|
||||
const_iterator it = begin() += index;
|
||||
return it != end() ? it->as<T>() : Internals::JsonVariantDefault<T>::get();
|
||||
}
|
||||
|
||||
// Check the type of the value at specified index.
|
||||
template <typename T>
|
||||
bool is(size_t index) const {
|
||||
node_type *node = findNode(index);
|
||||
return node ? node->content.is<T>() : false;
|
||||
const_iterator it = begin() += index;
|
||||
return it != end() ? it->is<T>() : false;
|
||||
}
|
||||
|
||||
// Creates a JsonArray and adds a reference at the end of the array.
|
||||
@ -134,9 +127,10 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
JsonObject &createNestedObject();
|
||||
|
||||
// Removes element at specified index.
|
||||
void removeAt(size_t index) {
|
||||
removeNode(findNode(index));
|
||||
void remove(size_t index) {
|
||||
remove(begin() += index);
|
||||
}
|
||||
using Internals::List<JsonVariant>::remove;
|
||||
|
||||
// Returns a reference an invalid JsonArray.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
@ -195,33 +189,30 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
void copyTo(T (&array)[N1][N2]) const {
|
||||
size_t i = 0;
|
||||
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
|
||||
it->asArray().copyTo(array[i++]);
|
||||
it->as<JsonArray>().copyTo(array[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
node_type *findNode(size_t index) const {
|
||||
node_type *node = _firstNode;
|
||||
while (node && index--) node = node->next;
|
||||
return node;
|
||||
#if ARDUINOJSON_ENABLE_DEPRECATED
|
||||
DEPRECATED("use remove() instead")
|
||||
FORCE_INLINE void removeAt(size_t index) {
|
||||
return remove(index);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
template <typename TValueRef>
|
||||
bool set_impl(size_t index, TValueRef value) {
|
||||
node_type *node = findNode(index);
|
||||
if (!node) return false;
|
||||
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content,
|
||||
value);
|
||||
iterator it = begin() += index;
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
|
||||
}
|
||||
|
||||
template <typename TValueRef>
|
||||
bool add_impl(TValueRef value) {
|
||||
node_type *node = addNewNode();
|
||||
if (!node) return false;
|
||||
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content,
|
||||
value);
|
||||
iterator it = Internals::List<JsonVariant>::add();
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
|
||||
}
|
||||
};
|
||||
|
||||
@ -232,5 +223,5 @@ struct JsonVariantDefault<JsonArray> {
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -26,4 +23,4 @@ inline JsonObject &JsonArray::createNestedObject() {
|
||||
add(object);
|
||||
return object;
|
||||
}
|
||||
}
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -16,6 +13,7 @@
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
public:
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
|
||||
@ -28,10 +26,9 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// operator=(TValue)
|
||||
// operator=(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
|
||||
_array.set(_index, src);
|
||||
@ -39,9 +36,9 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
}
|
||||
//
|
||||
// operator=(TValue)
|
||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const T* src) {
|
||||
FORCE_INLINE JsonArraySubscript& operator=(T* src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
@ -51,7 +48,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const {
|
||||
FORCE_INLINE typename JsonVariantAs<T>::type as() const {
|
||||
return _array.get<T>(_index);
|
||||
}
|
||||
|
||||
@ -62,27 +59,27 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// bool set(TValue)
|
||||
// bool set(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue& value) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue)
|
||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue* value) {
|
||||
FORCE_INLINE bool set(TValue* value) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue, uint8_t decimals);
|
||||
// TValue = float, double
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue& value, uint8_t decimals) {
|
||||
return _array.set(_index, value, decimals);
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
FORCE_INLINE bool set(const TValue& value, uint8_t) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -90,28 +87,34 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
inline const JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) const {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
const JsonArraySubscript& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
} // namespace Internals
|
||||
|
||||
inline JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||
return JsonArraySubscript(*this, index);
|
||||
inline Internals::JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||
return Internals::JsonArraySubscript(*this, index);
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline JsonArraySubscript JsonVariantBase<TImplem>::operator[](int index) {
|
||||
return asArray()[index];
|
||||
inline const Internals::JsonArraySubscript JsonArray::operator[](
|
||||
size_t index) const {
|
||||
return Internals::JsonArraySubscript(*const_cast<JsonArray*>(this), index);
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
|
||||
int index) const {
|
||||
return asArray()[index];
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#ifdef _MSC_VER
|
@ -1,9 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -11,20 +8,11 @@
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <string.h>
|
||||
|
||||
#include "Data/NonCopyable.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsArray.hpp"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
@ -34,13 +22,8 @@ class JsonObject;
|
||||
// Handle the memory management (done in derived classes) and calls the parser.
|
||||
// This abstract class is implemented by StaticJsonBuffer which implements a
|
||||
// fixed memory allocation.
|
||||
class JsonBuffer {
|
||||
class JsonBuffer : Internals::NonCopyable {
|
||||
public:
|
||||
// CAUTION: NO VIRTUAL DESTRUCTOR!
|
||||
// If we add a virtual constructor the Arduino compiler will add malloc() and
|
||||
// free() to the binary, adding 706 useless bytes.
|
||||
// virtual ~JsonBuffer() {}
|
||||
|
||||
// Allocates an empty JsonArray.
|
||||
//
|
||||
// Returns a reference to the new JsonArray or JsonArray::invalid() if the
|
||||
@ -55,20 +38,21 @@ class JsonBuffer {
|
||||
|
||||
// Duplicates a string
|
||||
//
|
||||
// char* strdup(TValue);
|
||||
// const char* strdup(TValue);
|
||||
// TValue = const std::string&, const String&,
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
char *>::type
|
||||
strdup(const TString &src) {
|
||||
DEPRECATED("char* are duplicated, you don't need strdup() anymore")
|
||||
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
|
||||
const char *>::type strdup(const TString &src) {
|
||||
return Internals::StringTraits<TString>::duplicate(src, this);
|
||||
}
|
||||
//
|
||||
// char* strdup(TValue);
|
||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
||||
// const char* strdup(TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TString>
|
||||
char *strdup(const TString *src) {
|
||||
return Internals::StringTraits<const TString *>::duplicate(src, this);
|
||||
DEPRECATED("char* are duplicated, you don't need strdup() anymore")
|
||||
const char *strdup(TString *src) {
|
||||
return Internals::StringTraits<TString *>::duplicate(src, this);
|
||||
}
|
||||
|
||||
// Allocates n bytes in the JsonBuffer.
|
||||
@ -76,6 +60,11 @@ class JsonBuffer {
|
||||
virtual void *alloc(size_t size) = 0;
|
||||
|
||||
protected:
|
||||
// CAUTION: NO VIRTUAL DESTRUCTOR!
|
||||
// If we add a virtual constructor the Arduino compiler will add malloc()
|
||||
// and free() to the binary, adding 706 useless bytes.
|
||||
~JsonBuffer() {}
|
||||
|
||||
// Preserve aligment if necessary
|
||||
static FORCE_INLINE size_t round_size_up(size_t bytes) {
|
||||
#if ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
@ -86,12 +75,4 @@ class JsonBuffer {
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
} // namespace ArduinoJson
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user