mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-04 22:26:39 +02:00
Compare commits
91 Commits
Author | SHA1 | Date | |
---|---|---|---|
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/
|
||||
|
66
.travis.yml
66
.travis.yml
@ -7,103 +7,89 @@ 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 SANITIZE=undefined
|
||||
- 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
|
||||
- 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
|
||||
env: SCRIPT=cmake CLANG=3.8 SANITIZE=undefined
|
||||
- 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
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake-osx
|
||||
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
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
|
@ -1,8 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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 "include/ArduinoJson.h"
|
||||
#include "src/ArduinoJson.h"
|
||||
|
326
CHANGELOG.md
326
CHANGELOG.md
@ -1,6 +1,131 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v5.12.0
|
||||
-------
|
||||
|
||||
* Added `JsonVariant::operator|` to return a default value (see bellow)
|
||||
* 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 +141,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 +190,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 +301,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 +317,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 +374,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 +431,7 @@ 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).
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> API changed significantly since v3, see [Migrating code to the new API](https://arduinojson.org/doc/migration/).
|
||||
|
||||
|
||||
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
|
||||
|
@ -1,25 +1,16 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2017
|
||||
# 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)
|
75
README.md
75
README.md
@ -1,8 +1,10 @@
|
||||
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)
|
||||
|
||||

|
||||
|
||||
ArduinoJson - C++ JSON library for IoT
|
||||
====================
|
||||
|
||||
*An elegant and efficient JSON library for embedded systems.*
|
||||
|
||||
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).
|
||||
@ -23,20 +25,21 @@ Features
|
||||
* Small footprint
|
||||
* Header-only library
|
||||
* MIT License
|
||||
* [Comprehensive documentation](https://arduinojson.org)
|
||||
|
||||
Works on
|
||||
--------
|
||||
|
||||
* All Arduino boards (Uno, Due, Mini, Micro, Yun...)
|
||||
* ESP8266
|
||||
* Arduino boards: Uno, Due, Mini, Micro, Yun...
|
||||
* ESP8266, ESP32
|
||||
* Teensy
|
||||
* Intel Edison and Galileo
|
||||
* PlatformIO
|
||||
* Energia
|
||||
* RedBearLab boards (BLE Nano...)
|
||||
* Computers (Windows, Linux, OSX...)
|
||||
|
||||
See [FAQ: Compatibility issues](https://github.com/bblanchon/ArduinoJson/wiki/Compatibility-issues)
|
||||
* Intel Edison and Galileo
|
||||
* WeMos boards: D1...
|
||||
* Computers: Windows, Linux, OSX...
|
||||
* PlatformIO
|
||||
* Particle
|
||||
* Energia
|
||||
|
||||
Quick start
|
||||
-----------
|
||||
@ -56,7 +59,9 @@ double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
```
|
||||
|
||||
[See JsonParserExample.ino](examples/JsonParserExample/JsonParserExample.ino)
|
||||
[See JsonParserExample.ino](https://arduinojson.org/example/parser/)
|
||||
|
||||
Use [ArduinoJson Assistant](https://arduinojson.org/assistant/) to compute the buffer size.
|
||||
|
||||
#### Encoding / Generating
|
||||
|
||||
@ -68,48 +73,26 @@ 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 JsonGeneratorExample.ino](https://arduinojson.org/example/generator/)
|
||||
|
||||
Use [ArduinoJson Assistant](https://arduinojson.org/assistant/) to compute the buffer size.
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The documentation is available online in the [Arduino JSON wiki](https://github.com/bblanchon/ArduinoJson/wiki)
|
||||
The documentation is available online in the [ArduinoJson Website](https://arduinojson.org/).
|
||||
|
||||
Testimonials
|
||||
------------
|
||||
The [ArduinoJson Assistant](https://arduinojson.org/assistant/) helps you get started with the library.
|
||||
|
||||
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
|
||||
--------
|
||||
@ -133,6 +116,16 @@ Special thanks to the following persons and companies who made generous donation
|
||||
* 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'>
|
||||
* Christoph Schmidt <img alt='Germany' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e9-1f1ea.svg' width='18' height='18'>
|
||||
* OpenEVSE LLC <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Prokhoryatov Alexey <img alt='Russia' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f7-1f1fa.svg' width='18' height='18'>
|
||||
* Google Inc. <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Charles Haynes <img alt='Australia' src='https://d1j8pt39hxlh3d.cloudfront.net/development/emojione/2.2/989/2546.svg' width='18' height='18'>
|
||||
* Charles Walker <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Günther Jehle <img alt='Liechtenstein' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1ee.svg' width='18' height='18'>
|
||||
* Patrick Elliott
|
||||
* Alexander Wilms <img alt='Germany' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e9-1f1ea.svg' width='18' height='18'>
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
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/)
|
||||
2. Search in the [API Reference](https://arduinojson.org/api/)
|
||||
|
||||
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.12.0.{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-2017
|
||||
// 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
|
||||
// --------
|
||||
//
|
||||
// The website 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.
|
||||
// Please check it out at: https://arduinojson.org/
|
||||
//
|
||||
// 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.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
@ -1,29 +1,27 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// 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
|
||||
// --------
|
||||
//
|
||||
// The website arduinojson.org contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
// Please check it out at: https://arduinojson.org/
|
||||
//
|
||||
// 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.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
@ -1,184 +1,112 @@
|
||||
// Sample Arduino Json Web Client
|
||||
// Downloads and parse http://jsonplaceholder.typicode.com/users/1
|
||||
//
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// 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 adapter 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
|
||||
// --------
|
||||
//
|
||||
// The website arduinojson.org contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
// Please check it out at: https://arduinojson.org/
|
||||
//
|
||||
// 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.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
@ -1,29 +1,27 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// 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
|
||||
// --------
|
||||
//
|
||||
// The website arduinojson.org contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// deserialization problem.
|
||||
// Please check it out at: https://arduinojson.org/
|
||||
//
|
||||
// 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.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
@ -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-2017
|
||||
// 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 adapter 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
|
||||
// --------
|
||||
//
|
||||
// The website arduinojson.org contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
// Please check it out at: https://arduinojson.org/
|
||||
//
|
||||
// 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.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
@ -1,55 +1,101 @@
|
||||
// Send a JSON object on UDP at regular interval
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// You can easily test this program with netcat:
|
||||
// $ nc -ulp 8888
|
||||
// This example shows how to 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
|
||||
// --------
|
||||
//
|
||||
// The website arduinojson.org contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
// Please check it out at: https://arduinojson.org/
|
||||
//
|
||||
// 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.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
@ -1,21 +1,19 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// 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.
|
||||
@ -54,3 +52,16 @@ void setup() {
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// The website arduinojson.org contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any memory
|
||||
// problem.
|
||||
// Please check it out at: https://arduinojson.org/
|
||||
//
|
||||
// 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.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
@ -1,19 +1,15 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// 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;
|
||||
|
||||
@ -61,3 +57,15 @@ void setup() {
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// The website arduinojson.org contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any problem.
|
||||
// Please check it out at: https://arduinojson.org/
|
||||
//
|
||||
// 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.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
@ -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 +1,9 @@
|
||||
#!/bin/bash
|
||||
# This script mimics an invocation from https://github.com/google/oss-fuzz
|
||||
|
||||
cd $(dirname $0)
|
||||
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
|
||||
./json_fuzzer my_corpus seed_corpus -max_len=1024 -timeout=10
|
||||
|
@ -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,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,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,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,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,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 "../Configuration.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TString, typename Enable = void>
|
||||
struct StringTraits {};
|
||||
|
||||
template <typename TString>
|
||||
struct StringTraits<const TString, void> : StringTraits<TString> {};
|
||||
|
||||
template <typename TString>
|
||||
struct StringTraits<TString&, void> : StringTraits<TString> {};
|
||||
}
|
||||
}
|
||||
|
||||
#include "CharPointer.hpp"
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STRING || ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#include "StdString.hpp"
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include "StdStream.hpp"
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#include "ArduinoStream.hpp"
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||
#include "FlashString.hpp"
|
||||
#endif
|
@ -6,14 +6,14 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"version": "5.8.1",
|
||||
"version": "5.12.0",
|
||||
"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,9 @@
|
||||
name=ArduinoJson
|
||||
version=5.8.1
|
||||
version=5.12.0
|
||||
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/
|
||||
architectures=*
|
||||
|
@ -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,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
|
||||
|
@ -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,30 @@
|
||||
#!/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"
|
||||
fi
|
||||
|
||||
$CMAKE .
|
||||
$CMAKE --build .
|
||||
$CTEST --output-on-failure .
|
||||
|
@ -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-2017
|
||||
// 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,12 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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 "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/JsonVariantComparisons.hpp"
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
|
||||
@ -19,5 +15,3 @@
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
@ -1,20 +1,27 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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 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 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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 {
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -19,7 +16,7 @@ class JsonBufferAllocated {
|
||||
return jsonBuffer->alloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *, JsonBuffer *)throw() {}
|
||||
void operator delete(void *, JsonBuffer *)throw();
|
||||
};
|
||||
}
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -20,20 +17,11 @@ enum JsonVariantType {
|
||||
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_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
|
||||
|
||||
// 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
|
||||
// ...
|
||||
JSON_FLOAT // JsonVariant stores a JsonFloat
|
||||
};
|
||||
}
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -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,7 +84,10 @@ class List {
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonBuffer *_buffer;
|
||||
|
||||
private:
|
||||
node_type *_firstNode;
|
||||
};
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -38,6 +35,14 @@ class ListConstIterator {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const ListNode<T> *_node;
|
||||
};
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -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);
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -18,7 +15,7 @@ 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;
|
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-2017
|
||||
// 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&);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -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&);
|
||||
};
|
||||
}
|
||||
}
|
48
src/ArduinoJson/Data/ValueSetter.hpp
Normal file
48
src/ArduinoJson/Data/ValueSetter.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TSourceRef, typename Enable = void>
|
||||
struct ValueSetter {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TSourceRef>
|
||||
struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<StringTraits<
|
||||
TSourceRef>::should_duplicate>::type> {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer* buffer, TDestination& destination,
|
||||
TSourceRef source) {
|
||||
const char* copy = buffer->strdup(source);
|
||||
if (!copy) return false;
|
||||
destination = copy;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TSourceRef>
|
||||
struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<!StringTraits<
|
||||
TSourceRef>::should_duplicate>::type> {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
|
||||
// unsigned char* -> char*
|
||||
destination = reinterpret_cast<const char*>(source);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
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-2017
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +1,12 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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 "StringReader.hpp"
|
||||
#include "../TypeTraits/IsConst.hpp"
|
||||
#include "StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
@ -72,25 +69,28 @@ 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 Internals::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 TypeTraits::EnableIf<!TypeTraits::IsConst<TChar>::value>::type> {
|
||||
typedef typename Internals::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);
|
||||
}
|
||||
};
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -148,6 +144,7 @@ ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
|
||||
typename TypeTraits::RemoveReference<TWriter>::type::String str =
|
||||
_writer.startString();
|
||||
|
||||
skipSpacesAndComments(_reader);
|
||||
char c = _reader.current();
|
||||
|
||||
if (isQuote(c)) { // quotes
|
@ -1,43 +1,41 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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 TChar>
|
||||
class StringWriter {
|
||||
public:
|
||||
class String {
|
||||
public:
|
||||
String(char** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
|
||||
String(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
|
||||
|
||||
void append(char c) {
|
||||
*(*_writePtr)++ = c;
|
||||
*(*_writePtr)++ = TChar(c);
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
*(*_writePtr)++ = 0;
|
||||
return _startPtr;
|
||||
return reinterpret_cast<const char*>(_startPtr);
|
||||
}
|
||||
|
||||
private:
|
||||
char** _writePtr;
|
||||
char* _startPtr;
|
||||
TChar** _writePtr;
|
||||
TChar* _startPtr;
|
||||
};
|
||||
|
||||
StringWriter(char* buffer) : _ptr(buffer) {}
|
||||
StringWriter(TChar* buffer) : _ptr(buffer) {}
|
||||
|
||||
String startString() {
|
||||
return String(&_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
char* _ptr;
|
||||
TChar* _ptr;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -46,30 +43,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 +92,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 +106,7 @@ class DynamicJsonBufferBase
|
||||
private:
|
||||
DynamicJsonBufferBase* _parent;
|
||||
char* _start;
|
||||
int _length;
|
||||
size_t _length;
|
||||
};
|
||||
|
||||
String startString() {
|
||||
@ -129,7 +137,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;
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -39,19 +36,18 @@ 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 JsonArraySubscript operator[](size_t index) const;
|
||||
|
||||
// Gets or sets the value at specified index
|
||||
JsonArraySubscript operator[](size_t index);
|
||||
@ -78,8 +74,9 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
// 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.
|
||||
@ -113,16 +110,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 +130,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 +192,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::ValueSetter<TValueRef>::set(_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::ValueSetter<TValueRef>::set(_buffer, *it, value);
|
||||
}
|
||||
};
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -81,8 +78,9 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
// 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:
|
||||
@ -101,15 +99,20 @@ inline JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||
return JsonArraySubscript(*this, index);
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline JsonArraySubscript JsonVariantBase<TImplem>::operator[](int index) {
|
||||
return asArray()[index];
|
||||
inline const JsonArraySubscript JsonArray::operator[](size_t index) const {
|
||||
return JsonArraySubscript(*const_cast<JsonArray*>(this), index);
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
|
||||
int index) const {
|
||||
return asArray()[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];
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -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
|
||||
@ -76,6 +59,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
|
||||
@ -87,11 +75,3 @@ class JsonBuffer {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
@ -1,24 +1,11 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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 "Deserialization/JsonParser.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 {
|
||||
template <typename TDerived>
|
||||
class JsonBufferBase : public JsonBuffer {
|
||||
@ -127,17 +114,12 @@ class JsonBufferBase : public JsonBuffer {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseVariant();
|
||||
}
|
||||
|
||||
protected:
|
||||
~JsonBufferBase() {}
|
||||
|
||||
private:
|
||||
TDerived *that() {
|
||||
return static_cast<TDerived *>(this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -38,13 +35,15 @@ class JsonBuffer;
|
||||
// It can also be deserialized from a JSON string via JsonBuffer::parseObject().
|
||||
class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
public Internals::ReferenceType,
|
||||
public Internals::NonCopyable,
|
||||
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) {}
|
||||
explicit JsonObject(JsonBuffer* buffer) throw()
|
||||
: Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
//
|
||||
@ -66,18 +65,24 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// JsonVariant operator[](TKey) const;
|
||||
// const JsonObjectSubscript 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);
|
||||
typename TypeTraits::EnableIf<
|
||||
!TypeTraits::IsArray<TString>::value,
|
||||
const JsonObjectSubscript<const TString&> >::type
|
||||
operator[](const TString& key) const {
|
||||
return JsonObjectSubscript<const TString&>(*const_cast<JsonObject*>(this),
|
||||
key);
|
||||
}
|
||||
//
|
||||
// JsonVariant operator[](TKey) const;
|
||||
// const JsonObjectSubscript 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);
|
||||
const JsonObjectSubscript<const TString*> operator[](
|
||||
const TString* key) const {
|
||||
return JsonObjectSubscript<const TString*>(*const_cast<JsonObject*>(this),
|
||||
key);
|
||||
}
|
||||
|
||||
// Sets the specified key with the specified value.
|
||||
@ -128,23 +133,25 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = float, double
|
||||
template <typename TValue, typename TString>
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
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));
|
||||
set(const TString& key, TValue value, uint8_t) {
|
||||
return set_impl<const TString&, const JsonVariant&>(key,
|
||||
JsonVariant(value));
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue, uint8_t decimals);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = float, double
|
||||
template <typename TValue, typename TString>
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
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));
|
||||
set(const TString* key, TValue value, uint8_t) {
|
||||
return set_impl<const TString*, const JsonVariant&>(key,
|
||||
JsonVariant(value));
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
@ -241,14 +248,14 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
bool>::type
|
||||
containsKey(const TString& key) const {
|
||||
return findNode<const TString&>(key) != NULL;
|
||||
return findKey<const TString&>(key) != end();
|
||||
}
|
||||
//
|
||||
// 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;
|
||||
return findKey<const TString*>(key) != end();
|
||||
}
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
@ -259,15 +266,18 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<TString>::value,
|
||||
void>::type
|
||||
remove(const TString& key) {
|
||||
removeNode(findNode<const TString&>(key));
|
||||
remove(findKey<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));
|
||||
remove(findKey<const TString*>(key));
|
||||
}
|
||||
//
|
||||
// void remove(iterator)
|
||||
using Internals::List<JsonPair>::remove;
|
||||
|
||||
// Returns a reference an invalid JsonObject.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
@ -280,41 +290,44 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
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;
|
||||
iterator findKey(TStringRef key) {
|
||||
iterator it;
|
||||
for (it = begin(); it != end(); ++it) {
|
||||
if (Internals::StringTraits<TStringRef>::equals(key, it->key)) break;
|
||||
}
|
||||
return NULL;
|
||||
return it;
|
||||
}
|
||||
template <typename TStringRef>
|
||||
const_iterator findKey(TStringRef key) const {
|
||||
return const_cast<JsonObject*>(this)->findKey<TStringRef>(key);
|
||||
}
|
||||
|
||||
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();
|
||||
const_iterator it = findKey<TStringRef>(key);
|
||||
return it != end() ? it->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;
|
||||
iterator it = findKey<TStringRef>(key);
|
||||
if (it == end()) {
|
||||
it = Internals::List<JsonPair>::add();
|
||||
if (it == end()) return false;
|
||||
|
||||
bool key_ok = Internals::ValueSetter<TStringRef>::set(
|
||||
_buffer, node->content.key, key);
|
||||
bool key_ok =
|
||||
Internals::ValueSetter<TStringRef>::set(_buffer, it->key, key);
|
||||
if (!key_ok) return false;
|
||||
}
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, node->content.value,
|
||||
value);
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, it->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;
|
||||
const_iterator it = findKey<TStringRef>(key);
|
||||
return it != end() ? it->value.is<TValue>() : false;
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -93,8 +90,9 @@ class JsonObjectSubscript
|
||||
// bool set(TValue, uint8_t decimals);
|
||||
// TValue = float, double
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue& value, uint8_t decimals) {
|
||||
return _object.set(_key, value, decimals);
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
FORCE_INLINE bool set(const TValue& value, uint8_t) {
|
||||
return _object.set(_key, value);
|
||||
}
|
||||
|
||||
private:
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
|
||||
@ -17,6 +14,7 @@
|
||||
#include "RawJson.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsChar.hpp"
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsIntegral.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
@ -39,8 +37,8 @@ class JsonObject;
|
||||
// - a string (const char*)
|
||||
// - a reference to a JsonArray or JsonObject
|
||||
class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
friend void Internals::JsonSerializer::serialize(const JsonVariant &,
|
||||
JsonWriter &);
|
||||
template <typename Print>
|
||||
friend class Internals::JsonSerializer;
|
||||
|
||||
public:
|
||||
// Creates an uninitialized JsonVariant
|
||||
@ -51,31 +49,39 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
JsonVariant(bool value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_BOOLEAN;
|
||||
_content.asInteger = static_cast<JsonInteger>(value);
|
||||
_content.asInteger = static_cast<JsonUInt>(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);
|
||||
// JsonVariant(double value);
|
||||
// JsonVariant(float value);
|
||||
template <typename T>
|
||||
JsonVariant(T value, uint8_t decimals = 2,
|
||||
JsonVariant(T value, typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
||||
using namespace Internals;
|
||||
_type = JSON_FLOAT;
|
||||
_content.asFloat = static_cast<JsonFloat>(value);
|
||||
}
|
||||
template <typename T>
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
JsonVariant(T value, uint8_t,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
||||
using namespace Internals;
|
||||
_type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals);
|
||||
_type = JSON_FLOAT;
|
||||
_content.asFloat = static_cast<JsonFloat>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing an integer value.
|
||||
// JsonVariant(char)
|
||||
// JsonVariant(signed short)
|
||||
// JsonVariant(signed int)
|
||||
// JsonVariant(signed long)
|
||||
// JsonVariant(signed char)
|
||||
template <typename T>
|
||||
JsonVariant(T value,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSignedIntegral<T>::value>::type * = 0) {
|
||||
JsonVariant(T value, typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsSignedIntegral<T>::value ||
|
||||
TypeTraits::IsSame<T, char>::value>::type * = 0) {
|
||||
using namespace Internals;
|
||||
if (value >= 0) {
|
||||
_type = JSON_POSITIVE_INTEGER;
|
||||
@ -98,9 +104,16 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing a string.
|
||||
JsonVariant(const char *value) {
|
||||
// JsonVariant(const char*);
|
||||
// JsonVariant(const signed char*);
|
||||
// JsonVariant(const unsigned char*);
|
||||
template <typename TChar>
|
||||
JsonVariant(
|
||||
const TChar *value,
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsChar<TChar>::value>::type * =
|
||||
0) {
|
||||
_type = Internals::JSON_STRING;
|
||||
_content.asString = value;
|
||||
_content.asString = reinterpret_cast<const char *>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing an unparsed string
|
||||
@ -121,24 +134,26 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
|
||||
// Get the variant as the specified type.
|
||||
//
|
||||
// short as<signed short>() const;
|
||||
// int as<signed int>() const;
|
||||
// long as<signed long>() const;
|
||||
// char as<char>() const;
|
||||
// signed char as<signed char>() const;
|
||||
// signed short as<signed short>() const;
|
||||
// signed int as<signed int>() const;
|
||||
// signed long as<signed long>() const;
|
||||
// unsigned char as<unsigned char>() const;
|
||||
// unsigned short as<unsigned short>() const;
|
||||
// unsigned int as<unsigned int>() const;
|
||||
// unsigned long as<unsigned long>() const;
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsSignedIntegral<T>::value,
|
||||
T>::type
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, T>::type
|
||||
as() const {
|
||||
return static_cast<T>(asInteger());
|
||||
return variantAsInteger<T>();
|
||||
}
|
||||
//
|
||||
// short as<unsigned short>() const;
|
||||
// int as<unsigned int>() const;
|
||||
// long as<unsigned long>() const;
|
||||
// bool as<bool>() const
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsUnsignedIntegral<T>::value,
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return static_cast<T>(asUnsignedInteger());
|
||||
return variantAsInteger<int>() != 0;
|
||||
}
|
||||
//
|
||||
// double as<double>() const;
|
||||
@ -147,7 +162,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return static_cast<T>(asFloat());
|
||||
return variantAsFloat<T>();
|
||||
}
|
||||
//
|
||||
// const char* as<const char*>() const;
|
||||
@ -157,7 +172,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
TypeTraits::IsSame<T, char *>::value,
|
||||
const char *>::type
|
||||
as() const {
|
||||
return asString();
|
||||
return variantAsString();
|
||||
}
|
||||
//
|
||||
// std::string as<std::string>() const;
|
||||
@ -165,21 +180,13 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<Internals::StringTraits<T>::has_append, T>::type
|
||||
as() const {
|
||||
const char *cstr = asString();
|
||||
const char *cstr = variantAsString();
|
||||
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>
|
||||
@ -188,7 +195,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
JsonArray>::value,
|
||||
JsonArray &>::type
|
||||
as() const {
|
||||
return asArray();
|
||||
return variantAsArray();
|
||||
}
|
||||
//
|
||||
// const JsonArray& as<const JsonArray&> const;
|
||||
@ -198,7 +205,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
const JsonArray>::value,
|
||||
const JsonArray &>::type
|
||||
as() const {
|
||||
return asArray();
|
||||
return variantAsArray();
|
||||
}
|
||||
//
|
||||
// JsonObject& as<JsonObject> const;
|
||||
@ -209,7 +216,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
JsonObject>::value,
|
||||
JsonObject &>::type
|
||||
as() const {
|
||||
return asObject();
|
||||
return variantAsObject();
|
||||
}
|
||||
//
|
||||
// JsonObject& as<const JsonObject> const;
|
||||
@ -220,7 +227,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
const JsonObject>::value,
|
||||
const JsonObject &>::type
|
||||
as() const {
|
||||
return asObject();
|
||||
return variantAsObject();
|
||||
}
|
||||
//
|
||||
// JsonVariant as<JsonVariant> const;
|
||||
@ -234,32 +241,35 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
// 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;
|
||||
// bool is<char>() const;
|
||||
// bool is<signed char>() const;
|
||||
// bool is<signed short>() const;
|
||||
// bool is<signed int>() const;
|
||||
// bool is<signed long>() const;
|
||||
// bool is<unsigned char>() const;
|
||||
// bool is<unsigned short>() const;
|
||||
// bool is<unsigned int>() const;
|
||||
// bool is<unsigned long>() const;
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value &&
|
||||
!TypeTraits::IsSame<T, bool>::value,
|
||||
bool>::type
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, bool>::type
|
||||
is() const {
|
||||
return isInteger();
|
||||
return variantIsInteger();
|
||||
}
|
||||
//
|
||||
// double is<double>() const;
|
||||
// float is<float>() const;
|
||||
// bool is<double>() const;
|
||||
// bool is<float>() const;
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||
bool>::type
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isFloat();
|
||||
return variantIsFloat();
|
||||
}
|
||||
//
|
||||
// const bool is<bool>() const
|
||||
// bool is<bool>() const
|
||||
template <typename T>
|
||||
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
||||
bool>::type
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, bool>::type
|
||||
is() const {
|
||||
return isBoolean();
|
||||
return variantIsBoolean();
|
||||
}
|
||||
//
|
||||
// bool is<const char*>() const;
|
||||
@ -269,7 +279,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
TypeTraits::IsSame<T, char *>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isString();
|
||||
return variantIsString();
|
||||
}
|
||||
//
|
||||
// bool is<JsonArray> const;
|
||||
@ -283,7 +293,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
JsonArray>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isArray();
|
||||
return variantIsArray();
|
||||
}
|
||||
//
|
||||
// bool is<JsonObject> const;
|
||||
@ -297,7 +307,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
JsonObject>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return isObject();
|
||||
return variantIsObject();
|
||||
}
|
||||
|
||||
// Returns true if the variant has a value
|
||||
@ -305,34 +315,24 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
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
|
||||
JsonArray &variantAsArray() const;
|
||||
JsonObject &variantAsObject() const;
|
||||
const char *variantAsString() const;
|
||||
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 {
|
||||
T variantAsFloat() const;
|
||||
template <typename T>
|
||||
T variantAsInteger() const;
|
||||
bool variantIsBoolean() const;
|
||||
bool variantIsFloat() const;
|
||||
bool variantIsInteger() const;
|
||||
bool variantIsArray() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
bool isObject() const {
|
||||
bool variantIsObject() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
bool isString() const {
|
||||
bool variantIsString() const {
|
||||
return _type == Internals::JSON_STRING ||
|
||||
(_type == Internals::JSON_UNPARSED && _content.asString &&
|
||||
!strcmp("null", _content.asString));
|
||||
@ -345,11 +345,13 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
Internals::JsonVariantContent _content;
|
||||
};
|
||||
|
||||
inline JsonVariant float_with_n_digits(float value, uint8_t digits) {
|
||||
return JsonVariant(value, digits);
|
||||
DEPRECATED("Decimal places are ignored, use the float value instead")
|
||||
inline JsonVariant float_with_n_digits(float value, uint8_t) {
|
||||
return JsonVariant(value);
|
||||
}
|
||||
|
||||
inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
|
||||
return JsonVariant(value, digits);
|
||||
DEPRECATED("Decimal places are ignored, use the double value instead")
|
||||
inline JsonVariant double_with_n_digits(double value, uint8_t) {
|
||||
return JsonVariant(value);
|
||||
}
|
||||
}
|
22
src/ArduinoJson/JsonVariantBase.hpp
Normal file
22
src/ArduinoJson/JsonVariantBase.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantCasts.hpp"
|
||||
#include "JsonVariantComparisons.hpp"
|
||||
#include "JsonVariantOr.hpp"
|
||||
#include "JsonVariantSubscripts.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantBase : public Internals::JsonPrintable<TImpl>,
|
||||
public JsonVariantCasts<TImpl>,
|
||||
public JsonVariantComparisons<TImpl>,
|
||||
public JsonVariantOr<TImpl>,
|
||||
public JsonVariantSubscripts<TImpl>,
|
||||
public TypeTraits::JsonVariantTag {};
|
||||
}
|
57
src/ArduinoJson/JsonVariantCasts.hpp
Normal file
57
src/ArduinoJson/JsonVariantCasts.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantCasts {
|
||||
public:
|
||||
#if ARDUINOJSON_ENABLE_DEPRECATED
|
||||
DEPRECATED("use as<JsonArray>() instead")
|
||||
FORCE_INLINE JsonArray &asArray() const {
|
||||
return impl()->template as<JsonArray>();
|
||||
}
|
||||
|
||||
DEPRECATED("use as<JsonObject>() instead")
|
||||
FORCE_INLINE JsonObject &asObject() const {
|
||||
return impl()->template as<JsonObject>();
|
||||
}
|
||||
|
||||
DEPRECATED("use as<char*>() instead")
|
||||
FORCE_INLINE const char *asString() const {
|
||||
return impl()->template as<const char *>();
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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 impl()->template 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 impl()->template as<JsonObject &>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE operator T() const {
|
||||
return impl()->template as<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
};
|
||||
}
|
141
src/ArduinoJson/JsonVariantComparisons.hpp
Normal file
141
src/ArduinoJson/JsonVariantComparisons.hpp
Normal file
@ -0,0 +1,141 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantComparisons {
|
||||
public:
|
||||
template <typename TComparand>
|
||||
friend bool operator==(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value,
|
||||
bool>::type
|
||||
operator==(TComparand comparand, const JsonVariantComparisons &variant) {
|
||||
return variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator!=(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return !variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value,
|
||||
bool>::type
|
||||
operator!=(TComparand comparand, const JsonVariantComparisons &variant) {
|
||||
return !variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator<=(const JsonVariantComparisons &left, TComparand right) {
|
||||
return left.as<TComparand>() <= right;
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator<=(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand <= variant.as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator>=(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return variant.as<TComparand>() >= comparand;
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator>=(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand >= variant.as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator<(const JsonVariantComparisons &varian,
|
||||
TComparand comparand) {
|
||||
return varian.as<TComparand>() < comparand;
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator<(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand < variant.as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator>(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return variant.as<TComparand>() > comparand;
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator>(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand > variant.as<TComparand>();
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const typename Internals::JsonVariantAs<T>::type as() const {
|
||||
return impl()->template as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return impl()->template is<T>();
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsString<TString>::value,
|
||||
bool>::type
|
||||
equals(const TString &comparand) const {
|
||||
const char *value = as<const char *>();
|
||||
return Internals::StringTraits<TString>::equals(comparand, value);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value &&
|
||||
!TypeTraits::IsString<TComparand>::value,
|
||||
bool>::type
|
||||
equals(const TComparand &comparand) const {
|
||||
return as<TComparand>() == comparand;
|
||||
}
|
||||
|
||||
template <typename TVariant2>
|
||||
bool equals(const JsonVariantComparisons<TVariant2> &right) const {
|
||||
using namespace Internals;
|
||||
if (is<bool>() && right.template is<bool>())
|
||||
return as<bool>() == right.template as<bool>();
|
||||
if (is<JsonInteger>() && right.template is<JsonInteger>())
|
||||
return as<JsonInteger>() == right.template as<JsonInteger>();
|
||||
if (is<JsonFloat>() && right.template is<JsonFloat>())
|
||||
return as<JsonFloat>() == right.template as<JsonFloat>();
|
||||
if (is<JsonArray>() && right.template is<JsonArray>())
|
||||
return as<JsonArray>() == right.template as<JsonArray>();
|
||||
if (is<JsonObject>() && right.template is<JsonObject>())
|
||||
return as<JsonObject>() == right.template as<JsonObject>();
|
||||
if (is<char *>() && right.template is<char *>())
|
||||
return strcmp(as<char *>(), right.template as<char *>()) == 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
126
src/ArduinoJson/JsonVariantImpl.hpp
Normal file
126
src/ArduinoJson/JsonVariantImpl.hpp
Normal file
@ -0,0 +1,126 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Polyfills/isFloat.hpp"
|
||||
#include "Polyfills/isInteger.hpp"
|
||||
#include "Polyfills/parseFloat.hpp"
|
||||
#include "Polyfills/parseInteger.hpp"
|
||||
|
||||
#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::variantAsArray() const {
|
||||
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
inline JsonObject &JsonVariant::variantAsObject() const {
|
||||
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonVariant::variantAsInteger() const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
return 0;
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return T(_content.asInteger);
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return T(~_content.asInteger + 1);
|
||||
case JSON_STRING:
|
||||
case JSON_UNPARSED:
|
||||
return Polyfills::parseInteger<T>(_content.asString);
|
||||
default:
|
||||
return T(_content.asFloat);
|
||||
}
|
||||
}
|
||||
|
||||
inline const char *JsonVariant::variantAsString() 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;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonVariant::variantAsFloat() const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
return 0;
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return static_cast<T>(_content.asInteger);
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return -static_cast<T>(_content.asInteger);
|
||||
case JSON_STRING:
|
||||
case JSON_UNPARSED:
|
||||
return Polyfills::parseFloat<T>(_content.asString);
|
||||
default:
|
||||
return static_cast<T>(_content.asFloat);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool JsonVariant::variantIsBoolean() 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::variantIsInteger() const {
|
||||
using namespace Internals;
|
||||
|
||||
return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER ||
|
||||
(_type == JSON_UNPARSED && Polyfills::isInteger(_content.asString));
|
||||
}
|
||||
|
||||
inline bool JsonVariant::variantIsFloat() const {
|
||||
using namespace Internals;
|
||||
|
||||
return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER ||
|
||||
_type == JSON_NEGATIVE_INTEGER ||
|
||||
(_type == JSON_UNPARSED && Polyfills::isFloat(_content.asString));
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
36
src/ArduinoJson/JsonVariantOr.hpp
Normal file
36
src/ArduinoJson/JsonVariantOr.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantOr {
|
||||
public:
|
||||
// Returns the default value if the JsonVariant is undefined of incompatible
|
||||
template <typename T>
|
||||
T operator|(const T &defaultValue) const {
|
||||
if (impl()->template is<T>())
|
||||
return impl()->template as<T>();
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Returns the default value if the JsonVariant is undefined of incompatible
|
||||
// Special case for string: null is treated as undefined
|
||||
const char *operator|(const char *defaultValue) const {
|
||||
const char *value = impl()->template as<const char *>();
|
||||
return value ? value : defaultValue;
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,15 +1,13 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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"
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
@ -19,60 +17,21 @@ template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||
class JsonVariantSubscripts {
|
||||
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();
|
||||
return impl()->template as<JsonArray>().size() +
|
||||
impl()->template as<JsonObject>().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);
|
||||
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
|
||||
FORCE_INLINE JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is
|
||||
@ -86,27 +45,27 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||
Internals::StringTraits<TString>::has_equals,
|
||||
const JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) const {
|
||||
return asObject()[key];
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
// 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];
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString *>::has_equals,
|
||||
Internals::StringTraits<const TString *>::has_equals,
|
||||
JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) {
|
||||
return asObject()[key];
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
@ -116,7 +75,7 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||
Internals::StringTraits<TString *>::has_equals,
|
||||
const JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) const {
|
||||
return asObject()[key];
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
private:
|
29
src/ArduinoJson/Polyfills/attributes.hpp
Normal file
29
src/ArduinoJson/Polyfills/attributes.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER // Visual Studio
|
||||
|
||||
#define FORCE_INLINE __forceinline
|
||||
#define NO_INLINE __declspec(noinline)
|
||||
#define DEPRECATED(msg) __declspec(deprecated(msg))
|
||||
|
||||
#elif defined(__GNUC__) // GCC or Clang
|
||||
|
||||
#define FORCE_INLINE __attribute__((always_inline))
|
||||
#define NO_INLINE __attribute__((noinline))
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
#define DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||
#else
|
||||
#define DEPRECATED(msg) __attribute__((deprecated))
|
||||
#endif
|
||||
|
||||
#else // Other compilers
|
||||
|
||||
#define FORCE_INLINE
|
||||
#define NO_INLINE
|
||||
#define DEPRECATED(msg)
|
||||
|
||||
#endif
|
18
src/ArduinoJson/Polyfills/ctype.hpp
Normal file
18
src/ArduinoJson/Polyfills/ctype.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Polyfills {
|
||||
|
||||
inline bool isdigit(char c) {
|
||||
return '0' <= c && c <= '9';
|
||||
}
|
||||
|
||||
inline bool issign(char c) {
|
||||
return '-' == c || c == '+';
|
||||
}
|
||||
}
|
||||
}
|
38
src/ArduinoJson/Polyfills/isFloat.hpp
Normal file
38
src/ArduinoJson/Polyfills/isFloat.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
#include "./ctype.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Polyfills {
|
||||
|
||||
inline bool isFloat(const char* s) {
|
||||
if (!s) return false;
|
||||
|
||||
if (!strcmp(s, "NaN")) return true;
|
||||
if (issign(*s)) s++;
|
||||
if (!strcmp(s, "Infinity")) return true;
|
||||
if (*s == '\0') return false;
|
||||
|
||||
while (isdigit(*s)) s++;
|
||||
|
||||
if (*s == '.') {
|
||||
s++;
|
||||
while (isdigit(*s)) s++;
|
||||
}
|
||||
|
||||
if (*s == 'e' || *s == 'E') {
|
||||
s++;
|
||||
if (issign(*s)) s++;
|
||||
if (!isdigit(*s)) return false;
|
||||
while (isdigit(*s)) s++;
|
||||
}
|
||||
|
||||
return *s == '\0';
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user