mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-03 21:57:02 +02:00
Compare commits
148 Commits
v6.2.1-bet
...
v6.11.1
Author | SHA1 | Date | |
---|---|---|---|
a0a451195b | |||
ce247a5637 | |||
59f9c9747f | |||
fec088e3ed | |||
4980ee8fb9 | |||
2ed77d2cc3 | |||
630107ae8a | |||
4eb8074358 | |||
80a02cd90d | |||
7427888e05 | |||
90c1d549a8 | |||
2af003e4e2 | |||
eaf55e174b | |||
0588e578d5 | |||
12f9aac4ea | |||
81bb3fce97 | |||
6011a2f51a | |||
6071bd07ec | |||
1c814d3bb6 | |||
9862048a58 | |||
ebc52a5a65 | |||
eacad922df | |||
d910996613 | |||
2fc220fa33 | |||
8cabda551d | |||
afd033e9c9 | |||
6ec5ba521b | |||
c8e49a7e4e | |||
dee8c8e242 | |||
576543c4b4 | |||
746f2882f7 | |||
c4cbf9d0bb | |||
49bd51b5f9 | |||
e53ae0f9bb | |||
afdd913a2f | |||
3df4efd512 | |||
91dd45c387 | |||
136ee0d576 | |||
1ea8d92cc3 | |||
20fcb99830 | |||
f3265d2111 | |||
d6e7709866 | |||
d11019d9e1 | |||
cfd924622e | |||
27c08b785d | |||
77f38e4449 | |||
16ddfbc4e0 | |||
8dea900869 | |||
f342dee2b4 | |||
1d5721f3bd | |||
3170558d6d | |||
3530aa88d6 | |||
21998890d4 | |||
c9d6bd76c9 | |||
bc2ce178ea | |||
e22e62d184 | |||
4181de119c | |||
56bf24e1ec | |||
e9b4c6289b | |||
7ed92bebd3 | |||
c3f71c1a99 | |||
7050ef675d | |||
070cd5b6c0 | |||
2c2cc33c94 | |||
169c83431c | |||
5f72c68d87 | |||
b184af6d00 | |||
6f55d1e58f | |||
5aea1363cc | |||
0685a36f0e | |||
70739f5cfd | |||
933a66a070 | |||
4167b11434 | |||
2a3b51ac3a | |||
e633292df1 | |||
30b94493bb | |||
c51cc91f92 | |||
8b04046321 | |||
11bb5e26ff | |||
9ac2ac303c | |||
f0784d3b41 | |||
3d8ece8c8b | |||
b0fb71f7d8 | |||
a5cd1b1693 | |||
d8a1eec530 | |||
e20c47c57b | |||
b77b203935 | |||
1ad97ebf85 | |||
ef12c74771 | |||
0bc03e8071 | |||
04286f3228 | |||
1d942cdf41 | |||
aaf0d5c3c5 | |||
04e8acd844 | |||
8ff48dde73 | |||
41b2e629f7 | |||
a60162ba76 | |||
45f4e5ac20 | |||
637f7a5bfa | |||
399ccec645 | |||
2bd280df80 | |||
c832edbda3 | |||
b8d0041851 | |||
0a97d4c825 | |||
5eee947ffe | |||
720e6548c7 | |||
f375459d53 | |||
e842838a23 | |||
00aa038818 | |||
eb78077a0c | |||
d8d939660b | |||
ae089dcff7 | |||
1a4515c0b9 | |||
4eee8e8bdf | |||
9f1421e0a6 | |||
84f199f0dd | |||
8230f8fc9b | |||
02d809f3f4 | |||
b0560cbd99 | |||
d1003ff6c9 | |||
b11ad4077b | |||
5dc7dc1216 | |||
0d4a93018b | |||
3ca40db9f8 | |||
ce607196d1 | |||
0b3af166ae | |||
39e5660c4a | |||
6b985b2d1f | |||
527dc19794 | |||
29e71cbb16 | |||
2d54019f83 | |||
98c8e8e35a | |||
b106b1ed14 | |||
2998a55f0b | |||
e5c4778ff7 | |||
2ec9569b36 | |||
58303d0837 | |||
e3639918eb | |||
6d290bd001 | |||
7683667b3c | |||
9cbc891816 | |||
0454bd1ef6 | |||
f139100b23 | |||
3f666bd5f0 | |||
d53a93e0ae | |||
2059d610a8 | |||
fa1a40ac6e | |||
954428e341 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
custom: https://arduinojson.org/book/
|
126
.travis.yml
126
.travis.yml
@ -2,114 +2,124 @@ sudo: false
|
||||
language: cpp
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
addons:
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.4']
|
||||
env: SCRIPT=test _CC=gcc-4.4 _CXX=g++-4.4
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.6']
|
||||
env: SCRIPT=cmake GCC=4.6
|
||||
- compiler: gcc
|
||||
addons:
|
||||
env: SCRIPT=test _CC=gcc-4.6 _CXX=g++-4.6
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.7']
|
||||
env: SCRIPT=cmake GCC=4.7
|
||||
- compiler: gcc
|
||||
addons:
|
||||
env: SCRIPT=test _CC=gcc-4.7 _CXX=g++-4.7
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.8']
|
||||
env: SCRIPT=cmake GCC=4.8 SANITIZE=address
|
||||
- compiler: gcc
|
||||
addons:
|
||||
env: SCRIPT=test _CC=gcc-4.8 _CXX=g++-4.8 SANITIZE=address
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.9']
|
||||
env: SCRIPT=cmake GCC=4.9 SANITIZE=leak
|
||||
- compiler: gcc
|
||||
addons:
|
||||
env: SCRIPT=test _CC=gcc-4.9 _CXX=g++-4.9 SANITIZE=leak
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5']
|
||||
env: SCRIPT=cmake GCC=5 # SANITIZE=undefined
|
||||
- compiler: gcc
|
||||
addons:
|
||||
env: SCRIPT=test _CC=gcc-5 _CXX=g++-5 # SANITIZE=undefined
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-6']
|
||||
env: SCRIPT=cmake GCC=6
|
||||
- compiler: gcc
|
||||
addons:
|
||||
env: SCRIPT=test _CC=gcc-6 _CXX=g++-6
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-7']
|
||||
env: SCRIPT=cmake GCC=7
|
||||
- compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- compiler: clang
|
||||
addons:
|
||||
env: SCRIPT=test _CC=gcc-7 _CXX=g++-7
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-8']
|
||||
env: SCRIPT=test _CC=gcc-8 _CXX=g++-8
|
||||
- addons:
|
||||
apt:
|
||||
packages: ['g++-arm-linux-gnueabihf']
|
||||
env: SCRIPT=build _CC=arm-linux-gnueabihf-gcc _CXX=arm-linux-gnueabihf-g++
|
||||
- env: SCRIPT=test _CC=clang _CXX=clang++
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5']
|
||||
packages: ['clang-3.5']
|
||||
env: SCRIPT=cmake CLANG=3.5 SANITIZE=address
|
||||
- compiler: clang
|
||||
addons:
|
||||
env: SCRIPT=test _CC=clang-3.5 _CXX=clang++-3.5 SANITIZE=address
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.6']
|
||||
packages: ['clang-3.6']
|
||||
env: SCRIPT=cmake CLANG=3.6 SANITIZE=leak
|
||||
- compiler: clang
|
||||
addons:
|
||||
env: SCRIPT=test _CC=clang-3.6 _CXX=clang++-3.6 SANITIZE=leak
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.7']
|
||||
packages: ['clang-3.7']
|
||||
env: SCRIPT=cmake CLANG=3.7
|
||||
- compiler: clang
|
||||
addons:
|
||||
env: SCRIPT=test _CC=clang-3.7 _CXX=clang++-3.7
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
|
||||
packages: ['clang-3.8']
|
||||
env: SCRIPT=cmake CLANG=3.8 SANITIZE=undefined
|
||||
- compiler: clang
|
||||
addons:
|
||||
env: SCRIPT=test _CC=clang-3.8 _CXX=clang++-3.8 SANITIZE=undefined
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-3.9']
|
||||
packages: ['clang-3.9']
|
||||
env: SCRIPT=cmake CLANG=3.9
|
||||
- compiler: clang
|
||||
addons:
|
||||
env: SCRIPT=test _CC=clang-3.9 _CXX=clang++-3.9
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-4.0']
|
||||
packages: ['clang-4.0']
|
||||
env: SCRIPT=cmake CLANG=4.0
|
||||
- compiler: clang
|
||||
addons:
|
||||
env: SCRIPT=test _CC=clang-4.0 _CXX=clang++-4.0
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-5.0']
|
||||
packages: ['clang-5.0']
|
||||
env: SCRIPT=cmake CLANG=5.0
|
||||
- compiler: clang
|
||||
addons:
|
||||
env: SCRIPT=test _CC=clang-5.0 _CXX=clang++-5.0
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
|
||||
packages: ['clang-6.0']
|
||||
env: SCRIPT=cmake CLANG=6.0
|
||||
- compiler: gcc
|
||||
env: SCRIPT=coverage
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
env: SCRIPT=test _CC=clang-6.0 _CXX=clang++-6.0
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-7']
|
||||
packages: ['clang-7']
|
||||
env: SCRIPT=test _CC=clang-7 _CXX=clang++-7
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-8']
|
||||
packages: ['clang-8']
|
||||
env: SCRIPT=test _CC=clang-8 _CXX=clang++-8
|
||||
- env: SCRIPT=coverage
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake SANITIZE=address
|
||||
env: SCRIPT=test
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
env: SCRIPT=test
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
env: SCRIPT=test
|
||||
- os: osx
|
||||
osx_image: xcode10
|
||||
env: SCRIPT=test SANITIZE=address
|
||||
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:samd:mkr1000
|
||||
- env: SCRIPT=platformio BOARD=uno
|
||||
- env: SCRIPT=platformio BOARD=esp01
|
||||
- compiler: clang
|
||||
addons:
|
||||
- addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
|
||||
packages: ['clang-6.0','llvm-6.0']
|
||||
@ -117,4 +127,6 @@ matrix:
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- "fuzzing/json_corpus"
|
||||
- "fuzzing/msgpack_corpus"
|
||||
script: scripts/travis/$SCRIPT.sh
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include "src/ArduinoJson.h"
|
||||
|
284
CHANGELOG.md
284
CHANGELOG.md
@ -1,15 +1,289 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v6.2.1-beta
|
||||
v6.11.1 (2019-06-21)
|
||||
-------
|
||||
|
||||
* Fixed `serialized()` not working with Flash strings (issue #1030)
|
||||
|
||||
v6.11.0 (2019-05-26)
|
||||
-------
|
||||
|
||||
* Fixed `deserializeJson()` silently accepting a `Stream*` (issue #978)
|
||||
* Fixed invalid result from `operator|` (issue #981)
|
||||
* Made `deserializeJson()` more picky about trailing characters (issue #980)
|
||||
* Added `ARDUINOJSON_ENABLE_NAN` (default=0) to enable NaN in JSON (issue #973)
|
||||
* Added `ARDUINOJSON_ENABLE_INFINITY` (default=0) to enable Infinity in JSON
|
||||
* Removed implicit conversion in comparison operators (issue #998)
|
||||
* Added lexicographical comparison for `JsonVariant`
|
||||
* Added support for `nullptr` (issue #998)
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### NaN and Infinity
|
||||
>
|
||||
> The JSON specification allows neither NaN not Infinity, but previous
|
||||
> versions of ArduinoJson supported it. Now, ArduinoJson behaves like most
|
||||
> other libraries: a NaN or and Infinity in the `JsonDocument`, becomes
|
||||
> a `null` in the output JSON. Also, `deserializeJson()` returns
|
||||
> `InvalidInput` if the JSON document contains NaN or Infinity.
|
||||
>
|
||||
> This version still supports NaN and Infinity in JSON documents, but
|
||||
> it's disabled by default to be compatible with other JSON parsers.
|
||||
> If you need the old behavior back, define `ARDUINOJSON_ENABLE_NAN` and
|
||||
> `ARDUINOJSON_ENABLE_INFINITY` to `1`;:
|
||||
>
|
||||
> ```c++
|
||||
> #define ARDUINOJSON_ENABLE_NAN 1
|
||||
> #define ARDUINOJSON_ENABLE_INFINITY 1
|
||||
> #include <ArduinoJson.h>
|
||||
> ```
|
||||
>
|
||||
> #### The "or" operator
|
||||
>
|
||||
> This version slightly changes the behavior of the | operator when the
|
||||
> variant contains a float and the user requests an integer.
|
||||
>
|
||||
> Older versions returned the floating point value truncated.
|
||||
> Now, it returns the default value.
|
||||
>
|
||||
> ```c++
|
||||
> // suppose variant contains 1.2
|
||||
> int value = variant | 3;
|
||||
>
|
||||
> // old behavior:
|
||||
> value == 1
|
||||
>
|
||||
> // new behavior
|
||||
> value == 3
|
||||
> ```
|
||||
>
|
||||
> If you need the old behavior, you must add `if (variant.is<float>())`.
|
||||
|
||||
v6.10.1 (2019-04-23)
|
||||
-------
|
||||
|
||||
* Fixed error "attributes are not allowed on a function-definition"
|
||||
* Fixed `deserializeJson()` not being picky enough (issue #969)
|
||||
* Fixed error "no matching function for call to write(uint8_t)" (issue #972)
|
||||
|
||||
v6.10.0 (2019-03-22)
|
||||
-------
|
||||
|
||||
* Fixed an integer overflow in the JSON deserializer
|
||||
* Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`.
|
||||
- `as<T>()` returns `0` if the integer `T` overflows
|
||||
- `is<T>()` returns `false` if the integer `T` overflows
|
||||
* Added `BasicJsonDocument` to support custom allocator (issue #876)
|
||||
* Added `JsonDocument::containsKey()` (issue #938)
|
||||
* Added `JsonVariant::containsKey()`
|
||||
|
||||
v6.9.1 (2019-03-01)
|
||||
------
|
||||
|
||||
* Fixed warning "unused variable" with GCC 4.4 (issue #912)
|
||||
* Fixed warning "cast increases required alignment" (issue #914)
|
||||
* Fixed warning "conversion may alter value" (issue #914)
|
||||
* Fixed naming conflict with "CAPACITY" (issue #839)
|
||||
* Muted warning "will change in GCC 7.1" (issue #914)
|
||||
* Added a clear error message for `StaticJsonBuffer` and `DynamicJsonBuffer`
|
||||
* Marked ArduinoJson.h as a "system header"
|
||||
|
||||
v6.9.0 (2019-02-26)
|
||||
------
|
||||
|
||||
* Decode escaped Unicode characters like \u00DE (issue #304, PR #791)
|
||||
Many thanks to Daniel Schulte (aka @trilader) who implemented this feature.
|
||||
* Added option ARDUINOJSON_DECODE_UNICODE to enable it
|
||||
* Converted `JsonArray::copyFrom()/copyTo()` to free functions `copyArray()`
|
||||
* Renamed `JsonArray::copyFrom()` and `JsonObject::copyFrom()` to `set()`
|
||||
* Renamed `JsonArray::get()` to `getElement()`
|
||||
* Renamed `JsonArray::add()` (without arg) to `addElement()`
|
||||
* Renamed `JsonObject::get()` to `getMember()`
|
||||
* Renamed `JsonObject::getOrCreate()` to `getOrAddMember()`
|
||||
* Fixed `JsonVariant::isNull()` not returning `true` after `set((char*)0)`
|
||||
* Fixed segfault after `variant.set(serialized((char*)0))`
|
||||
* Detect `IncompleteInput` in `false`, `true`, and `null`
|
||||
* Added `JsonDocument::size()`
|
||||
* Added `JsonDocument::remove()`
|
||||
* Added `JsonVariant::clear()`
|
||||
* Added `JsonVariant::remove()`
|
||||
|
||||
v6.8.0-beta (2019-01-30)
|
||||
-----------
|
||||
|
||||
* Import functions in the ArduinoJson namespace to get clearer errors
|
||||
* Improved syntax highlighting in Arduino IDE
|
||||
* Removed default capacity of `DynamicJsonDocument`
|
||||
* `JsonArray::copyFrom()` accepts `JsonArrayConst`
|
||||
* `JsonVariant::set()` accepts `JsonArrayConst` and `JsonObjectConst`
|
||||
* `JsonDocument` was missing in the ArduinoJson namespace
|
||||
* Added `memoryUsage()` to `JsonArray`, `JsonObject`, and `JsonVariant`
|
||||
* Added `nesting()` to `JsonArray`, `JsonDocument`, `JsonObject`, and `JsonVariant`
|
||||
* Replaced `JsonDocument::nestingLimit` with an additional parameter
|
||||
to `deserializeJson()` and `deserializeMsgPack()`
|
||||
* Fixed uninitialized variant in `JsonDocument`
|
||||
* Fixed `StaticJsonDocument` copy constructor and copy assignment
|
||||
* The copy constructor of `DynamicJsonDocument` chooses the capacity according to the memory usage of the source, not from the capacity of the source.
|
||||
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
|
||||
* Added `JsonDocument::isNull()`
|
||||
* Added `JsonDocument::operator[]`
|
||||
* Added `ARDUINOJSON_TAB` to configure the indentation character
|
||||
* Reduced the size of the pretty JSON serializer
|
||||
* Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant`
|
||||
* `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write.
|
||||
Calling `JsonVariant::to<T>()` is not required anymore.
|
||||
* `JsonDocument` now support the same operations as `JsonVariant`.
|
||||
Calling `JsonDocument::as<T>()` is not required anymore.
|
||||
* Fixed example `JsonHttpClient.ino`
|
||||
* User can now use a `JsonString` as a key or a value
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### `DynamicJsonDocument`'s constructor
|
||||
>
|
||||
> The parameter to the constructor of `DynamicJsonDocument` is now mandatory
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc(1024);
|
||||
> ```
|
||||
>
|
||||
> #### Nesting limit
|
||||
>
|
||||
> `JsonDocument::nestingLimit` was replaced with a new parameter to `deserializeJson()` and `deserializeMsgPack()`.
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> doc.nestingLimit = 15;
|
||||
> deserializeJson(doc, input);
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> deserializeJson(doc, input, DeserializationOption::NestingLimit(15));
|
||||
> ```
|
||||
|
||||
v6.7.0-beta (2018-12-07)
|
||||
-----------
|
||||
|
||||
* Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity.
|
||||
* Restored the monotonic allocator because the code was getting too big
|
||||
* Reduced the memory usage
|
||||
* Reduced the code size
|
||||
* Renamed `JsonKey` to `JsonString`
|
||||
* Removed spurious files in the Particle library
|
||||
|
||||
v6.6.0-beta (2018-11-13)
|
||||
-----------
|
||||
|
||||
* Removed `JsonArray::is<T>(i)` and `JsonArray::set(i,v)`
|
||||
* Removed `JsonObject::is<T>(k)` and `JsonObject::set(k,v)`
|
||||
* Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)`
|
||||
* Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)`
|
||||
* Added `JSON_STRING_SIZE()`
|
||||
* ~~Replacing or removing a value now releases the memory~~
|
||||
* Added `DeserializationError::code()` to be used in switch statements (issue #846)
|
||||
|
||||
v6.5.0-beta (2018-10-13)
|
||||
-----------
|
||||
|
||||
* Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant`
|
||||
* Allow mixed configuration in compilation units (issue #809)
|
||||
* Fixed object keys not being duplicated
|
||||
* `JsonPair::key()` now returns a `JsonKey`
|
||||
* Increased the default capacity of `DynamicJsonDocument`
|
||||
* Fixed `JsonVariant::is<String>()` (closes #763)
|
||||
* Added `JsonArrayConst`, `JsonObjectConst`, and `JsonVariantConst`
|
||||
* Added copy-constructor and copy-assignment-operator for `JsonDocument` (issue #827)
|
||||
|
||||
v6.4.0-beta (2018-09-11)
|
||||
-----------
|
||||
|
||||
* Copy `JsonArray` and `JsonObject`, instead of storing pointers (issue #780)
|
||||
* Added `JsonVariant::to<JsonArray>()` and `JsonVariant::to<JsonObject>()`
|
||||
|
||||
v6.3.0-beta (2018-08-31)
|
||||
-----------
|
||||
|
||||
* Implemented reference semantics for `JsonVariant`
|
||||
* Replaced `JsonPair`'s `key` and `value` with `key()` and `value()`
|
||||
* Fixed `serializeJson(obj[key], dst)` (issue #794)
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### JsonVariant
|
||||
>
|
||||
> `JsonVariant` now has a semantic similar to `JsonObject` and `JsonArray`.
|
||||
> It's a reference to a value stored in the `JsonDocument`.
|
||||
> As a consequence, a `JsonVariant` cannot be used as a standalone variable anymore.
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonVariant myValue = 42;
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> JsonVariant myValue = doc.to<JsonVariant>();
|
||||
> myValue.set(42);
|
||||
> ```
|
||||
>
|
||||
> #### JsonPair
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> for(JsonPair p : myObject) {
|
||||
> Serial.println(p.key);
|
||||
> Serial.println(p.value.as<int>());
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> for(JsonPair p : myObject) {
|
||||
> Serial.println(p.key());
|
||||
> Serial.println(p.value().as<int>());
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> CAUTION: the key is now read only!
|
||||
|
||||
v6.2.3-beta (2018-07-19)
|
||||
-----------
|
||||
|
||||
* Fixed exception when using Flash strings as object keys (issue #784)
|
||||
|
||||
v6.2.2-beta (2018-07-18)
|
||||
-----------
|
||||
|
||||
* Fixed `invalid application of 'sizeof' to incomplete type '__FlashStringHelper'` (issue #783)
|
||||
* Fixed `char[]` not duplicated when passed to `JsonVariant::operator[]`
|
||||
|
||||
v6.2.1-beta (2018-07-17)
|
||||
-----------
|
||||
|
||||
* Fixed `JsonObject` not inserting keys of type `String` (issue #782)
|
||||
|
||||
v6.2.0-beta
|
||||
v6.2.0-beta (2018-07-12)
|
||||
-----------
|
||||
|
||||
* Disabled lazy number deserialization (issue #772)
|
||||
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
|
||||
* Improved float serialization when `-fsingle-precision-constant` is used
|
||||
* Renamed function `RawJson()` to `serialized()`
|
||||
* `serializeMsgPack()` now supports values marked with `serialized()`
|
||||
@ -35,7 +309,7 @@ v6.2.0-beta
|
||||
> object["values"] = serialized("[1,2,3,4]");
|
||||
> ```
|
||||
|
||||
v6.1.0-beta
|
||||
v6.1.0-beta (2018-07-02)
|
||||
-----------
|
||||
|
||||
* Return `JsonArray` and `JsonObject` by value instead of reference (issue #309)
|
||||
@ -65,12 +339,12 @@ v6.1.0-beta
|
||||
> }
|
||||
> ```
|
||||
|
||||
v6.0.1-beta
|
||||
v6.0.1-beta (2018-06-11)
|
||||
-----------
|
||||
|
||||
* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752)
|
||||
|
||||
v6.0.0-beta
|
||||
v6.0.0-beta (2018-06-07)
|
||||
-----------
|
||||
|
||||
* Added `DynamicJsonDocument` and `StaticJsonDocument`
|
||||
|
@ -1,5 +1,5 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2018
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
@ -7,10 +7,16 @@ project(ArduinoJson)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_definitions(-DARDUINOJSON_DEBUG)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
add_subdirectory(third-party/catch)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(fuzzing)
|
||||
|
@ -1,7 +1,7 @@
|
||||
The MIT License (MIT)
|
||||
---------------------
|
||||
|
||||
Copyright © 2014-2018 Benoit BLANCHON
|
||||
Copyright © 2014-2019 Benoit BLANCHON
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
26
README.md
26
README.md
@ -2,7 +2,11 @@
|
||||
|
||||
---
|
||||
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=6.x) [](https://github.com/bblanchon/ArduinoJson)
|
||||
[](https://www.ardu-badge.com/ArduinoJson/6.11.1)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
[](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
|
||||
[](https://github.com/bblanchon/ArduinoJson)
|
||||
|
||||
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
|
||||
@ -60,14 +64,13 @@ Here is a program that parses a JSON document with ArduinoJson.
|
||||
```c++
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(1024);
|
||||
deserializeJson(doc, json);
|
||||
|
||||
JsonObjectRef root = doc.as<JsonObject>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
const char* sensor = doc["sensor"];
|
||||
long time = doc["time"];
|
||||
double latitude = doc["data"][0];
|
||||
double longitude = doc["data"][1];
|
||||
```
|
||||
|
||||
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme)
|
||||
@ -77,13 +80,12 @@ See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_
|
||||
Here is a program that generates a JSON document with ArduinoJson:
|
||||
|
||||
```c++
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(1024);
|
||||
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
doc["sensor"] = "gps";
|
||||
doc["time"] = 1351824120;
|
||||
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
JsonArray data = doc.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 6.0.1.{build}
|
||||
version: 6.11.1.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
@ -17,4 +17,4 @@ before_build:
|
||||
build_script:
|
||||
- cmake --build . --config %CONFIGURATION%
|
||||
test_script:
|
||||
- ctest --output-on-failure .
|
||||
- ctest -C %CONFIGURATION% --output-on-failure .
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to store your project configuration in a file.
|
||||
@ -10,12 +10,19 @@
|
||||
// "hostname": "examples.com",
|
||||
// "port": 2731
|
||||
// }
|
||||
//
|
||||
// https://arduinojson.org/v6/example/config/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <SD.h>
|
||||
#include <SPI.h>
|
||||
|
||||
// Configuration that we'll store on disk
|
||||
// Our configuration structure.
|
||||
//
|
||||
// Never use a JsonDocument to store the configuration!
|
||||
// A JsonDocument is *not* a permanent storage; it's only a temporary storage
|
||||
// used during the serialization phase. See:
|
||||
// https://arduinojson.org/v6/faq/why-must-i-create-a-separate-config-object/
|
||||
struct Config {
|
||||
char hostname[64];
|
||||
int port;
|
||||
@ -29,9 +36,9 @@ void loadConfiguration(const char *filename, Config &config) {
|
||||
// Open file for reading
|
||||
File file = SD.open(filename);
|
||||
|
||||
// Allocate the document on the stack.
|
||||
// Allocate a temporary JsonDocument
|
||||
// Don't forget to change the capacity to match your requirements.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<512> doc;
|
||||
|
||||
// Deserialize the JSON document
|
||||
@ -39,16 +46,13 @@ void loadConfiguration(const char *filename, Config &config) {
|
||||
if (error)
|
||||
Serial.println(F("Failed to read file, using default configuration"));
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
// Copy values from the JsonDocument to the Config
|
||||
config.port = doc["port"] | 2731;
|
||||
strlcpy(config.hostname, // <- destination
|
||||
doc["hostname"] | "example.com", // <- source
|
||||
sizeof(config.hostname)); // <- destination's capacity
|
||||
|
||||
// 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)
|
||||
// Close the file (Curiously, File's destructor doesn't close the file)
|
||||
file.close();
|
||||
}
|
||||
|
||||
@ -64,24 +68,21 @@ void saveConfiguration(const char *filename, const Config &config) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the document on the stack.
|
||||
// Allocate a temporary JsonDocument
|
||||
// Don't forget to change the capacity to match your requirements.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<256> doc;
|
||||
|
||||
// Make our document contain an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
|
||||
// Set the values in the object
|
||||
root["hostname"] = config.hostname;
|
||||
root["port"] = config.port;
|
||||
// Set the values in the document
|
||||
doc["hostname"] = config.hostname;
|
||||
doc["port"] = config.port;
|
||||
|
||||
// Serialize JSON to file
|
||||
if (serializeJson(doc, file) == 0) {
|
||||
Serial.println(F("Failed to write to file"));
|
||||
}
|
||||
|
||||
// Close the file (File's destructor doesn't close the file)
|
||||
// Close the file
|
||||
file.close();
|
||||
}
|
||||
|
||||
@ -100,7 +101,7 @@ void printFile(const char *filename) {
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// Close the file (File's destructor doesn't close the file)
|
||||
// Close the file
|
||||
file.close();
|
||||
}
|
||||
|
||||
@ -132,4 +133,15 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/config/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization or deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a case study of a project that has
|
||||
// a complex configuration with nested members.
|
||||
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,8 +1,10 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
//
|
||||
// https://arduinojson.org/v6/example/generator/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
@ -15,7 +17,7 @@ void setup() {
|
||||
//
|
||||
// Inside the brackets, 200 is the RAM allocated to this document.
|
||||
// Don't forget to change this value to match your requirement.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
@ -23,30 +25,30 @@ void setup() {
|
||||
//
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// Make our document be an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
|
||||
// Add values in the object
|
||||
// Add values in the document
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do root.set<long>("time", 1351824120);
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
doc["sensor"] = "gps";
|
||||
doc["time"] = 1351824120;
|
||||
|
||||
// Add an array.
|
||||
//
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
JsonArray data = doc.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
serializeJson(root, Serial);
|
||||
// This prints:
|
||||
// Generate the minified JSON and send it to the Serial port.
|
||||
//
|
||||
serializeJson(doc, Serial);
|
||||
// The above line prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
// Start a new line
|
||||
Serial.println();
|
||||
|
||||
serializeJsonPretty(root, Serial);
|
||||
// This prints:
|
||||
// Generate the prettified JSON and send it to the Serial port.
|
||||
//
|
||||
serializeJsonPretty(doc, Serial);
|
||||
// The above line prints:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
@ -61,4 +63,15 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/generator/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like serializing directly to a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to parse a JSON document in an HTTP response.
|
||||
@ -15,6 +15,8 @@
|
||||
// 2.302038
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
// https://arduinojson.org/v6/example/http-client/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
@ -57,7 +59,8 @@ void setup() {
|
||||
// Check HTTP status
|
||||
char status[32] = {0};
|
||||
client.readBytesUntil('\r', status, sizeof(status));
|
||||
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
|
||||
// It should be "HTTP/1.0 200 OK" or "HTTP/1.1 200 OK"
|
||||
if (strcmp(status + 9, "200 OK") != 0) {
|
||||
Serial.print(F("Unexpected response: "));
|
||||
Serial.println(status);
|
||||
return;
|
||||
@ -71,7 +74,7 @@ void setup() {
|
||||
}
|
||||
|
||||
// Allocate the JSON document
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
|
||||
DynamicJsonDocument doc(capacity);
|
||||
|
||||
@ -84,12 +87,11 @@ void setup() {
|
||||
}
|
||||
|
||||
// Extract values
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
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*>());
|
||||
Serial.println(doc["sensor"].as<char*>());
|
||||
Serial.println(doc["time"].as<long>());
|
||||
Serial.println(doc["data"][0].as<float>(), 6);
|
||||
Serial.println(doc["data"][1].as<float>(), 6);
|
||||
|
||||
// Disconnect
|
||||
client.stop();
|
||||
@ -99,4 +101,16 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/http-client/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization
|
||||
// showing how to parse the response from GitHub's API. In the last chapter,
|
||||
// it shows how to parse the huge documents from OpenWeatherMap
|
||||
// and Reddit.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,8 +1,10 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
||||
//
|
||||
// https://arduinojson.org/v6/example/parser/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
@ -13,21 +15,24 @@ void setup() {
|
||||
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the memory pool in bytes.
|
||||
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject doc(200);
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// JSON input string.
|
||||
//
|
||||
// It's better to use a char[] as shown here.
|
||||
// If you use a const char* or a String, ArduinoJson will
|
||||
// have to make a copy of the input in the JsonBuffer.
|
||||
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
|
||||
// the minimal amount of memory because the JsonDocument stores pointers to
|
||||
// the input buffer.
|
||||
// If you use another type of input, ArduinoJson must copy the strings from
|
||||
// the input to the JsonDocument, so you need to increase the capacity of the
|
||||
// JsonDocument.
|
||||
char json[] =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
@ -41,17 +46,14 @@ void setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do root["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = doc["sensor"];
|
||||
long time = doc["time"];
|
||||
double latitude = doc["data"][0];
|
||||
double longitude = doc["data"][1];
|
||||
|
||||
// Print values.
|
||||
Serial.println(sensor);
|
||||
@ -64,4 +66,15 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/parser/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like deserializing directly from a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,17 +1,19 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to implement an HTTP server that sends JSON document
|
||||
// in the responses.
|
||||
// This example shows how to implement an HTTP server that sends a JSON document
|
||||
// in the response.
|
||||
// It uses the Ethernet library but can be easily adapted for Wifi.
|
||||
//
|
||||
// It sends the value of the analog and digital pins.
|
||||
// The JSON document looks like the following:
|
||||
// The JSON document contains the values of the analog and digital pins.
|
||||
// It looks like that:
|
||||
// {
|
||||
// "analog": [ 0, 1, 2, 3, 4, 5 ],
|
||||
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
|
||||
// "analog": [0, 76, 123, 158, 192, 205],
|
||||
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
|
||||
// }
|
||||
//
|
||||
// https://arduinojson.org/v6/example/http-server/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
@ -51,15 +53,12 @@ void loop() {
|
||||
// Read the request (we ignore the content in this example)
|
||||
while (client.available()) client.read();
|
||||
|
||||
// Allocate the JSON document
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
// Allocate a temporary JsonDocument
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<500> doc;
|
||||
|
||||
// Make our document represent an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray analogValues = root.createNestedArray("analog");
|
||||
JsonArray analogValues = doc.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
// Read the analog input
|
||||
int value = analogRead(pin);
|
||||
@ -69,7 +68,7 @@ void loop() {
|
||||
}
|
||||
|
||||
// Create the "digital" array
|
||||
JsonArray digitalValues = root.createNestedArray("digital");
|
||||
JsonArray digitalValues = doc.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
// Read the digital input
|
||||
int value = digitalRead(pin);
|
||||
@ -79,20 +78,33 @@ void loop() {
|
||||
}
|
||||
|
||||
Serial.print(F("Sending: "));
|
||||
serializeJson(root, Serial);
|
||||
serializeJson(doc, Serial);
|
||||
Serial.println();
|
||||
|
||||
// Write response headers
|
||||
client.println("HTTP/1.0 200 OK");
|
||||
client.println("Content-Type: application/json");
|
||||
client.println("Connection: close");
|
||||
client.println(F("HTTP/1.0 200 OK"));
|
||||
client.println(F("Content-Type: application/json"));
|
||||
client.println(F("Connection: close"));
|
||||
client.print(F("Content-Length: "));
|
||||
client.println(measureJsonPretty(doc));
|
||||
client.println();
|
||||
|
||||
// Write JSON document
|
||||
serializeJsonPretty(root, client);
|
||||
serializeJsonPretty(doc, client);
|
||||
|
||||
// Disconnect
|
||||
client.stop();
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/http-server/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or an HTTP client.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,14 +1,14 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to send a JSON document to a UDP socket.
|
||||
// At regular interval, it sends a UDP packet that contains the status of
|
||||
// analog and digital pins.
|
||||
// The JSON document looks like the following:
|
||||
// It looks like that:
|
||||
// {
|
||||
// "analog": [ 0, 1, 2, 3, 4, 5 ],
|
||||
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
|
||||
// "analog": [0, 76, 123, 158, 192, 205],
|
||||
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
|
||||
// }
|
||||
//
|
||||
// If you want to test this program, you need to be able to receive the UDP
|
||||
@ -16,6 +16,8 @@
|
||||
// For example, you can run netcat on your computer
|
||||
// $ ncat -ulp 8888
|
||||
// See https://nmap.org/ncat/
|
||||
//
|
||||
// https://arduinojson.org/v6/example/udp-beacon/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
@ -43,15 +45,12 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Allocate the JSON document
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
// Allocate a temporary JsonDocument
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<500> doc;
|
||||
|
||||
// Make our document represent an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray analogValues = root.createNestedArray("analog");
|
||||
JsonArray analogValues = doc.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
// Read the analog input
|
||||
int value = analogRead(pin);
|
||||
@ -61,7 +60,7 @@ void loop() {
|
||||
}
|
||||
|
||||
// Create the "digital" array
|
||||
JsonArray digitalValues = root.createNestedArray("digital");
|
||||
JsonArray digitalValues = doc.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
// Read the digital input
|
||||
int value = digitalRead(pin);
|
||||
@ -75,11 +74,11 @@ void loop() {
|
||||
Serial.print(remoteIp);
|
||||
Serial.print(F(" on port "));
|
||||
Serial.println(remotePort);
|
||||
serializeJson(root, Serial);
|
||||
serializeJson(doc, Serial);
|
||||
|
||||
// Send UDP packet
|
||||
udp.beginPacket(remoteIp, remotePort);
|
||||
serializeJson(root, udp);
|
||||
serializeJson(doc, udp);
|
||||
udp.println();
|
||||
udp.endPacket();
|
||||
|
||||
@ -87,4 +86,15 @@ void loop() {
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/udp-beacon/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or any stream.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,9 +1,11 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a MessagePack document with
|
||||
// ArduinoJson.
|
||||
//
|
||||
// https://arduinojson.org/v6/example/msgpack-parser/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
@ -14,9 +16,9 @@ void setup() {
|
||||
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the memory pool in bytes.
|
||||
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
@ -26,9 +28,12 @@ void setup() {
|
||||
|
||||
// MessagePack input string.
|
||||
//
|
||||
// It's better to use a char[] as shown here.
|
||||
// If you use a const char* or a String, ArduinoJson will
|
||||
// have to make a copy of the input in the JsonBuffer.
|
||||
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
|
||||
// the minimal amount of memory because the JsonDocument stores pointers to
|
||||
// the input buffer.
|
||||
// If you use another type of input, ArduinoJson must copy the strings from
|
||||
// the input to the JsonDocument, so you need to increase the capacity of the
|
||||
// JsonDocument.
|
||||
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
|
||||
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
|
||||
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
|
||||
@ -40,31 +45,23 @@ void setup() {
|
||||
// "data": [48.75608, 2.302038]
|
||||
// }
|
||||
|
||||
// doc of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
DeserializationError error = deserializeMsgPack(doc, input);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
// Test if parsing succeeded.
|
||||
if (error) {
|
||||
Serial.print("deserializeMsgPack() failed: ");
|
||||
Serial.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do root["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = doc["sensor"];
|
||||
long time = doc["time"];
|
||||
double latitude = doc["data"][0];
|
||||
double longitude = doc["data"][1];
|
||||
|
||||
// Print values.
|
||||
Serial.println(sensor);
|
||||
@ -76,5 +73,3 @@ void setup() {
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/msgpack-parser/ for more.
|
||||
|
@ -1,24 +1,25 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// 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
|
||||
// JsonDocument. Prefer plain old char*, as they are more efficient in term of
|
||||
// code size, speed, and memory usage.
|
||||
//
|
||||
// https://arduinojson.org/v6/example/progmem/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
#ifdef PROGMEM // <- check that Flash strings are supported
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(1024);
|
||||
|
||||
// You can use a Flash String as your JSON input.
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
// WARNING: the strings in the input will be duplicated in the JsonDocument.
|
||||
deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120,"
|
||||
"\"data\":[48.756080,2.302038]}"));
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
@ -29,12 +30,12 @@ void setup() {
|
||||
|
||||
// You can use a Flash String to set an element of a JsonObject
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
// JsonDocument.
|
||||
obj[F("time")] = time;
|
||||
|
||||
// You can set a Flash String to a JsonObject or JsonArray:
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
// JsonDocument.
|
||||
obj["sensor"] = F("gps");
|
||||
|
||||
// It works with serialized() too:
|
||||
@ -57,4 +58,15 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/progmem/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any memory
|
||||
// problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. It also tells why you
|
||||
// should not abuse Flash strings with ArduinoJson.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,20 +1,22 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// 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
|
||||
// JsonDocument. Prefer plain old char[], as they are more efficient in term of
|
||||
// code size, speed, and memory usage.
|
||||
//
|
||||
// https://arduinojson.org/v6/example/string/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(1024);
|
||||
|
||||
// You can use a String as your JSON input.
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
// WARNING: the string in the input will be duplicated in the JsonDocument.
|
||||
String input =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
deserializeJson(doc, input);
|
||||
@ -25,11 +27,11 @@ void setup() {
|
||||
long time = obj[String("time")];
|
||||
|
||||
// You can use a String to set an element of a JsonObject
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
// WARNING: the content of the String will be duplicated in the JsonDocument.
|
||||
obj[String("time")] = time;
|
||||
|
||||
// You can get a String from a JsonObject or JsonArray:
|
||||
// No duplication is done, at least not in the JsonBuffer.
|
||||
// No duplication is done, at least not in the JsonDocument.
|
||||
String sensor = obj["sensor"];
|
||||
|
||||
// Unfortunately, the following doesn't work (issue #118):
|
||||
@ -38,14 +40,14 @@ void setup() {
|
||||
sensor = obj["sensor"].as<String>();
|
||||
|
||||
// You can set a String to a JsonObject or JsonArray:
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
// WARNING: the content of the String will be duplicated in the JsonDocument.
|
||||
obj["sensor"] = sensor;
|
||||
|
||||
// It works with serialized() too:
|
||||
obj["sensor"] = serialized(sensor);
|
||||
|
||||
// You can also concatenate strings
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
// WARNING: the content of the String will be duplicated in the JsonDocument.
|
||||
obj[String("sen") + "sor"] = String("gp") + "s";
|
||||
|
||||
// You can compare the content of a JsonObject with a String
|
||||
@ -62,4 +64,14 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/string/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. On several occasions, it
|
||||
// shows how you can avoid String in your program.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
17
fuzzing/CMakeLists.txt
Normal file
17
fuzzing/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
add_executable(msgpack_fuzzer
|
||||
msgpack_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
)
|
||||
|
||||
add_executable(json_fuzzer
|
||||
json_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
)
|
@ -1,6 +1,6 @@
|
||||
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
|
||||
|
||||
CXXFLAGS += -I../src
|
||||
CXXFLAGS += -I../src -DARDUINOJSON_DEBUG
|
||||
|
||||
all: \
|
||||
$(OUT)/json_fuzzer \
|
||||
|
50
fuzzing/fuzzer_main.cpp
Normal file
50
fuzzing/fuzzer_main.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
// This file is NOT use by Google's OSS fuzz
|
||||
// I only use it to reproduce the bugs found
|
||||
|
||||
#include <stdint.h> // size_t
|
||||
#include <stdio.h> // fopen et al.
|
||||
#include <stdlib.h> // exit
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
|
||||
|
||||
std::vector<uint8_t> read(const char* path) {
|
||||
FILE* f = fopen(path, "rb");
|
||||
if (!f) {
|
||||
std::cerr << "Failed to open " << path << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
std::vector<uint8_t> buffer(size);
|
||||
if (fread(buffer.data(), 1, size, f) != size) {
|
||||
fclose(f);
|
||||
std::cerr << "Failed to read " << path << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Usage: msgpack_fuzzer files" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::cout << "Loading " << argv[i] << std::endl;
|
||||
std::vector<uint8_t> buffer = read(argv[i]);
|
||||
LLVMFuzzerTestOneInput(buffer.data(), buffer.size());
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(4096);
|
||||
DeserializationError error = deserializeJson(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
|
1
fuzzing/json_seed_corpus/IntegerOverflow.json
Normal file
1
fuzzing/json_seed_corpus/IntegerOverflow.json
Normal file
@ -0,0 +1 @@
|
||||
9720730739393920739
|
@ -1,7 +1,7 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonDocument doc(4096);
|
||||
DeserializationError error = deserializeMsgPack(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
|
39
keywords.txt
39
keywords.txt
@ -1,17 +1,36 @@
|
||||
# Macros
|
||||
JSON_ARRAY_SIZE KEYWORD2
|
||||
JSON_OBJECT_SIZE KEYWORD2
|
||||
JSON_STRING_SIZE KEYWORD2
|
||||
|
||||
# Free functions
|
||||
deserializeJson KEYWORD2
|
||||
deserializeMsgPack KEYWORD2
|
||||
serialized KEYWORD2
|
||||
serializeJson KEYWORD2
|
||||
serializeJsonPretty KEYWORD2
|
||||
serializeMsgPack KEYWORD2
|
||||
|
||||
# Methods
|
||||
add KEYWORD2
|
||||
as KEYWORD2
|
||||
createNestedArray KEYWORD2
|
||||
createNestedObject KEYWORD2
|
||||
deserializeJson KEYWORD2
|
||||
deserializeMsgPack KEYWORD2
|
||||
DynamicJsonDocument KEYWORD1
|
||||
get KEYWORD2
|
||||
JsonArray KEYWORD1
|
||||
JsonObject KEYWORD1
|
||||
JsonVariant KEYWORD1
|
||||
serializeMsgPack KEYWORD2
|
||||
serializeJson KEYWORD2
|
||||
serializeJsonPretty KEYWORD2
|
||||
set KEYWORD2
|
||||
StaticJsonDocument KEYWORD1
|
||||
to KEYWORD2
|
||||
|
||||
# Type names
|
||||
DeserializationError KEYWORD1 DATA_TYPE
|
||||
DynamicJsonDocument KEYWORD1 DATA_TYPE
|
||||
JsonArray KEYWORD1 DATA_TYPE
|
||||
JsonArrayConst KEYWORD1 DATA_TYPE
|
||||
JsonFloat KEYWORD1 DATA_TYPE
|
||||
JsonInteger KEYWORD1 DATA_TYPE
|
||||
JsonObject KEYWORD1 DATA_TYPE
|
||||
JsonObjectConst KEYWORD1 DATA_TYPE
|
||||
JsonString KEYWORD1 DATA_TYPE
|
||||
JsonUInt KEYWORD1 DATA_TYPE
|
||||
JsonVariant KEYWORD1 DATA_TYPE
|
||||
JsonVariantConst KEYWORD1 DATA_TYPE
|
||||
StaticJsonDocument KEYWORD1 DATA_TYPE
|
||||
|
@ -7,7 +7,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"version": "6.2.1-beta",
|
||||
"version": "6.11.1",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "https://blog.benoitblanchon.fr"
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=ArduinoJson
|
||||
version=6.2.1-beta
|
||||
version=6.11.1
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
|
@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
OUTPUT="$(pwd)/sizes.csv"
|
||||
|
||||
echo "Tag;Date;Parser;Generator" > $OUTPUT
|
||||
|
||||
cd $(dirname $(dirname $0))
|
||||
|
||||
git tag | while read TAG
|
||||
do
|
||||
|
||||
git checkout -q tags/$TAG
|
||||
|
||||
DATE=$(git log -1 --date=short --pretty=format:%cd)
|
||||
PARSER_SIZE=$(arduino --verify examples/JsonParserExample/JsonParserExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
|
||||
if [ -e 'examples/JsonGeneratorExample/JsonGeneratorExample.ino' ]; then
|
||||
GENERATOR_SIZE=$(arduino --verify examples/JsonGeneratorExample/JsonGeneratorExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
else
|
||||
GENERATOR_SIZE=""
|
||||
fi
|
||||
|
||||
echo $TAG
|
||||
if [ ! -z "$PARSER_SIZE" ]
|
||||
then
|
||||
echo "JsonParserExample = $PARSER_SIZE bytes"
|
||||
else
|
||||
echo "JsonParserExample compilation failed."
|
||||
fi
|
||||
|
||||
if [ ! -z "$GENERATOR_SIZE" ]
|
||||
then
|
||||
echo "JsonGeneratorExample = $GENERATOR_SIZE bytes"
|
||||
else
|
||||
echo "JsonGeneratorExample compilation failed."
|
||||
fi
|
||||
|
||||
echo "$TAG;$DATE;$PARSER_SIZE;$GENERATOR_SIZE" >> $OUTPUT
|
||||
|
||||
done
|
18
scripts/publish-particle-library.sh
Normal file
18
scripts/publish-particle-library.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
SOURCE_DIR="$(dirname "$0")/.."
|
||||
WORK_DIR=$(mktemp -d)
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
cp "$SOURCE_DIR/README.md" "$WORK_DIR/README.md"
|
||||
cp "$SOURCE_DIR/CHANGELOG.md" "$WORK_DIR/CHANGELOG.md"
|
||||
cp "$SOURCE_DIR/library.properties" "$WORK_DIR/library.properties"
|
||||
cp "$SOURCE_DIR/LICENSE.md" "$WORK_DIR/LICENSE.txt"
|
||||
cp -r "$SOURCE_DIR/src" "$WORK_DIR/"
|
||||
cp -r "$SOURCE_DIR/examples" "$WORK_DIR/"
|
||||
|
||||
cd "$WORK_DIR"
|
||||
particle library upload
|
||||
particle library publish
|
61
scripts/publish.sh
Normal file
61
scripts/publish.sh
Normal file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
VERSION="$1"
|
||||
DATE=$(date +%F)
|
||||
TAG="v$VERSION"
|
||||
VERSION_REGEX="[0-9a-z\\.\\-]+"
|
||||
|
||||
update_version_in_source () {
|
||||
IFS=".-" read MAJOR MINOR REVISION EXTRA < <(echo "$VERSION")
|
||||
UNDERLINE=$(printf -- '-%.0s' $(seq 1 ${#TAG}))
|
||||
|
||||
sed -i~ -bE "s/version=$VERSION_REGEX/version=$VERSION/; s|ardu-badge.com/ArduinoJson/$VERSION_REGEX|ardu-badge.com/ArduinoJson/$VERSION|; " README.md
|
||||
rm README.md*~
|
||||
|
||||
sed -i~ -bE "4s/HEAD/$TAG ($DATE)/; 5s/-+/$UNDERLINE/" CHANGELOG.md
|
||||
rm CHANGELOG.md*~
|
||||
|
||||
sed -i~ -bE "s/\"version\":.*$/\"version\": \"$VERSION\",/" library.json
|
||||
rm library.json*~
|
||||
|
||||
sed -i~ -bE "s/version=.*$/version=$VERSION/" library.properties
|
||||
rm library.properties*~
|
||||
|
||||
sed -i~ -bE "s/version: .*$/version: $VERSION.{build}/" appveyor.yml
|
||||
rm appveyor.yml*~
|
||||
|
||||
sed -i~ -bE \
|
||||
-e "s/ARDUINOJSON_VERSION .*$/ARDUINOJSON_VERSION \"$VERSION\"/" \
|
||||
-e "s/ARDUINOJSON_VERSION_MAJOR .*$/ARDUINOJSON_VERSION_MAJOR $MAJOR/" \
|
||||
-e "s/ARDUINOJSON_VERSION_MINOR .*$/ARDUINOJSON_VERSION_MINOR $MINOR/" \
|
||||
-e "s/ARDUINOJSON_VERSION_REVISION .*$/ARDUINOJSON_VERSION_REVISION $REVISION/" \
|
||||
src/ArduinoJson/version.hpp
|
||||
rm src/ArduinoJson/version.hpp*~
|
||||
}
|
||||
|
||||
commit_new_version () {
|
||||
git add src/ArduinoJson/version.hpp README.md CHANGELOG.md library.json library.properties appveyor.yml
|
||||
git commit -m "Set version to $VERSION"
|
||||
}
|
||||
|
||||
add_tag () {
|
||||
CHANGES=$(awk '/\* /{ FOUND=1; print; next } { if (FOUND) exit}' CHANGELOG.md)
|
||||
git tag -m "ArduinoJson $VERSION"$'\n'"$CHANGES" "$TAG"
|
||||
}
|
||||
|
||||
push () {
|
||||
git push --follow-tags
|
||||
}
|
||||
|
||||
update_version_in_source
|
||||
commit_new_version
|
||||
add_tag
|
||||
push
|
||||
|
||||
scripts/build-arduino-package.sh
|
||||
scripts/build-single-header.sh
|
||||
scripts/wandbox/publish.sh "../ArduinoJson-$TAG.h"
|
14
scripts/travis/build.sh
Executable file
14
scripts/travis/build.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
export CC="$_CC"
|
||||
export CXX="$_CXX"
|
||||
|
||||
if [ -n "$SANITIZE" ]; then
|
||||
export CXXFLAGS="-fsanitize=$SANITIZE"
|
||||
BUILD_TYPE="Debug"
|
||||
else
|
||||
BUILD_TYPE="Release"
|
||||
fi
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .
|
||||
cmake --build .
|
@ -1,30 +0,0 @@
|
||||
#!/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
|
||||
|
||||
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,8 +1,6 @@
|
||||
#!/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 -DCOVERAGE=true .
|
||||
cmake -DCOVERAGE=true .
|
||||
make
|
||||
make test
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
ROOT_DIR=$(dirname $0)/../../
|
||||
INCLUDE_DIR=${ROOT_DIR}/src/
|
||||
FUZZING_DIR=${ROOT_DIR}/fuzzing/
|
||||
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,fuzzer"
|
||||
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,undefined,fuzzer -fno-sanitize-recover=all"
|
||||
|
||||
fuzz() {
|
||||
NAME="$1"
|
||||
@ -16,7 +16,7 @@ fuzz() {
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30 -timeout=1
|
||||
|
||||
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER}.profdata
|
||||
llvm-cov-${CLANG} report ./${FUZZER} -instr-profile=${FUZZER}.profdata
|
||||
|
@ -4,6 +4,18 @@ pip install --user platformio
|
||||
|
||||
rm -r test
|
||||
|
||||
case $BOARD in
|
||||
uno)
|
||||
platformio lib install 868 # SD library
|
||||
platformio lib install 872 # Ethernet library
|
||||
;;
|
||||
esp01)
|
||||
platformio lib uninstall 161 || true
|
||||
platformio lib uninstall 868 || true
|
||||
platformio lib uninstall 872 || true
|
||||
;;
|
||||
esac
|
||||
|
||||
for EXAMPLE in $PWD/examples/*/*.ino;
|
||||
do
|
||||
platformio ci $EXAMPLE -l '.' -b $BOARD
|
||||
|
4
scripts/travis/test.sh
Executable file
4
scripts/travis/test.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
"$(dirname "$0")/build.sh"
|
||||
ctest --output-on-failure .
|
60
scripts/wandbox/JsonGeneratorExample.cpp
Normal file
60
scripts/wandbox/JsonGeneratorExample.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the RAM allocated to this document.
|
||||
// Don't forget to change this value to match your requirement.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// Add values in the document
|
||||
//
|
||||
doc["sensor"] = "gps";
|
||||
doc["time"] = 1351824120;
|
||||
|
||||
// Add an array.
|
||||
//
|
||||
JsonArray data = doc.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
// Generate the minified JSON and send it to STDOUT
|
||||
//
|
||||
serializeJson(doc, std::cout);
|
||||
// The above line prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
// Start a new line
|
||||
std::cout << std::endl;
|
||||
|
||||
// Generate the prettified JSON and send it to STDOUT
|
||||
//
|
||||
serializeJsonPretty(doc, std::cout);
|
||||
// The above line prints:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [
|
||||
// 48.756080,
|
||||
// 2.302038
|
||||
// ]
|
||||
// }
|
||||
}
|
59
scripts/wandbox/JsonParserExample.cpp
Normal file
59
scripts/wandbox/JsonParserExample.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<300> doc;
|
||||
|
||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// JSON input string.
|
||||
//
|
||||
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
|
||||
// the minimal amount of memory because the JsonDocument stores pointers to
|
||||
// the input buffer.
|
||||
// If you use another type of input, ArduinoJson must copy the strings from
|
||||
// the input to the JsonDocument, so you need to increase the capacity of the
|
||||
// JsonDocument.
|
||||
char json[] =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, json);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
std::cerr << "deserializeJson() failed: " << error.c_str() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = doc["sensor"];
|
||||
long time = doc["time"];
|
||||
double latitude = doc["data"][0];
|
||||
double longitude = doc["data"][1];
|
||||
|
||||
// Print values.
|
||||
std::cout << sensor << std::endl;
|
||||
std::cout << time << std::endl;
|
||||
std::cout << latitude << std::endl;
|
||||
std::cout << longitude << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
68
scripts/wandbox/MsgPackParserExample.cpp
Normal file
68
scripts/wandbox/MsgPackParserExample.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 300 is the size of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<300> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject doc(200);
|
||||
|
||||
// MessagePack input string.
|
||||
//
|
||||
// It's better to use a char[] as shown here.
|
||||
// If you use a const char* or a String, ArduinoJson will
|
||||
// have to make a copy of the input in the JsonBuffer.
|
||||
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
|
||||
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
|
||||
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
|
||||
112, 203, 64, 2, 106, 146, 230, 33, 49, 169};
|
||||
// This MessagePack document contains:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [48.75608, 2.302038]
|
||||
// }
|
||||
|
||||
// doc of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
DeserializationError error = deserializeMsgPack(doc, input);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
std::cerr << "deserializeMsgPack() failed: " << error.c_str() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = doc["sensor"];
|
||||
long time = doc["time"];
|
||||
double latitude = doc["data"][0];
|
||||
double longitude = doc["data"][1];
|
||||
|
||||
// Print values.
|
||||
std::cout << sensor << std::endl;
|
||||
std::cout << time << std::endl;
|
||||
std::cout << latitude << std::endl;
|
||||
std::cout << longitude << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
29
scripts/wandbox/publish.sh
Normal file
29
scripts/wandbox/publish.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
ARDUINOJSON_H="$1"
|
||||
|
||||
read_string() {
|
||||
jq --slurp --raw-input '.' "$1"
|
||||
}
|
||||
|
||||
compile() {
|
||||
FILE_PATH="$(dirname $0)/$1.cpp"
|
||||
cat >parameters.json <<END
|
||||
{
|
||||
"code":$(read_string "$FILE_PATH"),
|
||||
"codes": [{"file":"ArduinoJson.h","code":$(read_string "$ARDUINOJSON_H")}],
|
||||
"options": "warning",
|
||||
"compiler": "gcc-4.9.3",
|
||||
"save": true
|
||||
}
|
||||
END
|
||||
URL=$(curl -sS -H "Content-type: application/json" -d @parameters.json https://wandbox.org/api/compile.json | jq --raw-output .url)
|
||||
rm parameters.json
|
||||
echo " $1: $URL"
|
||||
}
|
||||
|
||||
compile "JsonGeneratorExample"
|
||||
compile "JsonParserExample"
|
||||
compile "MsgPackParserExample"
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,26 +1,69 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/version.hpp"
|
||||
#ifndef ARDUINOJSON_DEBUG
|
||||
#ifdef __clang__
|
||||
#pragma clang system_header
|
||||
#elif defined __GNUC__
|
||||
#pragma GCC system_header
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "ArduinoJson/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/StaticJsonDocument.hpp"
|
||||
#include "ArduinoJson/Namespace.hpp"
|
||||
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/Array/ArrayRef.hpp"
|
||||
#include "ArduinoJson/Object/ObjectRef.hpp"
|
||||
#include "ArduinoJson/Variant/VariantRef.hpp"
|
||||
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
|
||||
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonArraySubscript.hpp"
|
||||
#include "ArduinoJson/JsonObjectSubscript.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Array/ArrayImpl.hpp"
|
||||
#include "ArduinoJson/Array/ElementProxy.hpp"
|
||||
#include "ArduinoJson/Array/Utilities.hpp"
|
||||
#include "ArduinoJson/Collection/CollectionImpl.hpp"
|
||||
#include "ArduinoJson/Object/MemberProxy.hpp"
|
||||
#include "ArduinoJson/Object/ObjectImpl.hpp"
|
||||
#include "ArduinoJson/Variant/VariantAsImpl.hpp"
|
||||
#include "ArduinoJson/Variant/VariantImpl.hpp"
|
||||
|
||||
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
||||
#include "ArduinoJson/Json/JsonSerializer.hpp"
|
||||
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
|
||||
|
||||
#include "ArduinoJson/compatibility.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
|
||||
typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
|
||||
typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
|
||||
typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
|
||||
typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
|
||||
typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
|
||||
typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
|
||||
typedef ARDUINOJSON_NAMESPACE::String JsonString;
|
||||
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
|
||||
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
|
||||
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
|
||||
using ARDUINOJSON_NAMESPACE::BasicJsonDocument;
|
||||
using ARDUINOJSON_NAMESPACE::copyArray;
|
||||
using ARDUINOJSON_NAMESPACE::DeserializationError;
|
||||
using ARDUINOJSON_NAMESPACE::deserializeJson;
|
||||
using ARDUINOJSON_NAMESPACE::deserializeMsgPack;
|
||||
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
|
||||
using ARDUINOJSON_NAMESPACE::JsonDocument;
|
||||
using ARDUINOJSON_NAMESPACE::serialized;
|
||||
using ARDUINOJSON_NAMESPACE::serializeJson;
|
||||
using ARDUINOJSON_NAMESPACE::serializeJsonPretty;
|
||||
using ARDUINOJSON_NAMESPACE::serializeMsgPack;
|
||||
using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
|
||||
|
||||
namespace DeserializationOption {
|
||||
using ARDUINOJSON_NAMESPACE::NestingLimit;
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
|
29
src/ArduinoJson/Array/ArrayFunctions.hpp
Normal file
29
src/ArduinoJson/Array/ArrayFunctions.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Collection/CollectionData.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) {
|
||||
return arr ? arr->add(pool) : 0;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
inline void arrayAccept(const CollectionData *arr, Visitor &visitor) {
|
||||
if (arr)
|
||||
visitor.visitArray(*arr);
|
||||
else
|
||||
visitor.visitNull();
|
||||
}
|
||||
|
||||
inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
|
||||
if (lhs == rhs) return true;
|
||||
if (!lhs || !rhs) return false;
|
||||
|
||||
return lhs->equalsArray(*rhs);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
22
src/ArduinoJson/Array/ArrayImpl.hpp
Normal file
22
src/ArduinoJson/Array/ArrayImpl.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Object/ObjectRef.hpp"
|
||||
#include "ArrayRef.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TArray>
|
||||
inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const {
|
||||
return impl()->addElement().template to<ArrayRef>();
|
||||
}
|
||||
|
||||
template <typename TArray>
|
||||
inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
|
||||
return impl()->addElement().template to<ObjectRef>();
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
121
src/ArduinoJson/Array/ArrayIterator.hpp
Normal file
121
src/ArduinoJson/Array/ArrayIterator.hpp
Normal file
@ -0,0 +1,121 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Variant/SlotFunctions.hpp"
|
||||
#include "../Variant/VariantRef.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class VariantPtr {
|
||||
public:
|
||||
VariantPtr(MemoryPool *pool, VariantData *data) : _variant(pool, data) {}
|
||||
|
||||
VariantRef *operator->() {
|
||||
return &_variant;
|
||||
}
|
||||
|
||||
VariantRef &operator*() {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
private:
|
||||
VariantRef _variant;
|
||||
};
|
||||
|
||||
class ArrayIterator {
|
||||
public:
|
||||
ArrayIterator() : _slot(0) {}
|
||||
explicit ArrayIterator(MemoryPool *pool, VariantSlot *slot)
|
||||
: _pool(pool), _slot(slot) {}
|
||||
|
||||
VariantRef operator*() const {
|
||||
return VariantRef(_pool, _slot->data());
|
||||
}
|
||||
VariantPtr operator->() {
|
||||
return VariantPtr(_pool, _slot->data());
|
||||
}
|
||||
|
||||
bool operator==(const ArrayIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const ArrayIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
ArrayIterator &operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArrayIterator &operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
VariantSlot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool *_pool;
|
||||
VariantSlot *_slot;
|
||||
};
|
||||
|
||||
class VariantConstPtr {
|
||||
public:
|
||||
VariantConstPtr(const VariantData *data) : _variant(data) {}
|
||||
|
||||
VariantConstRef *operator->() {
|
||||
return &_variant;
|
||||
}
|
||||
|
||||
VariantConstRef &operator*() {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
private:
|
||||
VariantConstRef _variant;
|
||||
};
|
||||
|
||||
class ArrayConstRefIterator {
|
||||
public:
|
||||
ArrayConstRefIterator() : _slot(0) {}
|
||||
explicit ArrayConstRefIterator(const VariantSlot *slot) : _slot(slot) {}
|
||||
|
||||
VariantConstRef operator*() const {
|
||||
return VariantConstRef(_slot->data());
|
||||
}
|
||||
VariantConstPtr operator->() {
|
||||
return VariantConstPtr(_slot->data());
|
||||
}
|
||||
|
||||
bool operator==(const ArrayConstRefIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const ArrayConstRefIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
ArrayConstRefIterator &operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArrayConstRefIterator &operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const VariantSlot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
const VariantSlot *_slot;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
153
src/ArduinoJson/Array/ArrayRef.hpp
Normal file
153
src/ArduinoJson/Array/ArrayRef.hpp
Normal file
@ -0,0 +1,153 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Variant/VariantData.hpp"
|
||||
#include "ArrayFunctions.hpp"
|
||||
#include "ArrayIterator.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
// Can be very handy to determine the size of a StaticMemoryPool.
|
||||
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class ObjectRef;
|
||||
template <typename>
|
||||
class ElementProxy;
|
||||
|
||||
template <typename TData>
|
||||
class ArrayRefBase {
|
||||
public:
|
||||
operator VariantConstRef() const {
|
||||
const void* data = _data; // prevent warning cast-align
|
||||
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
arrayAccept(_data, visitor);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t memoryUsage() const {
|
||||
return _data ? _data->memoryUsage() : 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t nesting() const {
|
||||
return _data ? _data->nesting() : 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return _data ? _data->size() : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
ArrayRefBase(TData* data) : _data(data) {}
|
||||
TData* _data;
|
||||
};
|
||||
|
||||
class ArrayConstRef : public ArrayRefBase<const CollectionData>,
|
||||
public Visitable {
|
||||
friend class ArrayRef;
|
||||
typedef ArrayRefBase<const CollectionData> base_type;
|
||||
|
||||
public:
|
||||
typedef ArrayConstRefIterator iterator;
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_data->head());
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
FORCE_INLINE ArrayConstRef() : base_type(0) {}
|
||||
FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {}
|
||||
|
||||
FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
|
||||
return arrayEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantConstRef operator[](size_t index) const {
|
||||
return getElement(index);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantConstRef getElement(size_t index) const {
|
||||
return VariantConstRef(_data ? _data->get(index) : 0);
|
||||
}
|
||||
};
|
||||
|
||||
class ArrayRef : public ArrayRefBase<CollectionData>,
|
||||
public ArrayShortcuts<ArrayRef>,
|
||||
public Visitable {
|
||||
typedef ArrayRefBase<CollectionData> base_type;
|
||||
|
||||
public:
|
||||
typedef ArrayIterator iterator;
|
||||
|
||||
FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {}
|
||||
FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data)
|
||||
: base_type(data), _pool(pool) {}
|
||||
|
||||
operator VariantRef() {
|
||||
void* data = _data; // prevent warning cast-align
|
||||
return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
|
||||
}
|
||||
|
||||
operator ArrayConstRef() const {
|
||||
return ArrayConstRef(_data);
|
||||
}
|
||||
|
||||
VariantRef addElement() const {
|
||||
return VariantRef(_pool, arrayAdd(_data, _pool));
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_pool, _data->head());
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
// Copy a ArrayRef
|
||||
FORCE_INLINE bool set(ArrayConstRef src) const {
|
||||
if (!_data || !src._data) return false;
|
||||
return _data->copyFrom(*src._data, _pool);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool operator==(ArrayRef rhs) const {
|
||||
return arrayEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
// Gets the value at the specified index.
|
||||
FORCE_INLINE VariantRef getElement(size_t index) const {
|
||||
return VariantRef(_pool, _data ? _data->get(index) : 0);
|
||||
}
|
||||
|
||||
// Removes element at specified position.
|
||||
FORCE_INLINE void remove(iterator it) const {
|
||||
if (!_data) return;
|
||||
_data->remove(it.internal());
|
||||
}
|
||||
|
||||
// Removes element at specified index.
|
||||
FORCE_INLINE void remove(size_t index) const {
|
||||
if (!_data) return;
|
||||
_data->remove(index);
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool* _pool;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
47
src/ArduinoJson/Array/ArrayShortcuts.hpp
Normal file
47
src/ArduinoJson/Array/ArrayShortcuts.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
// Forward declarations.
|
||||
template <typename>
|
||||
class ElementProxy;
|
||||
|
||||
template <typename TArray>
|
||||
class ArrayShortcuts {
|
||||
public:
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
FORCE_INLINE ElementProxy<const TArray &> operator[](size_t index) const;
|
||||
|
||||
FORCE_INLINE ObjectRef createNestedObject() const;
|
||||
|
||||
FORCE_INLINE ArrayRef createNestedArray() const;
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||
// std::string, String, ObjectRef
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(const T &value) const {
|
||||
return impl()->addElement().set(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(T *value) const {
|
||||
return impl()->addElement().set(value);
|
||||
}
|
||||
|
||||
private:
|
||||
const TArray *impl() const {
|
||||
return static_cast<const TArray *>(this);
|
||||
}
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
165
src/ArduinoJson/Array/ElementProxy.hpp
Normal file
165
src/ArduinoJson/Array/ElementProxy.hpp
Normal file
@ -0,0 +1,165 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Operators/VariantOperators.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TArray>
|
||||
class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||
public Visitable {
|
||||
typedef ElementProxy<TArray> this_type;
|
||||
|
||||
public:
|
||||
FORCE_INLINE ElementProxy(TArray array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
FORCE_INLINE this_type& operator=(const this_type& src) {
|
||||
getUpstreamElement().set(src.as<VariantConstRef>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// operator=(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename T>
|
||||
FORCE_INLINE this_type& operator=(const T& src) {
|
||||
getUpstreamElement().set(src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue)
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE this_type& operator=(T* src) {
|
||||
getUpstreamElement().set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE void clear() const {
|
||||
getUpstreamElement().clear();
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return getUpstreamElement().isNull();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename VariantAs<T>::type as() const {
|
||||
return getUpstreamElement().template as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is() const {
|
||||
return getUpstreamElement().template is<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename VariantTo<T>::type to() const {
|
||||
return getUpstreamElement().template to<T>();
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// bool set(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue& value) const {
|
||||
return getUpstreamElement().set(value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue)
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue* value) const {
|
||||
return getUpstreamElement().set(value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor& visitor) const {
|
||||
return getUpstreamElement().accept(visitor);
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return getUpstreamElement().size();
|
||||
}
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef getMember(TNestedKey* key) const {
|
||||
return getUpstreamElement().getMember(key);
|
||||
}
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef getMember(const TNestedKey& key) const {
|
||||
return getUpstreamElement().getMember(key);
|
||||
}
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef getOrAddMember(TNestedKey* key) const {
|
||||
return getUpstreamElement().getOrAddMember(key);
|
||||
}
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef getOrAddMember(const TNestedKey& key) const {
|
||||
return getUpstreamElement().getOrAddMember(key);
|
||||
}
|
||||
|
||||
VariantRef addElement() const {
|
||||
return getUpstreamElement().addElement();
|
||||
}
|
||||
|
||||
VariantRef getElement(size_t index) const {
|
||||
return getUpstreamElement().getElement(index);
|
||||
}
|
||||
|
||||
FORCE_INLINE void remove(size_t index) const {
|
||||
getUpstreamElement().remove(index);
|
||||
}
|
||||
// remove(char*) const
|
||||
// remove(const char*) const
|
||||
// remove(const __FlashStringHelper*) const
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
|
||||
TChar* key) const {
|
||||
getUpstreamElement().remove(key);
|
||||
}
|
||||
// remove(const std::string&) const
|
||||
// remove(const String&) const
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
|
||||
const TString& key) const {
|
||||
getUpstreamElement().remove(key);
|
||||
}
|
||||
|
||||
private:
|
||||
FORCE_INLINE VariantRef getUpstreamElement() const {
|
||||
return _array.getElement(_index);
|
||||
}
|
||||
|
||||
TArray _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
template <typename TArray>
|
||||
inline ElementProxy<const TArray&> ArrayShortcuts<TArray>::operator[](
|
||||
size_t index) const {
|
||||
return ElementProxy<const TArray&>(*impl(), index);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
66
src/ArduinoJson/Array/Utilities.hpp
Normal file
66
src/ArduinoJson/Array/Utilities.hpp
Normal file
@ -0,0 +1,66 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArrayRef.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// Copy a 1D array to a JsonArray
|
||||
template <typename T, size_t N>
|
||||
inline bool copyArray(T (&src)[N], ArrayRef dst) {
|
||||
return copyArray(src, N, dst);
|
||||
}
|
||||
|
||||
// Copy a 1D array to a JsonArray
|
||||
template <typename T>
|
||||
inline bool copyArray(T* src, size_t len, ArrayRef dst) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ok &= dst.add(src[i]);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Copy a 2D array to a JsonArray
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
inline bool copyArray(T (&src)[N1][N2], ArrayRef dst) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < N1; i++) {
|
||||
ArrayRef nestedArray = dst.createNestedArray();
|
||||
for (size_t j = 0; j < N2; j++) {
|
||||
ok &= nestedArray.add(src[i][j]);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Copy a JsonArray to a 1D array
|
||||
template <typename T, size_t N>
|
||||
inline size_t copyArray(ArrayConstRef src, T (&dst)[N]) {
|
||||
return copyArray(src, dst, N);
|
||||
}
|
||||
|
||||
// Copy a JsonArray to a 1D array
|
||||
template <typename T>
|
||||
inline size_t copyArray(ArrayConstRef src, T* dst, size_t len) {
|
||||
size_t i = 0;
|
||||
for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < len;
|
||||
++it)
|
||||
dst[i++] = *it;
|
||||
return i;
|
||||
}
|
||||
|
||||
// Copy a JsonArray to a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
inline void copyArray(ArrayConstRef src, T (&dst)[N1][N2]) {
|
||||
size_t i = 0;
|
||||
for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < N1;
|
||||
++it) {
|
||||
copyArray(it->as<ArrayConstRef>(), dst[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
70
src/ArduinoJson/Collection/CollectionData.hpp
Normal file
70
src/ArduinoJson/Collection/CollectionData.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class MemoryPool;
|
||||
class VariantData;
|
||||
class VariantSlot;
|
||||
|
||||
class CollectionData {
|
||||
VariantSlot *_head;
|
||||
VariantSlot *_tail;
|
||||
|
||||
public:
|
||||
// Must be a POD!
|
||||
// - no constructor
|
||||
// - no destructor
|
||||
// - no virtual
|
||||
// - no inheritance
|
||||
VariantSlot *addSlot(MemoryPool *);
|
||||
|
||||
VariantData *add(MemoryPool *pool);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData *add(TAdaptedString key, MemoryPool *pool);
|
||||
|
||||
void clear();
|
||||
|
||||
template <typename TAdaptedString>
|
||||
bool containsKey(const TAdaptedString &key) const;
|
||||
|
||||
bool copyFrom(const CollectionData &src, MemoryPool *pool);
|
||||
|
||||
bool equalsArray(const CollectionData &other) const;
|
||||
bool equalsObject(const CollectionData &other) const;
|
||||
|
||||
VariantData *get(size_t index) const;
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData *get(TAdaptedString key) const;
|
||||
|
||||
VariantSlot *head() const {
|
||||
return _head;
|
||||
}
|
||||
|
||||
void remove(size_t index);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void remove(TAdaptedString key) {
|
||||
remove(getSlot(key));
|
||||
}
|
||||
|
||||
void remove(VariantSlot *slot);
|
||||
|
||||
size_t memoryUsage() const;
|
||||
size_t nesting() const;
|
||||
size_t size() const;
|
||||
|
||||
private:
|
||||
VariantSlot *getSlot(size_t index) const;
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantSlot *getSlot(TAdaptedString key) const;
|
||||
|
||||
VariantSlot *getPreviousSlot(VariantSlot *) const;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
163
src/ArduinoJson/Collection/CollectionImpl.hpp
Normal file
163
src/ArduinoJson/Collection/CollectionImpl.hpp
Normal file
@ -0,0 +1,163 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Variant/VariantData.hpp"
|
||||
#include "CollectionData.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
|
||||
VariantSlot* slot = pool->allocVariant();
|
||||
if (!slot) return 0;
|
||||
|
||||
if (_tail) {
|
||||
_tail->setNextNotNull(slot);
|
||||
_tail = slot;
|
||||
} else {
|
||||
_head = slot;
|
||||
_tail = slot;
|
||||
}
|
||||
|
||||
slot->clear();
|
||||
return slot;
|
||||
}
|
||||
|
||||
inline VariantData* CollectionData::add(MemoryPool* pool) {
|
||||
return slotData(addSlot(pool));
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) {
|
||||
VariantSlot* slot = addSlot(pool);
|
||||
if (!slotSetKey(slot, key, pool)) return 0;
|
||||
return slot->data();
|
||||
}
|
||||
|
||||
inline void CollectionData::clear() {
|
||||
_head = 0;
|
||||
_tail = 0;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline bool CollectionData::containsKey(const TAdaptedString& key) const {
|
||||
return getSlot(key) != 0;
|
||||
}
|
||||
|
||||
inline bool CollectionData::copyFrom(const CollectionData& src,
|
||||
MemoryPool* pool) {
|
||||
clear();
|
||||
for (VariantSlot* s = src._head; s; s = s->next()) {
|
||||
VariantData* var;
|
||||
if (s->key() != 0) {
|
||||
if (s->ownsKey())
|
||||
var = add(RamStringAdapter(s->key()), pool);
|
||||
else
|
||||
var = add(ConstRamStringAdapter(s->key()), pool);
|
||||
} else {
|
||||
var = add(pool);
|
||||
}
|
||||
if (!var) return false;
|
||||
if (!var->copyFrom(*s->data(), pool)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool CollectionData::equalsObject(const CollectionData& other) const {
|
||||
size_t count = 0;
|
||||
for (VariantSlot* slot = _head; slot; slot = slot->next()) {
|
||||
VariantData* v1 = slot->data();
|
||||
VariantData* v2 = other.get(adaptString(slot->key()));
|
||||
if (!variantEquals(v1, v2)) return false;
|
||||
count++;
|
||||
}
|
||||
return count == other.size();
|
||||
}
|
||||
|
||||
inline bool CollectionData::equalsArray(const CollectionData& other) const {
|
||||
VariantSlot* s1 = _head;
|
||||
VariantSlot* s2 = other._head;
|
||||
for (;;) {
|
||||
if (s1 == s2) return true;
|
||||
if (!s1 || !s2) return false;
|
||||
if (!variantEquals(s1->data(), s2->data())) return false;
|
||||
s1 = s1->next();
|
||||
s2 = s2->next();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
|
||||
VariantSlot* slot = _head;
|
||||
while (slot) {
|
||||
if (key.equals(slot->key())) break;
|
||||
slot = slot->next();
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
inline VariantSlot* CollectionData::getSlot(size_t index) const {
|
||||
return _head->next(index);
|
||||
}
|
||||
|
||||
inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
|
||||
VariantSlot* current = _head;
|
||||
while (current) {
|
||||
VariantSlot* next = current->next();
|
||||
if (next == target) return current;
|
||||
current = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* CollectionData::get(TAdaptedString key) const {
|
||||
VariantSlot* slot = getSlot(key);
|
||||
return slot ? slot->data() : 0;
|
||||
}
|
||||
|
||||
inline VariantData* CollectionData::get(size_t index) const {
|
||||
VariantSlot* slot = getSlot(index);
|
||||
return slot ? slot->data() : 0;
|
||||
}
|
||||
|
||||
inline void CollectionData::remove(VariantSlot* slot) {
|
||||
if (!slot) return;
|
||||
VariantSlot* prev = getPreviousSlot(slot);
|
||||
VariantSlot* next = slot->next();
|
||||
if (prev)
|
||||
prev->setNext(next);
|
||||
else
|
||||
_head = next;
|
||||
if (!next) _tail = prev;
|
||||
}
|
||||
|
||||
inline void CollectionData::remove(size_t index) {
|
||||
remove(getSlot(index));
|
||||
}
|
||||
|
||||
inline size_t CollectionData::memoryUsage() const {
|
||||
size_t total = 0;
|
||||
for (VariantSlot* s = _head; s; s = s->next()) {
|
||||
total += sizeof(VariantSlot) + s->data()->memoryUsage();
|
||||
if (s->ownsKey()) total += strlen(s->key()) + 1;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
inline size_t CollectionData::nesting() const {
|
||||
size_t maxChildNesting = 0;
|
||||
for (VariantSlot* s = _head; s; s = s->next()) {
|
||||
size_t childNesting = s->data()->nesting();
|
||||
if (childNesting > maxChildNesting) maxChildNesting = childNesting;
|
||||
}
|
||||
return maxChildNesting + 1;
|
||||
}
|
||||
|
||||
inline size_t CollectionData::size() const {
|
||||
return slotSize(_head);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,9 +1,23 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ARDUINOJSON_HAS_INT64 1
|
||||
#else
|
||||
#define ARDUINOJSON_HAS_INT64 0
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#define ARDUINOJSON_HAS_LONG_LONG 1
|
||||
#define ARDUINOJSON_HAS_NULLPTR 1
|
||||
#else
|
||||
#define ARDUINOJSON_HAS_LONG_LONG 0
|
||||
#define ARDUINOJSON_HAS_NULLPTR 0
|
||||
#endif
|
||||
|
||||
// Small or big machine?
|
||||
#ifndef ARDUINOJSON_EMBEDDED_MODE
|
||||
#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
|
||||
@ -25,9 +39,6 @@
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
|
||||
// Embedded systems usually don't have std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
@ -53,22 +64,13 @@
|
||||
|
||||
// Use long long when available
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64
|
||||
#define ARDUINOJSON_USE_LONG_LONG 1
|
||||
#else
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Use _int64 on old versions of Visual Studio
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
#define ARDUINOJSON_USE_INT64 1
|
||||
#else
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// On a computer, we can use std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
#define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||
@ -88,28 +90,38 @@
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
// Enable support for Arduino String
|
||||
// Enable support for Arduino's String class
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||
#endif
|
||||
|
||||
// Enable support for Arduino Stream
|
||||
// Enable support for Arduino's Stream class
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
|
||||
#endif
|
||||
|
||||
// Enable support for Arduino's Print class
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1
|
||||
#endif
|
||||
|
||||
#else // ARDUINO
|
||||
|
||||
// Disable support for Arduino String
|
||||
// Enable support for Arduino's String class
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||
#endif
|
||||
|
||||
// Disable support for Arduino Stream
|
||||
// Enable support for Arduino's Stream class
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
|
||||
#endif
|
||||
|
||||
// Enable support for Arduino's Print class
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
|
||||
#endif
|
||||
|
||||
#endif // ARDUINO
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||
@ -120,14 +132,19 @@
|
||||
#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
|
||||
// Convert unicode escape sequence (\u0123) to UTF-8
|
||||
#ifndef ARDUINOJSON_DECODE_UNICODE
|
||||
#define ARDUINOJSON_DECODE_UNICODE 0
|
||||
#endif
|
||||
|
||||
// Support NaN in JSON
|
||||
#ifndef ARDUINOJSON_ENABLE_NAN
|
||||
#define ARDUINOJSON_ENABLE_NAN 0
|
||||
#endif
|
||||
|
||||
// Support Infinity in JSON
|
||||
#ifndef ARDUINOJSON_ENABLE_INFINITY
|
||||
#define ARDUINOJSON_ENABLE_INFINITY 0
|
||||
#endif
|
||||
|
||||
// Control the exponentiation threshold for big numbers
|
||||
@ -141,16 +158,16 @@
|
||||
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
|
||||
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_LITTLE_ENDIAN
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
|
||||
(defined(__LITTLE_ENDIAN__))
|
||||
defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64)
|
||||
#define ARDUINOJSON_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define ARDUINOJSON_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_TAB
|
||||
#define ARDUINOJSON_TAB " "
|
||||
#endif
|
||||
|
@ -1,17 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class JsonVariantTag {};
|
||||
|
||||
template <typename T>
|
||||
struct IsVariant : is_base_of<JsonVariantTag, T> {};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,18 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
typedef double JsonFloat;
|
||||
#else
|
||||
typedef float JsonFloat;
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
typedef long long JsonInteger;
|
||||
typedef unsigned long long JsonUInt;
|
||||
#elif ARDUINOJSON_USE_INT64
|
||||
typedef __int64 JsonInteger;
|
||||
typedef unsigned _int64 JsonUInt;
|
||||
#else
|
||||
typedef long JsonInteger;
|
||||
typedef unsigned long JsonUInt;
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// JsonVariant::as<T>()
|
||||
template <typename T>
|
||||
struct JsonVariantAs {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<char*> {
|
||||
typedef const char* type;
|
||||
};
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,30 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
// Forward declarations
|
||||
struct JsonArrayData;
|
||||
struct JsonObjectData;
|
||||
|
||||
// A union that defines the actual content of a JsonVariant.
|
||||
// The enum JsonVariantType determines which member is in use.
|
||||
union JsonVariantContent {
|
||||
JsonFloat asFloat; // used for double and float
|
||||
JsonUInt asInteger; // used for bool, char, short, int and longs
|
||||
JsonArrayData* asArray; // asArray cannot be null
|
||||
JsonObjectData* asObject; // asObject cannot be null
|
||||
const char* asString; // asString can be null
|
||||
struct {
|
||||
const char* data;
|
||||
size_t size;
|
||||
} asRaw;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,23 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault {
|
||||
static T get() {
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_UNDEFINED, // JsonVariant has not been initialized
|
||||
JSON_UNPARSED, // JsonVariant contains an unparsed string
|
||||
JSON_STRING, // JsonVariant stores a const char*
|
||||
JSON_BOOLEAN, // JsonVariant stores a bool
|
||||
JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt
|
||||
JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated
|
||||
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArrayData
|
||||
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObjectData
|
||||
JSON_FLOAT // JsonVariant stores a JsonFloat
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,88 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListIterator.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A singly linked list of T.
|
||||
// The linked list is composed of ListNode<T>.
|
||||
// It is derived by JsonArrayData and JsonObjectData
|
||||
template <typename T>
|
||||
class List {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ListNode<T> node_type;
|
||||
typedef ListIterator<T> iterator;
|
||||
typedef ListConstIterator<T> const_iterator;
|
||||
|
||||
explicit List(JsonBuffer *buf) : _buffer(buf), _firstNode(NULL) {}
|
||||
|
||||
// Returns the numbers of elements in the list.
|
||||
// For a JsonObjectData, it would return the number of key-value pairs
|
||||
size_t size() const {
|
||||
size_t nodeCount = 0;
|
||||
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
|
||||
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);
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(NULL);
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return const_iterator(_firstNode);
|
||||
}
|
||||
const_iterator end() const {
|
||||
return const_iterator(NULL);
|
||||
}
|
||||
|
||||
void remove(iterator it) {
|
||||
node_type *nodeToRemove = it._node;
|
||||
if (!nodeToRemove) return;
|
||||
if (nodeToRemove == _firstNode) {
|
||||
_firstNode = nodeToRemove->next;
|
||||
} else {
|
||||
for (node_type *node = _firstNode; node; node = node->next)
|
||||
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
|
||||
}
|
||||
}
|
||||
|
||||
JsonBuffer &buffer() const {
|
||||
return *_buffer;
|
||||
}
|
||||
JsonBuffer *_buffer; // TODO!!
|
||||
|
||||
protected:
|
||||
void clear() {
|
||||
_firstNode = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
node_type *_firstNode;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,50 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ListNode.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A read-only forward itertor for List<T>
|
||||
template <typename T>
|
||||
class ListConstIterator {
|
||||
public:
|
||||
explicit ListConstIterator(const ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
const T &operator*() const {
|
||||
return _node->content;
|
||||
}
|
||||
const T *operator->() {
|
||||
return &_node->content;
|
||||
}
|
||||
|
||||
bool operator==(const ListConstIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
}
|
||||
|
||||
bool operator!=(const ListConstIterator<T> &other) const {
|
||||
return _node != other._node;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator++() {
|
||||
if (_node) _node = _node->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListNode.hpp"
|
||||
|
||||
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) {}
|
||||
|
||||
T &operator*() const {
|
||||
return _node->content;
|
||||
}
|
||||
T *operator->() {
|
||||
return &_node->content;
|
||||
}
|
||||
|
||||
bool operator==(const ListIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
}
|
||||
|
||||
bool operator!=(const ListIterator<T> &other) const {
|
||||
return _node != other._node;
|
||||
}
|
||||
|
||||
ListIterator<T> &operator++() {
|
||||
if (_node) _node = _node->next;
|
||||
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);
|
||||
}
|
||||
|
||||
private:
|
||||
ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for NULL
|
||||
|
||||
#include "../Memory/JsonBufferAllocated.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A node for a singly-linked list.
|
||||
// Used by List<T> and its iterators.
|
||||
template <typename T>
|
||||
struct ListNode : public Internals::JsonBufferAllocated {
|
||||
ListNode() throw() : next(NULL) {}
|
||||
|
||||
ListNode<T> *next;
|
||||
T content;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,53 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Strings/StringTypes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename Source, typename Enable = void>
|
||||
struct ValueSaver {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& destination, Source source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// We duplicate all strings except const char*
|
||||
template <typename TString>
|
||||
struct ValueSaver<
|
||||
TString, typename enable_if<IsString<TString>::value &&
|
||||
!is_same<const char*, TString>::value>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer* buffer, Destination& dest, TString source) {
|
||||
const char* dup = makeString(source).save(buffer);
|
||||
if (!dup) return false;
|
||||
dest = dup;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// We duplicate all SerializedValue<T> except SerializedValue<const char*>
|
||||
template <typename TString>
|
||||
struct ValueSaver<
|
||||
const SerializedValue<TString>&,
|
||||
typename enable_if<!is_same<const char*, TString>::value>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer* buffer, Destination& dest,
|
||||
const SerializedValue<TString>& source) {
|
||||
const char* dup = makeString(source.data(), source.size()).save(buffer);
|
||||
if (!dup) return false;
|
||||
dest = SerializedValue<const char*>(dup, source.size());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
@ -8,34 +8,24 @@
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct ArduinoStreamReader {
|
||||
Stream& _stream;
|
||||
char _current;
|
||||
bool _ended;
|
||||
|
||||
public:
|
||||
explicit ArduinoStreamReader(Stream& stream)
|
||||
: _stream(stream), _current(0), _ended(false) {}
|
||||
explicit ArduinoStreamReader(Stream& stream) : _stream(stream) {}
|
||||
|
||||
char read() {
|
||||
int read() {
|
||||
// don't use _stream.read() as it ignores the timeout
|
||||
char c = 0;
|
||||
_ended = _stream.readBytes(&c, 1) == 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ended;
|
||||
uint8_t c;
|
||||
return _stream.readBytes(&c, 1) ? c : -1;
|
||||
}
|
||||
};
|
||||
|
||||
inline ArduinoStreamReader makeReader(Stream& input) {
|
||||
return ArduinoStreamReader(input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -1,64 +1,67 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T>
|
||||
struct IsCharOrVoid {
|
||||
static const bool value =
|
||||
is_same<T, void>::value || is_same<T, char>::value ||
|
||||
is_same<T, unsigned char>::value || is_same<T, signed char>::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
|
||||
|
||||
template <typename TChar>
|
||||
class UnsafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
explicit UnsafeCharPointerReader(const TChar* ptr)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")) {}
|
||||
explicit UnsafeCharPointerReader(const char* ptr)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// we cannot know
|
||||
return false;
|
||||
int read() {
|
||||
return static_cast<unsigned char>(*_ptr++);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
class SafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
const TChar* _end;
|
||||
const char* _ptr;
|
||||
const char* _end;
|
||||
|
||||
public:
|
||||
explicit SafeCharPointerReader(const TChar* ptr, size_t len)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")),
|
||||
_end(_ptr + len) {}
|
||||
explicit SafeCharPointerReader(const char* ptr, size_t len)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")), _end(_ptr + len) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
int read() {
|
||||
if (_ptr < _end)
|
||||
return static_cast<unsigned char>(*_ptr++);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
inline UnsafeCharPointerReader<TChar> makeReader(TChar* input) {
|
||||
return UnsafeCharPointerReader<TChar>(input);
|
||||
inline typename enable_if<IsCharOrVoid<TChar>::value,
|
||||
UnsafeCharPointerReader>::type
|
||||
makeReader(TChar* input) {
|
||||
return UnsafeCharPointerReader(reinterpret_cast<const char*>(input));
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline SafeCharPointerReader<TChar> makeReader(TChar* input, size_t n) {
|
||||
return SafeCharPointerReader<TChar>(input, n);
|
||||
inline
|
||||
typename enable_if<IsCharOrVoid<TChar>::value, SafeCharPointerReader>::type
|
||||
makeReader(TChar* input, size_t n) {
|
||||
return SafeCharPointerReader(reinterpret_cast<const char*>(input), n);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
inline SafeCharPointerReader<char> makeReader(const String& input) {
|
||||
return SafeCharPointerReader<char>(input.c_str(), input.length());
|
||||
inline SafeCharPointerReader makeReader(const ::String& input) {
|
||||
return SafeCharPointerReader(input.c_str(), input.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
@ -8,9 +8,13 @@
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class DeserializationError {
|
||||
// safe bool idiom
|
||||
typedef void (DeserializationError::*bool_type)() const;
|
||||
void safeBoolHelper() const {}
|
||||
|
||||
public:
|
||||
enum Code {
|
||||
Ok,
|
||||
@ -22,26 +26,52 @@ class DeserializationError {
|
||||
};
|
||||
|
||||
DeserializationError() {}
|
||||
DeserializationError(Code code) : _code(code) {}
|
||||
DeserializationError(Code c) : _code(c) {}
|
||||
|
||||
friend bool operator==(const DeserializationError& err, Code code) {
|
||||
return err._code == code;
|
||||
// Compare with DeserializationError
|
||||
friend bool operator==(const DeserializationError& lhs,
|
||||
const DeserializationError& rhs) {
|
||||
return lhs._code == rhs._code;
|
||||
}
|
||||
friend bool operator!=(const DeserializationError& lhs,
|
||||
const DeserializationError& rhs) {
|
||||
return lhs._code != rhs._code;
|
||||
}
|
||||
|
||||
friend bool operator==(Code code, const DeserializationError& err) {
|
||||
return err._code == code;
|
||||
// Compare with Code
|
||||
friend bool operator==(const DeserializationError& lhs, Code rhs) {
|
||||
return lhs._code == rhs;
|
||||
}
|
||||
friend bool operator==(Code lhs, const DeserializationError& rhs) {
|
||||
return lhs == rhs._code;
|
||||
}
|
||||
friend bool operator!=(const DeserializationError& lhs, Code rhs) {
|
||||
return lhs._code != rhs;
|
||||
}
|
||||
friend bool operator!=(Code lhs, const DeserializationError& rhs) {
|
||||
return lhs != rhs._code;
|
||||
}
|
||||
|
||||
friend bool operator!=(const DeserializationError& err, Code code) {
|
||||
return err._code != code;
|
||||
// Behaves like a bool
|
||||
operator bool_type() const {
|
||||
return _code != Ok ? &DeserializationError::safeBoolHelper : 0;
|
||||
}
|
||||
friend bool operator==(bool value, const DeserializationError& err) {
|
||||
return static_cast<bool>(err) == value;
|
||||
}
|
||||
friend bool operator==(const DeserializationError& err, bool value) {
|
||||
return static_cast<bool>(err) == value;
|
||||
}
|
||||
friend bool operator!=(bool value, const DeserializationError& err) {
|
||||
return static_cast<bool>(err) != value;
|
||||
}
|
||||
friend bool operator!=(const DeserializationError& err, bool value) {
|
||||
return static_cast<bool>(err) != value;
|
||||
}
|
||||
|
||||
friend bool operator!=(Code code, const DeserializationError& err) {
|
||||
return err._code != code;
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return _code != Ok;
|
||||
// Returns internal enum, useful for switch statement
|
||||
Code code() const {
|
||||
return _code;
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
@ -80,4 +110,4 @@ inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -1,13 +1,12 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class UnsafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
|
||||
@ -15,14 +14,9 @@ class UnsafeFlashStringReader {
|
||||
explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||
|
||||
char read() {
|
||||
int read() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// this reader cannot detect the end
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class SafeFlashStringReader {
|
||||
@ -33,12 +27,11 @@ class SafeFlashStringReader {
|
||||
explicit SafeFlashStringReader(const __FlashStringHelper* ptr, size_t size)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
|
||||
|
||||
char read() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
int read() {
|
||||
if (_ptr < _end)
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
@ -50,7 +43,6 @@ inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
|
||||
size_t size) {
|
||||
return SafeFlashStringReader(input, size);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -1,11 +1,10 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TIterator>
|
||||
class IteratorReader {
|
||||
@ -15,12 +14,11 @@ class IteratorReader {
|
||||
explicit IteratorReader(TIterator begin, TIterator end)
|
||||
: _ptr(begin), _end(end) {}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
|
||||
char read() {
|
||||
return char(*_ptr++);
|
||||
int read() {
|
||||
if (_ptr < _end)
|
||||
return static_cast<unsigned char>(*_ptr++);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
@ -30,5 +28,4 @@ inline IteratorReader<typename TInput::const_iterator> makeReader(
|
||||
return IteratorReader<typename TInput::const_iterator>(input.begin(),
|
||||
input.end());
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
17
src/ArduinoJson/Deserialization/NestingLimit.hpp
Normal file
17
src/ArduinoJson/Deserialization/NestingLimit.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct NestingLimit {
|
||||
NestingLimit() : value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
||||
explicit NestingLimit(uint8_t n) : value(n) {}
|
||||
|
||||
uint8_t value;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
@ -8,8 +8,7 @@
|
||||
|
||||
#include <istream>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StdStreamReader {
|
||||
std::istream& _stream;
|
||||
@ -19,12 +18,8 @@ class StdStreamReader {
|
||||
explicit StdStreamReader(std::istream& stream)
|
||||
: _stream(stream), _current(0) {}
|
||||
|
||||
bool ended() const {
|
||||
return _stream.eof();
|
||||
}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(_stream.get());
|
||||
int read() {
|
||||
return _stream.get();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -34,7 +29,6 @@ class StdStreamReader {
|
||||
inline StdStreamReader makeReader(std::istream& input) {
|
||||
return StdStreamReader(input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -1,82 +1,76 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../StringStorage/StringStorage.hpp"
|
||||
#include "./ArduinoStreamReader.hpp"
|
||||
#include "./CharPointerReader.hpp"
|
||||
#include "./DeserializationError.hpp"
|
||||
#include "./FlashStringReader.hpp"
|
||||
#include "./IteratorReader.hpp"
|
||||
#include "./StdStreamReader.hpp"
|
||||
#include "ArduinoStreamReader.hpp"
|
||||
#include "CharPointerReader.hpp"
|
||||
#include "DeserializationError.hpp"
|
||||
#include "FlashStringReader.hpp"
|
||||
#include "IteratorReader.hpp"
|
||||
#include "NestingLimit.hpp"
|
||||
#include "StdStreamReader.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <template <typename, typename> class TDeserializer,
|
||||
typename TJsonBuffer, typename TReader, typename TWriter>
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(TJsonBuffer *buffer,
|
||||
template <template <typename, typename> class TDeserializer, typename TReader,
|
||||
typename TWriter>
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
|
||||
TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit) {
|
||||
return TDeserializer<TReader, TWriter>(buffer, reader, writer, nestingLimit);
|
||||
return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit);
|
||||
}
|
||||
|
||||
// DeserializationError deserialize(TDocument& doc, TString input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TString = const std::string&, const String&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TString>
|
||||
typename Internals::enable_if<!Internals::is_array<TString>::value,
|
||||
DeserializationError>::type
|
||||
deserialize(TDocument &doc, const TString &input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TChar>
|
||||
DeserializationError deserialize(TDocument &doc, TChar *input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input, size_t
|
||||
// inputSize);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TChar>
|
||||
DeserializationError deserialize(TDocument &doc, TChar *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
// deserialize(JsonDocument&, const std::string&);
|
||||
// deserialize(JsonDocument&, const String&);
|
||||
template <template <typename, typename> class TDeserializer, typename TString>
|
||||
typename enable_if<!is_array<TString>::value, DeserializationError>::type
|
||||
deserialize(JsonDocument &doc, const TString &input,
|
||||
NestingLimit nestingLimit) {
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
&doc.buffer(), makeReader(input, inputSize),
|
||||
makeStringStorage(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
doc.memoryPool(), makeReader(input),
|
||||
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
||||
.parse(doc.data());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TStream input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TStream = std::istream&, Stream&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TStream>
|
||||
DeserializationError deserialize(TDocument &doc, TStream &input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
// deserialize(JsonDocument&, char*);
|
||||
// deserialize(JsonDocument&, const char*);
|
||||
// deserialize(JsonDocument&, const __FlashStringHelper*);
|
||||
template <template <typename, typename> class TDeserializer, typename TChar>
|
||||
DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
||||
NestingLimit nestingLimit) {
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), makeReader(input),
|
||||
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
||||
.parse(doc.data());
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
//
|
||||
// deserialize(JsonDocument&, char*, size_t);
|
||||
// deserialize(JsonDocument&, const char*, size_t);
|
||||
// deserialize(JsonDocument&, const __FlashStringHelper*, size_t);
|
||||
template <template <typename, typename> class TDeserializer, typename TChar>
|
||||
DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
||||
size_t inputSize, NestingLimit nestingLimit) {
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), makeReader(input, inputSize),
|
||||
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
||||
.parse(doc.data());
|
||||
}
|
||||
//
|
||||
// deserialize(JsonDocument&, std::istream&);
|
||||
// deserialize(JsonDocument&, Stream&);
|
||||
template <template <typename, typename> class TDeserializer, typename TStream>
|
||||
DeserializationError deserialize(JsonDocument &doc, TStream &input,
|
||||
NestingLimit nestingLimit) {
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), makeReader(input),
|
||||
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
||||
.parse(doc.data());
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
89
src/ArduinoJson/Document/BasicJsonDocument.hpp
Normal file
89
src/ArduinoJson/Document/BasicJsonDocument.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonDocument.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TAllocator>
|
||||
class AllocatorOwner {
|
||||
protected:
|
||||
AllocatorOwner() {}
|
||||
AllocatorOwner(const AllocatorOwner& src) : _allocator(src._allocator) {}
|
||||
AllocatorOwner(TAllocator allocator) : _allocator(allocator) {}
|
||||
|
||||
void* allocate(size_t n) {
|
||||
return _allocator.allocate(n);
|
||||
}
|
||||
|
||||
void deallocate(void* p) {
|
||||
_allocator.deallocate(p);
|
||||
}
|
||||
|
||||
private:
|
||||
TAllocator _allocator;
|
||||
};
|
||||
|
||||
template <typename TAllocator>
|
||||
class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
||||
public:
|
||||
explicit BasicJsonDocument(size_t capa, TAllocator allocator = TAllocator())
|
||||
: AllocatorOwner<TAllocator>(allocator), JsonDocument(allocPool(capa)) {}
|
||||
|
||||
BasicJsonDocument(const BasicJsonDocument& src)
|
||||
: AllocatorOwner<TAllocator>(src),
|
||||
JsonDocument(allocPool(src.memoryUsage())) {
|
||||
set(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
BasicJsonDocument(const T& src,
|
||||
typename enable_if<IsVisitable<T>::value>::type* = 0)
|
||||
: JsonDocument(allocPool(src.memoryUsage())) {
|
||||
set(src);
|
||||
}
|
||||
|
||||
// disambiguate
|
||||
BasicJsonDocument(VariantRef src)
|
||||
: JsonDocument(allocPool(src.memoryUsage())) {
|
||||
set(src);
|
||||
}
|
||||
|
||||
~BasicJsonDocument() {
|
||||
freePool();
|
||||
}
|
||||
|
||||
BasicJsonDocument& operator=(const BasicJsonDocument& src) {
|
||||
reallocPoolIfTooSmall(src.memoryUsage());
|
||||
set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
BasicJsonDocument& operator=(const T& src) {
|
||||
reallocPoolIfTooSmall(src.memoryUsage());
|
||||
set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool allocPool(size_t requiredSize) {
|
||||
size_t capa = addPadding(requiredSize);
|
||||
return MemoryPool(reinterpret_cast<char*>(this->allocate(capa)), capa);
|
||||
}
|
||||
|
||||
void reallocPoolIfTooSmall(size_t requiredSize) {
|
||||
if (requiredSize <= capacity()) return;
|
||||
freePool();
|
||||
replacePool(allocPool(addPadding(requiredSize)));
|
||||
}
|
||||
|
||||
void freePool() {
|
||||
this->deallocate(memoryPool().buffer());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
25
src/ArduinoJson/Document/DynamicJsonDocument.hpp
Normal file
25
src/ArduinoJson/Document/DynamicJsonDocument.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BasicJsonDocument.hpp"
|
||||
|
||||
#include <stdlib.h> // malloc, free
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct DefaultAllocator {
|
||||
void* allocate(size_t n) {
|
||||
return malloc(n);
|
||||
}
|
||||
|
||||
void deallocate(void* p) {
|
||||
free(p);
|
||||
}
|
||||
};
|
||||
|
||||
typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
307
src/ArduinoJson/Document/JsonDocument.hpp
Normal file
307
src/ArduinoJson/Document/JsonDocument.hpp
Normal file
@ -0,0 +1,307 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Memory/MemoryPool.hpp"
|
||||
#include "../Object/ObjectRef.hpp"
|
||||
#include "../Variant/VariantRef.hpp"
|
||||
#include "../Variant/VariantTo.hpp"
|
||||
|
||||
#include "../Array/ElementProxy.hpp"
|
||||
#include "../Object/MemberProxy.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonDocument : public Visitable {
|
||||
public:
|
||||
template <typename Visitor>
|
||||
void accept(Visitor& visitor) const {
|
||||
return getVariant().accept(visitor);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename VariantAs<T>::type as() {
|
||||
return getVariant().template as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename VariantConstAs<T>::type as() const {
|
||||
return getVariant().template as<T>();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_pool.clear();
|
||||
_data.setNull();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return getVariant().template is<T>();
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return getVariant().isNull();
|
||||
}
|
||||
|
||||
size_t memoryUsage() const {
|
||||
return _pool.size();
|
||||
}
|
||||
|
||||
size_t nesting() const {
|
||||
return _data.nesting();
|
||||
}
|
||||
|
||||
size_t capacity() const {
|
||||
return _pool.capacity();
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return _data.size();
|
||||
}
|
||||
|
||||
bool set(const JsonDocument& src) {
|
||||
return to<VariantRef>().set(src.as<VariantRef>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set(
|
||||
const T& src) {
|
||||
return to<VariantRef>().set(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename VariantTo<T>::type to() {
|
||||
clear();
|
||||
return getVariant().template to<T>();
|
||||
}
|
||||
|
||||
// for internal use only
|
||||
MemoryPool& memoryPool() {
|
||||
return _pool;
|
||||
}
|
||||
|
||||
VariantData& data() {
|
||||
return _data;
|
||||
}
|
||||
|
||||
ArrayRef createNestedArray() {
|
||||
return addElement().to<ArrayRef>();
|
||||
}
|
||||
|
||||
// createNestedArray(char*)
|
||||
// createNestedArray(const char*)
|
||||
// createNestedArray(const __FlashStringHelper*)
|
||||
template <typename TChar>
|
||||
ArrayRef createNestedArray(TChar* key) {
|
||||
return getOrAddMember(key).template to<ArrayRef>();
|
||||
}
|
||||
|
||||
// createNestedArray(const std::string&)
|
||||
// createNestedArray(const String&)
|
||||
template <typename TString>
|
||||
ArrayRef createNestedArray(const TString& key) {
|
||||
return getOrAddMember(key).template to<ArrayRef>();
|
||||
}
|
||||
|
||||
ObjectRef createNestedObject() {
|
||||
return addElement().to<ObjectRef>();
|
||||
}
|
||||
|
||||
// createNestedObject(char*)
|
||||
// createNestedObject(const char*)
|
||||
// createNestedObject(const __FlashStringHelper*)
|
||||
template <typename TChar>
|
||||
ObjectRef createNestedObject(TChar* key) {
|
||||
return getOrAddMember(key).template to<ObjectRef>();
|
||||
}
|
||||
|
||||
// createNestedObject(const std::string&)
|
||||
// createNestedObject(const String&)
|
||||
template <typename TString>
|
||||
ObjectRef createNestedObject(const TString& key) {
|
||||
return getOrAddMember(key).template to<ObjectRef>();
|
||||
}
|
||||
|
||||
// containsKey(char*) const
|
||||
// containsKey(const char*) const
|
||||
// containsKey(const __FlashStringHelper*) const
|
||||
template <typename TChar>
|
||||
bool containsKey(TChar* key) const {
|
||||
return !getMember(key).isUndefined();
|
||||
}
|
||||
|
||||
// containsKey(const std::string&) const
|
||||
// containsKey(const String&) const
|
||||
template <typename TString>
|
||||
bool containsKey(const TString& key) const {
|
||||
return !getMember(key).isUndefined();
|
||||
}
|
||||
|
||||
// operator[](const std::string&)
|
||||
// operator[](const String&)
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString>::value,
|
||||
MemberProxy<JsonDocument&, const TString&> >::type
|
||||
operator[](const TString& key) {
|
||||
return MemberProxy<JsonDocument&, const TString&>(*this, key);
|
||||
}
|
||||
|
||||
// operator[](char*)
|
||||
// operator[](const char*)
|
||||
// operator[](const __FlashStringHelper*)
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
|
||||
MemberProxy<JsonDocument&, TChar*> >::type
|
||||
operator[](TChar* key) {
|
||||
return MemberProxy<JsonDocument&, TChar*>(*this, key);
|
||||
}
|
||||
|
||||
// operator[](const std::string&) const
|
||||
// operator[](const String&) const
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString>::value, VariantConstRef>::type
|
||||
operator[](const TString& key) const {
|
||||
return getMember(key);
|
||||
}
|
||||
|
||||
// operator[](char*) const
|
||||
// operator[](const char*) const
|
||||
// operator[](const __FlashStringHelper*) const
|
||||
template <typename TChar>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
|
||||
operator[](TChar* key) const {
|
||||
return getMember(key);
|
||||
}
|
||||
|
||||
FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
|
||||
return ElementProxy<JsonDocument&>(*this, index);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantConstRef operator[](size_t index) const {
|
||||
return getElement(index);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantRef getElement(size_t index) {
|
||||
return VariantRef(&_pool, _data.getElement(index));
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantConstRef getElement(size_t index) const {
|
||||
return VariantConstRef(_data.getElement(index));
|
||||
}
|
||||
|
||||
// JsonVariantConst getMember(char*) const
|
||||
// JsonVariantConst getMember(const char*) const
|
||||
// JsonVariantConst getMember(const __FlashStringHelper*) const
|
||||
template <typename TChar>
|
||||
FORCE_INLINE VariantConstRef getMember(TChar* key) const {
|
||||
return VariantConstRef(_data.getMember(adaptString(key)));
|
||||
}
|
||||
|
||||
// JsonVariantConst getMember(const std::string&) const
|
||||
// JsonVariantConst getMember(const String&) const
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString>::value, VariantConstRef>::type
|
||||
getMember(const TString& key) const {
|
||||
return VariantConstRef(_data.getMember(adaptString(key)));
|
||||
}
|
||||
|
||||
// JsonVariant getMember(char*)
|
||||
// JsonVariant getMember(const char*)
|
||||
// JsonVariant getMember(const __FlashStringHelper*)
|
||||
template <typename TChar>
|
||||
FORCE_INLINE VariantRef getMember(TChar* key) {
|
||||
return VariantRef(&_pool, _data.getMember(adaptString(key)));
|
||||
}
|
||||
|
||||
// JsonVariant getMember(const std::string&)
|
||||
// JsonVariant getMember(const String&)
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
|
||||
getMember(const TString& key) {
|
||||
return VariantRef(&_pool, _data.getMember(adaptString(key)));
|
||||
}
|
||||
|
||||
// getOrAddMember(char*)
|
||||
// getOrAddMember(const char*)
|
||||
// getOrAddMember(const __FlashStringHelper*)
|
||||
template <typename TChar>
|
||||
FORCE_INLINE VariantRef getOrAddMember(TChar* key) {
|
||||
return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
|
||||
}
|
||||
|
||||
// getOrAddMember(const std::string&)
|
||||
// getOrAddMember(const String&)
|
||||
template <typename TString>
|
||||
FORCE_INLINE VariantRef getOrAddMember(const TString& key) {
|
||||
return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantRef addElement() {
|
||||
return VariantRef(&_pool, _data.addElement(&_pool));
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool add(const TValue& value) {
|
||||
return addElement().set(value);
|
||||
}
|
||||
|
||||
// add(char*) const
|
||||
// add(const char*) const
|
||||
// add(const __FlashStringHelper*) const
|
||||
template <typename TChar>
|
||||
FORCE_INLINE bool add(TChar* value) {
|
||||
return addElement().set(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE void remove(size_t index) {
|
||||
_data.remove(index);
|
||||
}
|
||||
// remove(char*)
|
||||
// remove(const char*)
|
||||
// remove(const __FlashStringHelper*)
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
|
||||
TChar* key) {
|
||||
_data.remove(adaptString(key));
|
||||
}
|
||||
// remove(const std::string&)
|
||||
// remove(const String&)
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
|
||||
const TString& key) {
|
||||
_data.remove(adaptString(key));
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonDocument(MemoryPool pool) : _pool(pool) {
|
||||
_data.setNull();
|
||||
}
|
||||
|
||||
JsonDocument(char* buf, size_t capa) : _pool(buf, capa) {
|
||||
_data.setNull();
|
||||
}
|
||||
|
||||
void replacePool(MemoryPool pool) {
|
||||
_pool = pool;
|
||||
}
|
||||
|
||||
private:
|
||||
VariantRef getVariant() {
|
||||
return VariantRef(&_pool, &_data);
|
||||
}
|
||||
|
||||
VariantConstRef getVariant() const {
|
||||
return VariantConstRef(&_data);
|
||||
}
|
||||
|
||||
MemoryPool _pool;
|
||||
VariantData _data;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
51
src/ArduinoJson/Document/StaticJsonDocument.hpp
Normal file
51
src/ArduinoJson/Document/StaticJsonDocument.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonDocument.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <size_t desiredCapacity>
|
||||
class StaticJsonDocument : public JsonDocument {
|
||||
static const size_t _capacity =
|
||||
AddPadding<Max<1, desiredCapacity>::value>::value;
|
||||
|
||||
public:
|
||||
StaticJsonDocument() : JsonDocument(_buffer, _capacity) {}
|
||||
|
||||
StaticJsonDocument(const StaticJsonDocument& src)
|
||||
: JsonDocument(_buffer, _capacity) {
|
||||
set(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
StaticJsonDocument(const T& src,
|
||||
typename enable_if<IsVisitable<T>::value>::type* = 0)
|
||||
: JsonDocument(_buffer, _capacity) {
|
||||
set(src);
|
||||
}
|
||||
|
||||
// disambiguate
|
||||
StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, _capacity) {
|
||||
set(src);
|
||||
}
|
||||
|
||||
StaticJsonDocument operator=(const StaticJsonDocument& src) {
|
||||
set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
StaticJsonDocument operator=(const T& src) {
|
||||
set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
char _buffer[_capacity];
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,84 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Memory/DynamicJsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class DynamicJsonDocument {
|
||||
Internals::DynamicJsonBuffer _buffer;
|
||||
JsonVariant _root;
|
||||
|
||||
public:
|
||||
uint8_t nestingLimit;
|
||||
|
||||
DynamicJsonDocument() : nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
||||
DynamicJsonDocument(size_t capacity)
|
||||
: _buffer(capacity), nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return _root.is<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type as() const {
|
||||
return _root.as<T>();
|
||||
}
|
||||
|
||||
// JsonObject to<JsonObject>()
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonObject>::value,
|
||||
JsonObject>::type
|
||||
to() {
|
||||
clear();
|
||||
JsonObject object(&_buffer);
|
||||
_root = object;
|
||||
return object;
|
||||
}
|
||||
|
||||
// JsonArray to<JsonArray>()
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonArray>::value,
|
||||
JsonArray>::type
|
||||
to() {
|
||||
clear();
|
||||
JsonArray array(&_buffer);
|
||||
_root = array;
|
||||
return array;
|
||||
}
|
||||
|
||||
// JsonVariant& to<JsonVariant>()
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
|
||||
T&>::type
|
||||
to() {
|
||||
clear();
|
||||
return _root;
|
||||
}
|
||||
|
||||
Internals::DynamicJsonBuffer& buffer() {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_buffer.clear();
|
||||
_root = JsonVariant();
|
||||
}
|
||||
|
||||
size_t memoryUsage() const {
|
||||
return _buffer.size();
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor& visitor) const {
|
||||
return _root.visit(visitor);
|
||||
}
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,11 +1,10 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class EscapeSequence {
|
||||
public:
|
||||
@ -33,5 +32,4 @@ class EscapeSequence {
|
||||
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -1,71 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Decorator on top of Print to allow indented output.
|
||||
// This class is used by serializeJsonPretty() but can also be used
|
||||
// for your own purpose, like logging.
|
||||
template <typename Print>
|
||||
class IndentedPrint {
|
||||
public:
|
||||
explicit IndentedPrint(Print &p) : sink(&p) {
|
||||
level = 0;
|
||||
tabSize = 2;
|
||||
isNewLine = true;
|
||||
}
|
||||
|
||||
size_t write(uint8_t c) {
|
||||
size_t n = 0;
|
||||
if (isNewLine) n += writeTabs();
|
||||
n += sink->write(c);
|
||||
isNewLine = c == '\n';
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t write(const uint8_t *s, size_t n) {
|
||||
// TODO: optimize
|
||||
size_t bytesWritten = 0;
|
||||
while (n > 0) {
|
||||
bytesWritten += write(*s++);
|
||||
n--;
|
||||
}
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
// Adds one level of indentation
|
||||
void indent() {
|
||||
if (level < MAX_LEVEL) level++;
|
||||
}
|
||||
|
||||
// Removes one level of indentation
|
||||
void unindent() {
|
||||
if (level > 0) level--;
|
||||
}
|
||||
|
||||
// Set the number of space printed for each level of indentation
|
||||
void setTabSize(uint8_t n) {
|
||||
if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE;
|
||||
}
|
||||
|
||||
private:
|
||||
Print *sink;
|
||||
uint8_t level : 4;
|
||||
uint8_t tabSize : 3;
|
||||
bool isNewLine : 1;
|
||||
|
||||
size_t writeTabs() {
|
||||
size_t n = 0;
|
||||
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
|
||||
return n;
|
||||
}
|
||||
|
||||
static const int MAX_LEVEL = 15; // because it's only 4 bits
|
||||
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,42 +1,41 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Deserialization/deserialize.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Memory/MemoryPool.hpp"
|
||||
#include "../Numbers/parseNumber.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "./EscapeSequence.hpp"
|
||||
#include "../Variant/VariantData.hpp"
|
||||
#include "EscapeSequence.hpp"
|
||||
#include "Utf8.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TReader, typename TStringStorage>
|
||||
class JsonDeserializer {
|
||||
typedef typename remove_reference<TStringStorage>::type::StringBuilder
|
||||
StringBuilder;
|
||||
|
||||
public:
|
||||
JsonDeserializer(JsonBuffer *buffer, TReader reader,
|
||||
JsonDeserializer(MemoryPool &pool, TReader reader,
|
||||
TStringStorage stringStorage, uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
: _pool(&pool),
|
||||
_reader(reader),
|
||||
_stringStorage(stringStorage),
|
||||
_nestingLimit(nestingLimit),
|
||||
_loaded(false) {}
|
||||
DeserializationError parse(JsonVariant &variant) {
|
||||
DeserializationError err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
DeserializationError parse(VariantData &variant) {
|
||||
DeserializationError err = parseVariant(variant);
|
||||
|
||||
switch (current()) {
|
||||
case '[':
|
||||
return parseArray(variant);
|
||||
|
||||
case '{':
|
||||
return parseObject(variant);
|
||||
|
||||
default:
|
||||
return parseValue(variant);
|
||||
if (!err && _current != 0 && !variant.isEnclosed()) {
|
||||
// We don't detect trailing characters earlier, so we need to check now
|
||||
err = DeserializationError::InvalidInput;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -44,10 +43,8 @@ class JsonDeserializer {
|
||||
|
||||
char current() {
|
||||
if (!_loaded) {
|
||||
if (_reader.ended())
|
||||
_current = 0;
|
||||
else
|
||||
_current = _reader.read();
|
||||
int c = _reader.read();
|
||||
_current = static_cast<char>(c > 0 ? c : 0);
|
||||
_loaded = true;
|
||||
}
|
||||
return _current;
|
||||
@ -63,12 +60,28 @@ class JsonDeserializer {
|
||||
return true;
|
||||
}
|
||||
|
||||
DeserializationError parseArray(JsonVariant &variant) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
DeserializationError parseVariant(VariantData &variant) {
|
||||
DeserializationError err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
JsonArray array(_buffer);
|
||||
if (array.isNull()) return DeserializationError::NoMemory;
|
||||
variant = array;
|
||||
switch (current()) {
|
||||
case '[':
|
||||
return parseArray(variant.toArray());
|
||||
|
||||
case '{':
|
||||
return parseObject(variant.toObject());
|
||||
|
||||
case '\"':
|
||||
case '\'':
|
||||
return parseStringValue(variant);
|
||||
|
||||
default:
|
||||
return parseNumericValue(variant);
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseArray(CollectionData &array) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
|
||||
// Check opening braket
|
||||
if (!eat('[')) return DeserializationError::InvalidInput;
|
||||
@ -82,13 +95,15 @@ class JsonDeserializer {
|
||||
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// Allocate slot in array
|
||||
VariantData *value = array.add(_pool);
|
||||
if (!value) return DeserializationError::NoMemory;
|
||||
|
||||
// 1 - Parse value
|
||||
JsonVariant value;
|
||||
_nestingLimit--;
|
||||
err = parse(value);
|
||||
err = parseVariant(*value);
|
||||
_nestingLimit++;
|
||||
if (err) return err;
|
||||
if (!array.add(value)) return DeserializationError::NoMemory;
|
||||
|
||||
// 2 - Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
@ -100,13 +115,9 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseObject(JsonVariant &variant) {
|
||||
DeserializationError parseObject(CollectionData &object) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
|
||||
JsonObject object(_buffer);
|
||||
if (object.isNull()) return DeserializationError::NoMemory;
|
||||
variant = object;
|
||||
|
||||
// Check opening brace
|
||||
if (!eat('{')) return DeserializationError::InvalidInput;
|
||||
|
||||
@ -119,10 +130,15 @@ class JsonDeserializer {
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// Allocate slot in object
|
||||
VariantSlot *slot = object.addSlot(_pool);
|
||||
if (!slot) return DeserializationError::NoMemory;
|
||||
|
||||
// Parse key
|
||||
const char *key;
|
||||
err = parseKey(&key);
|
||||
err = parseKey(key);
|
||||
if (err) return err;
|
||||
slot->setOwnedKey(make_not_null(key));
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
@ -130,12 +146,10 @@ class JsonDeserializer {
|
||||
if (!eat(':')) return DeserializationError::InvalidInput;
|
||||
|
||||
// Parse value
|
||||
JsonVariant value;
|
||||
_nestingLimit--;
|
||||
err = parse(value);
|
||||
err = parseVariant(*slot->data());
|
||||
_nestingLimit++;
|
||||
if (err) return err;
|
||||
if (!object.set(key, value)) return DeserializationError::NoMemory;
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
@ -151,15 +165,7 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseValue(JsonVariant &variant) {
|
||||
if (isQuote(current())) {
|
||||
return parseStringValue(variant);
|
||||
} else {
|
||||
return parseNumericValue(variant);
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseKey(const char **key) {
|
||||
DeserializationError parseKey(const char *&key) {
|
||||
if (isQuote(current())) {
|
||||
return parseQuotedString(key);
|
||||
} else {
|
||||
@ -167,19 +173,17 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseStringValue(JsonVariant &variant) {
|
||||
DeserializationError parseStringValue(VariantData &variant) {
|
||||
const char *value;
|
||||
DeserializationError err = parseQuotedString(&value);
|
||||
DeserializationError err = parseQuotedString(value);
|
||||
if (err) return err;
|
||||
variant = value;
|
||||
variant.setOwnedString(make_not_null(value));
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError parseQuotedString(const char **result) {
|
||||
typename remove_reference<TStringStorage>::type::String str =
|
||||
_stringStorage.startString();
|
||||
|
||||
char stopChar = current();
|
||||
DeserializationError parseQuotedString(const char *&result) {
|
||||
StringBuilder builder = _stringStorage.startString();
|
||||
const char stopChar = current();
|
||||
|
||||
move();
|
||||
for (;;) {
|
||||
@ -192,24 +196,34 @@ class JsonDeserializer {
|
||||
if (c == '\\') {
|
||||
c = current();
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
if (c == 'u') return DeserializationError::NotSupported;
|
||||
if (c == 'u') {
|
||||
#if ARDUINOJSON_DECODE_UNICODE
|
||||
uint16_t codepoint;
|
||||
move();
|
||||
DeserializationError err = parseCodepoint(codepoint);
|
||||
if (err) return err;
|
||||
Utf8::encodeCodepoint(codepoint, builder);
|
||||
continue;
|
||||
#else
|
||||
return DeserializationError::NotSupported;
|
||||
#endif
|
||||
}
|
||||
// replace char
|
||||
c = EscapeSequence::unescapeChar(c);
|
||||
if (c == '\0') return DeserializationError::InvalidInput;
|
||||
move();
|
||||
}
|
||||
|
||||
str.append(c);
|
||||
builder.append(c);
|
||||
}
|
||||
|
||||
*result = str.c_str();
|
||||
if (*result == NULL) return DeserializationError::NoMemory;
|
||||
result = builder.complete();
|
||||
if (!result) return DeserializationError::NoMemory;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError parseNonQuotedString(const char **result) {
|
||||
typename remove_reference<TStringStorage>::type::String str =
|
||||
_stringStorage.startString();
|
||||
DeserializationError parseNonQuotedString(const char *&result) {
|
||||
StringBuilder builder = _stringStorage.startString();
|
||||
|
||||
char c = current();
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
@ -217,19 +231,19 @@ class JsonDeserializer {
|
||||
if (canBeInNonQuotedString(c)) { // no quotes
|
||||
do {
|
||||
move();
|
||||
str.append(c);
|
||||
builder.append(c);
|
||||
c = current();
|
||||
} while (canBeInNonQuotedString(c));
|
||||
} else {
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
|
||||
*result = str.c_str();
|
||||
if (*result == NULL) return DeserializationError::NoMemory;
|
||||
result = builder.complete();
|
||||
if (!result) return DeserializationError::NoMemory;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError parseNumericValue(JsonVariant &result) {
|
||||
DeserializationError parseNumericValue(VariantData &result) {
|
||||
char buffer[64];
|
||||
uint8_t n = 0;
|
||||
|
||||
@ -241,18 +255,51 @@ class JsonDeserializer {
|
||||
}
|
||||
buffer[n] = 0;
|
||||
|
||||
if (isInteger(buffer)) {
|
||||
result = parseInteger<JsonInteger>(buffer);
|
||||
} else if (isFloat(buffer)) {
|
||||
result = parseFloat<JsonFloat>(buffer);
|
||||
} else if (!strcmp(buffer, "true")) {
|
||||
result = true;
|
||||
} else if (!strcmp(buffer, "false")) {
|
||||
result = false;
|
||||
} else if (!strcmp(buffer, "null")) {
|
||||
result = static_cast<const char *>(0);
|
||||
} else {
|
||||
return DeserializationError::InvalidInput;
|
||||
c = buffer[0];
|
||||
if (c == 't') { // true
|
||||
result.setBoolean(true);
|
||||
return n == 4 ? DeserializationError::Ok
|
||||
: DeserializationError::IncompleteInput;
|
||||
}
|
||||
if (c == 'f') { // false
|
||||
result.setBoolean(false);
|
||||
return n == 5 ? DeserializationError::Ok
|
||||
: DeserializationError::IncompleteInput;
|
||||
}
|
||||
if (c == 'n') { // null
|
||||
// the variant is already null
|
||||
return n == 4 ? DeserializationError::Ok
|
||||
: DeserializationError::IncompleteInput;
|
||||
}
|
||||
|
||||
ParsedNumber<Float, UInt> num = parseNumber<Float, UInt>(buffer);
|
||||
|
||||
switch (num.type()) {
|
||||
case VALUE_IS_NEGATIVE_INTEGER:
|
||||
result.setNegativeInteger(num.uintValue);
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case VALUE_IS_POSITIVE_INTEGER:
|
||||
result.setPositiveInteger(num.uintValue);
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case VALUE_IS_FLOAT:
|
||||
result.setFloat(num.floatValue);
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
|
||||
DeserializationError parseCodepoint(uint16_t &codepoint) {
|
||||
codepoint = 0;
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
char digit = current();
|
||||
if (!digit) return DeserializationError::IncompleteInput;
|
||||
uint8_t value = decodeHex(digit);
|
||||
if (value > 0x0F) return DeserializationError::InvalidInput;
|
||||
codepoint = uint16_t((codepoint << 4) | value);
|
||||
move();
|
||||
}
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
@ -270,6 +317,12 @@ class JsonDeserializer {
|
||||
return c == '\'' || c == '\"';
|
||||
}
|
||||
|
||||
static inline uint8_t decodeHex(char c) {
|
||||
if (c < 'A') return uint8_t(c - '0');
|
||||
c = char(c & ~0x20); // uppercase
|
||||
return uint8_t(c - 'A' + 10);
|
||||
}
|
||||
|
||||
DeserializationError skipSpacesAndComments() {
|
||||
for (;;) {
|
||||
switch (current()) {
|
||||
@ -329,37 +382,39 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
MemoryPool *_pool;
|
||||
TReader _reader;
|
||||
TStringStorage _stringStorage;
|
||||
uint8_t _nestingLimit;
|
||||
char _current;
|
||||
bool _loaded;
|
||||
}; // namespace Internals
|
||||
} // namespace Internals
|
||||
};
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, const TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
template <typename TInput>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, const TInput &input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput *input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
template <typename TInput>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TInput *input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize);
|
||||
template <typename TInput>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TInput *input, size_t inputSize,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
template <typename TInput>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TInput &input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -1,142 +1,124 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Misc/Visitable.hpp"
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "./JsonWriter.hpp"
|
||||
#include "TextFormatter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TWriter>
|
||||
class JsonSerializer {
|
||||
public:
|
||||
JsonSerializer(TWriter &writer) : _writer(writer) {}
|
||||
JsonSerializer(TWriter &writer) : _formatter(writer) {}
|
||||
|
||||
void acceptFloat(JsonFloat value) {
|
||||
_writer.writeFloat(value);
|
||||
}
|
||||
FORCE_INLINE void visitArray(const CollectionData &array) {
|
||||
write('[');
|
||||
|
||||
void acceptArray(const JsonArray &array) {
|
||||
_writer.beginArray();
|
||||
VariantSlot *slot = array.head();
|
||||
|
||||
JsonArray::const_iterator it = array.begin();
|
||||
while (it != array.end()) {
|
||||
it->visit(*this);
|
||||
while (slot != 0) {
|
||||
slot->data()->accept(*this);
|
||||
|
||||
++it;
|
||||
if (it == array.end()) break;
|
||||
slot = slot->next();
|
||||
if (slot == 0) break;
|
||||
|
||||
_writer.writeComma();
|
||||
write(',');
|
||||
}
|
||||
|
||||
_writer.endArray();
|
||||
write(']');
|
||||
}
|
||||
|
||||
void acceptObject(const JsonObject &object) {
|
||||
_writer.beginObject();
|
||||
void visitObject(const CollectionData &object) {
|
||||
write('{');
|
||||
|
||||
JsonObject::const_iterator it = object.begin();
|
||||
while (it != object.end()) {
|
||||
_writer.writeString(it->key);
|
||||
_writer.writeColon();
|
||||
it->value.visit(*this);
|
||||
VariantSlot *slot = object.head();
|
||||
|
||||
++it;
|
||||
if (it == object.end()) break;
|
||||
while (slot != 0) {
|
||||
_formatter.writeString(slot->key());
|
||||
write(':');
|
||||
slot->data()->accept(*this);
|
||||
|
||||
_writer.writeComma();
|
||||
slot = slot->next();
|
||||
if (slot == 0) break;
|
||||
|
||||
write(',');
|
||||
}
|
||||
|
||||
_writer.endObject();
|
||||
write('}');
|
||||
}
|
||||
|
||||
void acceptString(const char *value) {
|
||||
_writer.writeString(value);
|
||||
void visitFloat(Float value) {
|
||||
_formatter.writeFloat(value);
|
||||
}
|
||||
|
||||
void acceptRawJson(const char *data, size_t n) {
|
||||
// TODO
|
||||
for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]);
|
||||
void visitString(const char *value) {
|
||||
_formatter.writeString(value);
|
||||
}
|
||||
|
||||
void acceptNegativeInteger(JsonUInt value) {
|
||||
_writer.writeRaw('-');
|
||||
_writer.writeInteger(value);
|
||||
void visitRawJson(const char *data, size_t n) {
|
||||
_formatter.writeRaw(data, n);
|
||||
}
|
||||
|
||||
void acceptPositiveInteger(JsonUInt value) {
|
||||
_writer.writeInteger(value);
|
||||
void visitNegativeInteger(UInt value) {
|
||||
_formatter.writeNegativeInteger(value);
|
||||
}
|
||||
|
||||
void acceptBoolean(bool value) {
|
||||
_writer.writeBoolean(value);
|
||||
void visitPositiveInteger(UInt value) {
|
||||
_formatter.writePositiveInteger(value);
|
||||
}
|
||||
|
||||
void acceptNull() {
|
||||
_writer.writeRaw("null");
|
||||
void visitBoolean(bool value) {
|
||||
_formatter.writeBoolean(value);
|
||||
}
|
||||
|
||||
void visitNull() {
|
||||
_formatter.writeRaw("null");
|
||||
}
|
||||
|
||||
size_t bytesWritten() const {
|
||||
return _writer.bytesWritten();
|
||||
return _formatter.bytesWritten();
|
||||
}
|
||||
|
||||
protected:
|
||||
void write(char c) {
|
||||
_formatter.writeRaw(c);
|
||||
}
|
||||
|
||||
void write(const char *s) {
|
||||
_formatter.writeRaw(s);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonWriter<TWriter> _writer;
|
||||
TextFormatter<TWriter> _formatter;
|
||||
};
|
||||
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
size_t serializeJson(TSource &source, TDestination &destination) {
|
||||
using namespace Internals;
|
||||
size_t serializeJson(const TSource &source, TDestination &destination) {
|
||||
return serialize<JsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJson(const TSource &source, char *buffer, size_t bufferSize) {
|
||||
using namespace Internals;
|
||||
return serialize<JsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJson(const TSource &source) {
|
||||
using namespace Internals;
|
||||
return measure<JsonSerializer>(source);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonArray &source) {
|
||||
template <typename T>
|
||||
inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type
|
||||
operator<<(std::ostream &os, const T &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonObject &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
|
||||
namespace Internals {
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
const JsonArraySubscript &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
const JsonObjectSubscript<TKey> &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
} // namespace Internals
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -1,57 +1,83 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "./IndentedPrint.hpp"
|
||||
#include "./JsonSerializer.hpp"
|
||||
#include "./Prettyfier.hpp"
|
||||
#include "JsonSerializer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TWriter>
|
||||
class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
||||
typedef JsonSerializer<TWriter> base;
|
||||
|
||||
template <typename TPrint>
|
||||
class PrettyJsonSerializer_Base {
|
||||
public:
|
||||
PrettyJsonSerializer_Base(TPrint &output)
|
||||
: _indentedPrint(output), _prettyfier(_indentedPrint) {}
|
||||
PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
|
||||
|
||||
protected:
|
||||
IndentedPrint<TPrint> _indentedPrint;
|
||||
Prettyfier<TPrint> _prettyfier;
|
||||
};
|
||||
void visitArray(const CollectionData &array) {
|
||||
VariantSlot *slot = array.head();
|
||||
if (!slot) return base::write("[]");
|
||||
|
||||
template <typename TPrint>
|
||||
class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>,
|
||||
public JsonSerializer<Prettyfier<TPrint> > {
|
||||
public:
|
||||
PrettyJsonSerializer(TPrint &output)
|
||||
: PrettyJsonSerializer_Base<TPrint>(output),
|
||||
JsonSerializer<Prettyfier<TPrint> >(
|
||||
PrettyJsonSerializer_Base<TPrint>::_prettyfier) {}
|
||||
base::write("[\r\n");
|
||||
_nesting++;
|
||||
while (slot != 0) {
|
||||
indent();
|
||||
slot->data()->accept(*this);
|
||||
|
||||
slot = slot->next();
|
||||
base::write(slot ? ",\r\n" : "\r\n");
|
||||
}
|
||||
_nesting--;
|
||||
indent();
|
||||
base::write("]");
|
||||
}
|
||||
|
||||
void visitObject(const CollectionData &object) {
|
||||
VariantSlot *slot = object.head();
|
||||
if (!slot) return base::write("{}");
|
||||
|
||||
base::write("{\r\n");
|
||||
_nesting++;
|
||||
while (slot != 0) {
|
||||
indent();
|
||||
base::visitString(slot->key());
|
||||
base::write(": ");
|
||||
slot->data()->accept(*this);
|
||||
|
||||
slot = slot->next();
|
||||
base::write(slot ? ",\r\n" : "\r\n");
|
||||
}
|
||||
_nesting--;
|
||||
indent();
|
||||
base::write("}");
|
||||
}
|
||||
|
||||
private:
|
||||
void indent() {
|
||||
for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB);
|
||||
}
|
||||
|
||||
uint8_t _nesting;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
size_t serializeJsonPretty(TSource &source, TDestination &destination) {
|
||||
using namespace Internals;
|
||||
size_t serializeJsonPretty(const TSource &source, TDestination &destination) {
|
||||
return serialize<PrettyJsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJsonPretty(const TSource &source, char *buffer,
|
||||
size_t bufferSize) {
|
||||
using namespace Internals;
|
||||
return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJsonPretty(const TSource &source) {
|
||||
using namespace Internals;
|
||||
return measure<PrettyJsonSerializer>(source);
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -1,145 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IndentedPrint.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Converts a compact JSON string into an indented one.
|
||||
template <typename TWriter>
|
||||
class Prettyfier {
|
||||
public:
|
||||
explicit Prettyfier(IndentedPrint<TWriter>& p) : _sink(p) {
|
||||
_previousChar = 0;
|
||||
_inString = false;
|
||||
}
|
||||
|
||||
size_t write(uint8_t c) {
|
||||
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(char(c));
|
||||
_previousChar = char(c);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t write(const uint8_t* s, size_t n) {
|
||||
// TODO: optimize
|
||||
size_t bytesWritten = 0;
|
||||
while (n > 0) {
|
||||
bytesWritten += write(*s++);
|
||||
n--;
|
||||
}
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
private:
|
||||
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
|
||||
|
||||
bool inEmptyBlock() {
|
||||
return _previousChar == '{' || _previousChar == '[';
|
||||
}
|
||||
|
||||
size_t handleStringChar(uint8_t c) {
|
||||
bool isQuote = c == '"' && _previousChar != '\\';
|
||||
|
||||
if (isQuote) _inString = false;
|
||||
|
||||
return _sink.write(c);
|
||||
}
|
||||
|
||||
size_t handleMarkupChar(char c) {
|
||||
switch (c) {
|
||||
case '{':
|
||||
case '[':
|
||||
return writeBlockOpen(c);
|
||||
|
||||
case '}':
|
||||
case ']':
|
||||
return writeBlockClose(c);
|
||||
|
||||
case ':':
|
||||
return writeColon();
|
||||
|
||||
case ',':
|
||||
return writeComma();
|
||||
|
||||
case '"':
|
||||
return writeQuoteOpen();
|
||||
|
||||
default:
|
||||
return writeNormalChar(c);
|
||||
}
|
||||
}
|
||||
|
||||
size_t writeBlockClose(char c) {
|
||||
size_t n = 0;
|
||||
n += unindentIfNeeded();
|
||||
n += write(c);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeBlockOpen(char c) {
|
||||
size_t n = 0;
|
||||
n += indentIfNeeded();
|
||||
n += write(c);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeColon() {
|
||||
size_t n = 0;
|
||||
n += write(": ");
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeComma() {
|
||||
size_t n = 0;
|
||||
n += write(",\r\n");
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeQuoteOpen() {
|
||||
_inString = true;
|
||||
size_t n = 0;
|
||||
n += indentIfNeeded();
|
||||
n += write('"');
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t writeNormalChar(char c) {
|
||||
size_t n = 0;
|
||||
n += indentIfNeeded();
|
||||
n += write(c);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t indentIfNeeded() {
|
||||
if (!inEmptyBlock()) return 0;
|
||||
|
||||
_sink.indent();
|
||||
return write("\r\n");
|
||||
}
|
||||
|
||||
size_t unindentIfNeeded() {
|
||||
if (inEmptyBlock()) return 0;
|
||||
|
||||
_sink.unindent();
|
||||
return write("\r\n");
|
||||
}
|
||||
|
||||
size_t write(char c) {
|
||||
return _sink.write(static_cast<uint8_t>(c));
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
size_t write(const char (&s)[N]) {
|
||||
return _sink.write(reinterpret_cast<const uint8_t*>(s), N - 1);
|
||||
}
|
||||
|
||||
char _previousChar;
|
||||
IndentedPrint<TWriter>& _sink;
|
||||
bool _inString;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,50 +1,28 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h> // for strlen
|
||||
#include "../Data/JsonInteger.hpp"
|
||||
#include "../Numbers/FloatParts.hpp"
|
||||
#include "../Numbers/Integer.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
#include "./EscapeSequence.hpp"
|
||||
#include "EscapeSequence.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TWriter>
|
||||
class JsonWriter {
|
||||
class TextFormatter {
|
||||
public:
|
||||
explicit JsonWriter(TWriter &writer) : _writer(writer), _length(0) {}
|
||||
explicit TextFormatter(TWriter &writer) : _writer(writer), _length(0) {}
|
||||
|
||||
// Returns the number of bytes sent to the TWriter implementation.
|
||||
size_t bytesWritten() const {
|
||||
return _length;
|
||||
}
|
||||
|
||||
void beginArray() {
|
||||
writeRaw('[');
|
||||
}
|
||||
void endArray() {
|
||||
writeRaw(']');
|
||||
}
|
||||
|
||||
void beginObject() {
|
||||
writeRaw('{');
|
||||
}
|
||||
void endObject() {
|
||||
writeRaw('}');
|
||||
}
|
||||
|
||||
void writeColon() {
|
||||
writeRaw(':');
|
||||
}
|
||||
void writeComma() {
|
||||
writeRaw(',');
|
||||
}
|
||||
|
||||
void writeBoolean(bool value) {
|
||||
if (value)
|
||||
writeRaw("true");
|
||||
@ -72,35 +50,49 @@ class JsonWriter {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TFloat>
|
||||
void writeFloat(TFloat value) {
|
||||
if (isnan(value)) return writeRaw("NaN");
|
||||
template <typename T>
|
||||
void writeFloat(T value) {
|
||||
if (isnan(value)) return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
|
||||
|
||||
#if ARDUINOJSON_ENABLE_INFINITY
|
||||
if (value < 0.0) {
|
||||
writeRaw('-');
|
||||
value = -value;
|
||||
}
|
||||
|
||||
if (isinf(value)) return writeRaw("Infinity");
|
||||
#else
|
||||
if (isinf(value)) return writeRaw("null");
|
||||
|
||||
FloatParts<TFloat> parts(value);
|
||||
if (value < 0.0) {
|
||||
writeRaw('-');
|
||||
value = -value;
|
||||
}
|
||||
#endif
|
||||
|
||||
writeInteger(parts.integral);
|
||||
FloatParts<T> parts(value);
|
||||
|
||||
writePositiveInteger(parts.integral);
|
||||
if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces);
|
||||
|
||||
if (parts.exponent < 0) {
|
||||
writeRaw("e-");
|
||||
writeInteger(-parts.exponent);
|
||||
writePositiveInteger(-parts.exponent);
|
||||
}
|
||||
|
||||
if (parts.exponent > 0) {
|
||||
writeRaw('e');
|
||||
writeInteger(parts.exponent);
|
||||
writePositiveInteger(parts.exponent);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename UInt>
|
||||
void writeInteger(UInt value) {
|
||||
void writeNegativeInteger(UInt value) {
|
||||
writeRaw('-');
|
||||
writePositiveInteger(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void writePositiveInteger(T value) {
|
||||
char buffer[22];
|
||||
char *end = buffer + sizeof(buffer);
|
||||
char *begin = end;
|
||||
@ -108,7 +100,7 @@ class JsonWriter {
|
||||
// write the string in reverse order
|
||||
do {
|
||||
*--begin = char(value % 10 + '0');
|
||||
value = UInt(value / 10);
|
||||
value = T(value / 10);
|
||||
} while (value);
|
||||
|
||||
// and dump it in the right order
|
||||
@ -135,10 +127,16 @@ class JsonWriter {
|
||||
void writeRaw(const char *s) {
|
||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
|
||||
}
|
||||
|
||||
void writeRaw(const char *s, size_t n) {
|
||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), n);
|
||||
}
|
||||
|
||||
void writeRaw(const char *begin, const char *end) {
|
||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(begin),
|
||||
static_cast<size_t>(end - begin));
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
void writeRaw(const char (&s)[N]) {
|
||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
|
||||
@ -152,7 +150,6 @@ class JsonWriter {
|
||||
size_t _length;
|
||||
|
||||
private:
|
||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||
TextFormatter &operator=(const TextFormatter &); // cannot be assigned
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
26
src/ArduinoJson/Json/Utf8.hpp
Normal file
26
src/ArduinoJson/Json/Utf8.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
namespace Utf8 {
|
||||
template <typename TStringBuilder>
|
||||
inline void encodeCodepoint(uint16_t codepoint, TStringBuilder &str) {
|
||||
if (codepoint < 0x80) {
|
||||
str.append(char(codepoint));
|
||||
return;
|
||||
}
|
||||
|
||||
if (codepoint >= 0x00000800) {
|
||||
str.append(char(0xe0 /*0b11100000*/ | (codepoint >> 12)));
|
||||
str.append(char(((codepoint >> 6) & 0x3f /*0b00111111*/) | 0x80));
|
||||
} else {
|
||||
str.append(char(0xc0 /*0b11000000*/ | (codepoint >> 6)));
|
||||
}
|
||||
str.append(char((codepoint & 0x3f /*0b00111111*/) | 0x80));
|
||||
}
|
||||
} // namespace Utf8
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,208 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./JsonArrayData.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
class JsonArraySubscript;
|
||||
}
|
||||
|
||||
class JsonArray {
|
||||
friend class JsonVariant;
|
||||
|
||||
public:
|
||||
typedef Internals::JsonArrayData::iterator iterator;
|
||||
typedef Internals::JsonArrayData::const_iterator const_iterator;
|
||||
|
||||
JsonArray() : _data(0) {}
|
||||
JsonArray(Internals::JsonArrayData* arr) : _data(arr) {}
|
||||
JsonArray(Internals::JsonBuffer* buf)
|
||||
: _data(new (buf) Internals::JsonArrayData(buf)) {}
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArrayData, JsonObject
|
||||
template <typename T>
|
||||
bool add(const T& value) {
|
||||
return add_impl<const T&>(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool add(T* value) {
|
||||
return add_impl<T*>(value);
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
if (!_data) return iterator();
|
||||
return _data->begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
if (!_data) return const_iterator();
|
||||
return _data->begin();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T, size_t N>
|
||||
bool copyFrom(T (&array)[N]) {
|
||||
return copyFrom(array, N);
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T>
|
||||
bool copyFrom(T* array, size_t len) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ok &= add(array[i]);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Imports a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
bool copyFrom(T (&array)[N1][N2]) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < N1; i++) {
|
||||
JsonArray nestedArray = createNestedArray();
|
||||
for (size_t j = 0; j < N2; j++) {
|
||||
ok &= nestedArray.add(array[i][j]);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T, size_t N>
|
||||
size_t copyTo(T (&array)[N]) const {
|
||||
return copyTo(array, N);
|
||||
}
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T>
|
||||
size_t copyTo(T* array, size_t len) const {
|
||||
size_t i = 0;
|
||||
for (const_iterator it = begin(); it != end() && i < len; ++it)
|
||||
array[i++] = *it;
|
||||
return i;
|
||||
}
|
||||
|
||||
// Exports a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
void copyTo(T (&array)[N1][N2]) const {
|
||||
if (!_data) return;
|
||||
size_t i = 0;
|
||||
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
|
||||
it->as<JsonArray>().copyTo(array[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
JsonArray createNestedArray();
|
||||
JsonObject createNestedObject();
|
||||
|
||||
Internals::JsonArraySubscript operator[](size_t index);
|
||||
|
||||
const Internals::JsonArraySubscript operator[](size_t index) const;
|
||||
|
||||
bool operator==(const JsonArray& rhs) const {
|
||||
return _data == rhs._data;
|
||||
}
|
||||
|
||||
// Gets the value at the specified index.
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
|
||||
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 {
|
||||
const_iterator it = begin() += index;
|
||||
return it != end() ? it->is<T>() : false;
|
||||
}
|
||||
|
||||
// Removes element at specified position.
|
||||
void remove(iterator it) {
|
||||
if (!_data) return;
|
||||
_data->remove(it);
|
||||
}
|
||||
|
||||
// Removes element at specified index.
|
||||
void remove(size_t index) {
|
||||
remove(begin() += index);
|
||||
}
|
||||
|
||||
// Sets the value at specified index.
|
||||
//
|
||||
// bool add(size_t index, const TValue&);
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArrayData, JsonObject
|
||||
template <typename T>
|
||||
bool set(size_t index, const T& value) {
|
||||
if (!_data) return false;
|
||||
return set_impl<const T&>(index, value);
|
||||
}
|
||||
//
|
||||
// bool add(size_t index, TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool set(size_t index, T* value) {
|
||||
if (!_data) return false;
|
||||
return set_impl<T*>(index, value);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
if (!_data) return 0;
|
||||
return _data->size();
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor& visitor) const {
|
||||
if (_data)
|
||||
return visitor.acceptArray(*this);
|
||||
else
|
||||
visitor.acceptNull();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TValueRef>
|
||||
bool set_impl(size_t index, TValueRef value) {
|
||||
iterator it = begin() += index;
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, *it, value);
|
||||
}
|
||||
|
||||
template <typename TValueRef>
|
||||
bool add_impl(TValueRef value) {
|
||||
if (!_data) return false;
|
||||
iterator it = _data->add();
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, *it, value);
|
||||
}
|
||||
|
||||
Internals::JsonArrayData* _data;
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,26 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/List.hpp"
|
||||
#include "Data/ValueSaver.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Memory/JsonBufferAllocated.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(ArduinoJson::Internals::JsonArrayData) + \
|
||||
(NUMBER_OF_ELEMENTS) * \
|
||||
sizeof(ArduinoJson::Internals::JsonArrayData::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
struct JsonArrayData : List<JsonVariant>, JsonBufferAllocated {
|
||||
explicit JsonArrayData(JsonBuffer *buf) throw() : List<JsonVariant>(buf) {}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,25 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonArray JsonArray::createNestedArray() {
|
||||
if (!_data) return JsonArray();
|
||||
JsonArray array(_data->_buffer);
|
||||
if (!array.isNull()) add(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
inline JsonObject JsonArray::createNestedObject() {
|
||||
if (!_data) return JsonObject();
|
||||
JsonObject object(_data->_buffer);
|
||||
if (!object.isNull()) add(object);
|
||||
return object;
|
||||
}
|
||||
} // namespace ArduinoJson
|
@ -1,112 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
public:
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// operator=(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue)
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(T* src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _index >= _array.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename JsonVariantAs<T>::type as() const {
|
||||
return _array.get<T>(_index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is() const {
|
||||
return _array.is<T>(_index);
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// bool set(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue& value) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue)
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue* value) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor& visitor) const {
|
||||
return _array.get<JsonVariant>(_index).visit(visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonArray _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
inline const JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) const {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
} // namespace Internals
|
||||
|
||||
inline Internals::JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||
return Internals::JsonArraySubscript(*this, index);
|
||||
}
|
||||
|
||||
inline const Internals::JsonArraySubscript JsonArray::operator[](
|
||||
size_t index) const {
|
||||
return Internals::JsonArraySubscript(*this, index);
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
@ -1,311 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./JsonObjectData.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class JsonObject {
|
||||
friend class JsonVariant;
|
||||
|
||||
public:
|
||||
typedef Internals::JsonObjectData::iterator iterator;
|
||||
typedef Internals::JsonObjectData::const_iterator const_iterator;
|
||||
|
||||
JsonObject() : _data(0) {}
|
||||
JsonObject(Internals::JsonObjectData* object) : _data(object) {}
|
||||
JsonObject(Internals::JsonBuffer* buf)
|
||||
: _data(new (buf) Internals::JsonObjectData(buf)) {}
|
||||
|
||||
iterator begin() {
|
||||
if (!_data) return iterator();
|
||||
return _data->begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
if (!_data) return const_iterator();
|
||||
return _data->begin();
|
||||
}
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
bool containsKey(const TString& key) const {
|
||||
return containsKey_impl<const TString&>(key);
|
||||
}
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
bool containsKey(TString* key) const {
|
||||
return containsKey_impl<TString*>(key);
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
//
|
||||
// JsonArray createNestedArray(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
JsonArray createNestedArray(const TString& key);
|
||||
// JsonArray createNestedArray(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonArray createNestedArray(TString* key);
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
//
|
||||
// JsonObject createNestedObject(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
JsonObject createNestedObject(const TString& key) {
|
||||
if (!_data) return JsonObject();
|
||||
return createNestedObject_impl<const TString&>(key);
|
||||
}
|
||||
//
|
||||
// JsonObject createNestedObject(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonObject createNestedObject(TString* key) {
|
||||
return createNestedObject_impl<TString*>(key);
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
typename Internals::JsonVariantAs<TValue>::type get(
|
||||
const TString& key) const {
|
||||
return get_impl<const TString&, TValue>(key);
|
||||
}
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
typename Internals::JsonVariantAs<TValue>::type get(TString* key) const {
|
||||
return get_impl<TString*, TValue>(key);
|
||||
}
|
||||
|
||||
// Checks the type of the value associated with the specified key.
|
||||
//
|
||||
//
|
||||
// bool is<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool is(const TString& key) const {
|
||||
return is_impl<const TString&, TValue>(key);
|
||||
}
|
||||
//
|
||||
// bool is<TValue>(TKey) const;
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool is(TString* key) const {
|
||||
return is_impl<TString*, TValue>(key);
|
||||
}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
Internals::JsonObjectSubscript<const TString&> operator[](
|
||||
const TString& key) {
|
||||
return Internals::JsonObjectSubscript<const TString&>(*this, key);
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
Internals::JsonObjectSubscript<TString*> operator[](TString* key) {
|
||||
return Internals::JsonObjectSubscript<TString*>(*this, key);
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
const Internals::JsonObjectSubscript<const TString&> operator[](
|
||||
const TString& key) const {
|
||||
return Internals::JsonObjectSubscript<const TString&>(*this, key);
|
||||
}
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
const Internals::JsonObjectSubscript<TString*> operator[](
|
||||
TString* key) const {
|
||||
return Internals::JsonObjectSubscript<TString*>(*this, key);
|
||||
}
|
||||
|
||||
bool operator==(const JsonObject& rhs) const {
|
||||
return _data == rhs._data;
|
||||
}
|
||||
|
||||
void remove(iterator it) {
|
||||
if (!_data) return;
|
||||
_data->remove(it);
|
||||
}
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
void remove(const TString& key) {
|
||||
remove_impl<const TString&>(key);
|
||||
}
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
void remove(TString* key) {
|
||||
remove_impl<TString*>(key);
|
||||
}
|
||||
|
||||
// Sets the specified key with the specified value.
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool set(const TString& key, const TValue& value) {
|
||||
return set_impl<const TString&, const TValue&>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue, typename TString>
|
||||
bool set(const TString& key, TValue* value) {
|
||||
return set_impl<const TString&, TValue*>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, const TValue&);
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool set(TString* key, const TValue& value) {
|
||||
return set_impl<TString*, const TValue&>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue, typename TString>
|
||||
bool set(TString* key, TValue* value) {
|
||||
return set_impl<TString*, TValue*>(key, value);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
if (!_data) return 0;
|
||||
return _data->size();
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor& visitor) const {
|
||||
if (_data)
|
||||
visitor.acceptObject(*this);
|
||||
else
|
||||
return visitor.acceptNull();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TStringRef>
|
||||
bool containsKey_impl(TStringRef key) const {
|
||||
return findKey<TStringRef>(key) != end();
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
JsonArray createNestedArray_impl(TStringRef key);
|
||||
|
||||
template <typename TStringRef>
|
||||
JsonObject createNestedObject_impl(TStringRef key);
|
||||
|
||||
// Returns the list node that matches the specified key.
|
||||
template <typename TStringRef>
|
||||
iterator findKey(TStringRef key) {
|
||||
iterator it;
|
||||
for (it = begin(); it != end(); ++it) {
|
||||
if (Internals::makeString(key).equals(it->key)) break;
|
||||
}
|
||||
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 {
|
||||
const_iterator it = findKey<TStringRef>(key);
|
||||
return it != end() ? it->value.as<TValue>()
|
||||
: Internals::JsonVariantDefault<TValue>::get();
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValue>
|
||||
bool is_impl(TStringRef key) const {
|
||||
const_iterator it = findKey<TStringRef>(key);
|
||||
return it != end() ? it->value.is<TValue>() : false;
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
void remove_impl(TStringRef key) {
|
||||
if (!_data) return;
|
||||
_data->remove(findKey<TStringRef>(key));
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValueRef>
|
||||
bool set_impl(TStringRef key, TValueRef value) {
|
||||
if (!_data) return false;
|
||||
|
||||
// ignore null key
|
||||
if (Internals::makeString(key).is_null()) return false;
|
||||
|
||||
// search a matching key
|
||||
iterator it = findKey<TStringRef>(key);
|
||||
if (it == end()) {
|
||||
// add the key
|
||||
it = _data->add();
|
||||
if (it == end()) return false;
|
||||
bool key_ok =
|
||||
Internals::ValueSaver<TStringRef>::save(_data->_buffer, it->key, key);
|
||||
if (!key_ok) return false;
|
||||
}
|
||||
|
||||
// save the value
|
||||
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, it->value,
|
||||
value);
|
||||
}
|
||||
|
||||
Internals::JsonObjectData* _data;
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,26 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/List.hpp"
|
||||
#include "Data/ValueSaver.hpp"
|
||||
#include "JsonPair.hpp"
|
||||
#include "Memory/JsonBufferAllocated.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(ArduinoJson::Internals::JsonObjectData) + \
|
||||
(NUMBER_OF_ELEMENTS) * \
|
||||
sizeof(ArduinoJson::Internals::JsonObjectData::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
struct JsonObjectData : List<JsonPair>, JsonBufferAllocated {
|
||||
explicit JsonObjectData(JsonBuffer* buf) throw() : List<JsonPair>(buf) {}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,37 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TString>
|
||||
inline JsonArray JsonObject::createNestedArray(const TString& key) {
|
||||
return createNestedArray_impl<const TString&>(key);
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
inline JsonArray JsonObject::createNestedArray(TString* key) {
|
||||
return createNestedArray_impl<TString*>(key);
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
inline JsonArray JsonObject::createNestedArray_impl(TStringRef key) {
|
||||
if (!_data) return JsonArray();
|
||||
JsonArray array(_data->_buffer);
|
||||
if (!array.isNull()) set(key, array);
|
||||
return array;
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
inline JsonObject JsonObject::createNestedObject_impl(TStringRef key) {
|
||||
if (!_data) return JsonObject();
|
||||
JsonObject object(_data->_buffer);
|
||||
if (!object.isNull()) set(key, object);
|
||||
return object;
|
||||
}
|
||||
} // namespace ArduinoJson
|
@ -1,133 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TStringRef>
|
||||
class JsonObjectSubscript
|
||||
: public JsonVariantBase<JsonObjectSubscript<TStringRef> > {
|
||||
typedef JsonObjectSubscript<TStringRef> this_type;
|
||||
|
||||
public:
|
||||
FORCE_INLINE JsonObjectSubscript(JsonObject object, TStringRef key)
|
||||
: _object(object), _key(key) {}
|
||||
|
||||
FORCE_INLINE this_type &operator=(const this_type &src) {
|
||||
_object.set(_key, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Set the specified value
|
||||
//
|
||||
// operator=(const TValue&);
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
|
||||
operator=(const TValue &src) {
|
||||
_object.set(_key, src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE this_type &operator=(TValue *src) {
|
||||
_object.set(_key, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return !_object.containsKey(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename JsonVariantAs<TValue>::type as() const {
|
||||
return _object.get<TValue>(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool is() const {
|
||||
return _object.is<TValue>(_key);
|
||||
}
|
||||
|
||||
// Sets the specified value.
|
||||
//
|
||||
// bool set(const TValue&);
|
||||
// TValue = bool, char, long, int, short, float, double, serialized,
|
||||
// JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
|
||||
const TValue &value) {
|
||||
return _object.set(_key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue);
|
||||
// TValue = char*, const char, const FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue *value) {
|
||||
return _object.set(_key, value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor &visitor) const {
|
||||
return _object.get<JsonVariant>(_key).visit(visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonObject _object;
|
||||
TStringRef _key;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString>::value,
|
||||
const JsonObjectSubscript<const TString &> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](const TString &key) const {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString>::value,
|
||||
JsonObjectSubscript<const TString &> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](const TString &key) {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<const TString *>::value,
|
||||
JsonObjectSubscript<const TString *> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](const TString *key) {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString *>::value,
|
||||
const JsonObjectSubscript<const TString *> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](const TString *key) const {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// A key value pair for JsonObjectData.
|
||||
struct JsonPair {
|
||||
const char* key;
|
||||
JsonVariant value;
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,324 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h> // for uint8_t
|
||||
|
||||
#include "Data/JsonVariantContent.hpp"
|
||||
#include "Data/JsonVariantDefault.hpp"
|
||||
#include "Data/JsonVariantType.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "Serialization/DynamicStringWriter.hpp"
|
||||
#include "SerializedValue.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
// A variant that can be a any value serializable to a JSON value.
|
||||
//
|
||||
// It can be set to:
|
||||
// - a boolean
|
||||
// - a char, short, int or a long (signed or unsigned)
|
||||
// - a string (const char*)
|
||||
// - a reference to a JsonArray or JsonObject
|
||||
class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
|
||||
public:
|
||||
// Creates an uninitialized JsonVariant
|
||||
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||
|
||||
// Create a JsonVariant containing a boolean value.
|
||||
// It will be serialized as "true" or "false" in JSON.
|
||||
JsonVariant(bool value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_BOOLEAN;
|
||||
_content.asInteger = static_cast<JsonUInt>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing a floating point value.
|
||||
// JsonVariant(double value);
|
||||
// JsonVariant(float value);
|
||||
template <typename T>
|
||||
JsonVariant(T value,
|
||||
typename Internals::enable_if<
|
||||
Internals::is_floating_point<T>::value>::type * = 0) {
|
||||
using namespace Internals;
|
||||
_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 Internals::enable_if<Internals::is_integral<T>::value &&
|
||||
Internals::is_signed<T>::value>::type * =
|
||||
0) {
|
||||
using namespace Internals;
|
||||
if (value >= 0) {
|
||||
_type = JSON_POSITIVE_INTEGER;
|
||||
_content.asInteger = static_cast<JsonUInt>(value);
|
||||
} else {
|
||||
_type = JSON_NEGATIVE_INTEGER;
|
||||
_content.asInteger = ~static_cast<JsonUInt>(value) + 1;
|
||||
}
|
||||
}
|
||||
// JsonVariant(unsigned short)
|
||||
// JsonVariant(unsigned int)
|
||||
// JsonVariant(unsigned long)
|
||||
template <typename T>
|
||||
JsonVariant(
|
||||
T value,
|
||||
typename Internals::enable_if<Internals::is_integral<T>::value &&
|
||||
Internals::is_unsigned<T>::value>::type * =
|
||||
0) {
|
||||
using namespace Internals;
|
||||
_type = JSON_POSITIVE_INTEGER;
|
||||
_content.asInteger = static_cast<JsonUInt>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing a string.
|
||||
// JsonVariant(const char*);
|
||||
// JsonVariant(const signed char*);
|
||||
// JsonVariant(const unsigned char*);
|
||||
template <typename TChar>
|
||||
JsonVariant(const TChar *value,
|
||||
typename Internals::enable_if<sizeof(TChar) == 1>::type * = 0) {
|
||||
_type = Internals::JSON_STRING;
|
||||
_content.asString = reinterpret_cast<const char *>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing an unparsed string
|
||||
JsonVariant(Internals::SerializedValue<const char *> value) {
|
||||
_type = Internals::JSON_UNPARSED;
|
||||
_content.asRaw.data = value.data();
|
||||
_content.asRaw.size = value.size();
|
||||
}
|
||||
|
||||
JsonVariant(JsonArray array);
|
||||
JsonVariant(JsonObject object);
|
||||
|
||||
// Get the variant as the specified type.
|
||||
//
|
||||
// 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 Internals::enable_if<Internals::is_integral<T>::value, T>::type
|
||||
as() const {
|
||||
return variantAsInteger<T>();
|
||||
}
|
||||
// bool as<bool>() const
|
||||
template <typename T>
|
||||
const typename Internals::enable_if<Internals::is_same<T, bool>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return variantAsInteger<int>() != 0;
|
||||
}
|
||||
//
|
||||
// double as<double>() const;
|
||||
// float as<float>() const;
|
||||
template <typename T>
|
||||
const typename Internals::enable_if<Internals::is_floating_point<T>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return variantAsFloat<T>();
|
||||
}
|
||||
//
|
||||
// const char* as<const char*>() const;
|
||||
// const char* as<char*>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, const char *>::value ||
|
||||
Internals::is_same<T, char *>::value,
|
||||
const char *>::type
|
||||
as() const {
|
||||
return variantAsString();
|
||||
}
|
||||
//
|
||||
// std::string as<std::string>() const;
|
||||
// String as<String>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::IsWriteableString<T>::value, T>::type
|
||||
as() const {
|
||||
const char *cstr = variantAsString();
|
||||
if (cstr) return T(cstr);
|
||||
T s;
|
||||
serializeJson(*this, s);
|
||||
return s;
|
||||
}
|
||||
//
|
||||
// JsonArray as<JsonArray>() const;
|
||||
// const JsonArray as<const JsonArray>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonArray>::value,
|
||||
JsonArray>::type
|
||||
as() const;
|
||||
//
|
||||
// JsonObject as<JsonObject>() const;
|
||||
// const JsonObject as<const JsonObject>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonObject>::value,
|
||||
T>::type
|
||||
as() const;
|
||||
//
|
||||
// JsonVariant as<JsonVariant> const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Tells weither the variant has the specified type.
|
||||
// Returns true if the variant has type type T, false otherwise.
|
||||
//
|
||||
// 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>
|
||||
typename Internals::enable_if<Internals::is_integral<T>::value, bool>::type
|
||||
is() const {
|
||||
return variantIsInteger();
|
||||
}
|
||||
//
|
||||
// bool is<double>() const;
|
||||
// bool is<float>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_floating_point<T>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return variantIsFloat();
|
||||
}
|
||||
//
|
||||
// bool is<bool>() const
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, bool>::value, bool>::type
|
||||
is() const {
|
||||
return variantIsBoolean();
|
||||
}
|
||||
//
|
||||
// bool is<const char*>() const;
|
||||
// bool is<char*>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, const char *>::value ||
|
||||
Internals::is_same<T, char *>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return variantIsString();
|
||||
}
|
||||
//
|
||||
// bool is<JsonArray> const;
|
||||
// bool is<const JsonArray> const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonArray>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return variantIsArray();
|
||||
}
|
||||
//
|
||||
// bool is<JsonObject> const;
|
||||
// bool is<const JsonObject> const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonObject>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return variantIsObject();
|
||||
}
|
||||
|
||||
// Returns true if the variant has a value
|
||||
bool isNull() const {
|
||||
return _type == Internals::JSON_UNDEFINED;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor &visitor) const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_FLOAT:
|
||||
return visitor.acceptFloat(_content.asFloat);
|
||||
|
||||
case JSON_ARRAY:
|
||||
return visitor.acceptArray(_content.asArray);
|
||||
|
||||
case JSON_OBJECT:
|
||||
return visitor.acceptObject(_content.asObject);
|
||||
|
||||
case JSON_STRING:
|
||||
return visitor.acceptString(_content.asString);
|
||||
|
||||
case JSON_UNPARSED:
|
||||
return visitor.acceptRawJson(_content.asRaw.data, _content.asRaw.size);
|
||||
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return visitor.acceptNegativeInteger(_content.asInteger);
|
||||
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
return visitor.acceptPositiveInteger(_content.asInteger);
|
||||
|
||||
case JSON_BOOLEAN:
|
||||
return visitor.acceptBoolean(_content.asInteger != 0);
|
||||
|
||||
default: // JSON_UNDEFINED
|
||||
return visitor.acceptNull();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
JsonArray variantAsArray() const;
|
||||
JsonObject variantAsObject() const;
|
||||
const char *variantAsString() const;
|
||||
template <typename T>
|
||||
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 variantIsObject() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
bool variantIsString() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
}
|
||||
|
||||
// The current type of the variant
|
||||
Internals::JsonVariantType _type;
|
||||
|
||||
// The various alternatives for the value of the variant.
|
||||
Internals::JsonVariantContent _content;
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,22 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantCasts.hpp"
|
||||
#include "JsonVariantComparisons.hpp"
|
||||
#include "JsonVariantOr.hpp"
|
||||
#include "JsonVariantSubscripts.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantBase : public JsonVariantCasts<TImpl>,
|
||||
public JsonVariantComparisons<TImpl>,
|
||||
public JsonVariantOr<TImpl>,
|
||||
public JsonVariantSubscripts<TImpl>,
|
||||
public JsonVariantTag {};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,139 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/IsVariant.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "Strings/StringTypes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
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 enable_if<!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 enable_if<!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 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 enable_if<IsString<TString>::value, bool>::type equals(
|
||||
const TString &comparand) const {
|
||||
return makeString(comparand).equals(as<const char *>());
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
typename enable_if<
|
||||
!IsVariant<TComparand>::value && !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 makeString(as<char *>()).equals(right.template as<char *>());
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,127 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonArrayData.hpp"
|
||||
#include "JsonObjectData.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Numbers/isFloat.hpp"
|
||||
#include "Numbers/isInteger.hpp"
|
||||
#include "Numbers/parseFloat.hpp"
|
||||
#include "Numbers/parseInteger.hpp"
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonVariant::JsonVariant(JsonArray array) {
|
||||
if (!array.isNull()) {
|
||||
_type = Internals::JSON_ARRAY;
|
||||
_content.asArray = array._data;
|
||||
} else {
|
||||
_type = Internals::JSON_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(JsonObject object) {
|
||||
if (!object.isNull()) {
|
||||
_type = Internals::JSON_OBJECT;
|
||||
_content.asObject = object._data;
|
||||
} else {
|
||||
_type = Internals::JSON_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonArray>::value,
|
||||
JsonArray>::type
|
||||
JsonVariant::as() const {
|
||||
return variantAsArray();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonObject>::value,
|
||||
T>::type
|
||||
JsonVariant::as() const {
|
||||
return variantAsObject();
|
||||
}
|
||||
|
||||
inline JsonArray JsonVariant::variantAsArray() const {
|
||||
if (_type == Internals::JSON_ARRAY) return _content.asArray;
|
||||
return JsonArray();
|
||||
}
|
||||
|
||||
inline JsonObject JsonVariant::variantAsObject() const {
|
||||
if (_type == Internals::JSON_OBJECT) return _content.asObject;
|
||||
return JsonObject();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonVariant::variantAsInteger() const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
case JSON_UNPARSED:
|
||||
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:
|
||||
return parseInteger<T>(_content.asString);
|
||||
default:
|
||||
return T(_content.asFloat);
|
||||
}
|
||||
}
|
||||
|
||||
inline const char *JsonVariant::variantAsString() const {
|
||||
using namespace Internals;
|
||||
return _type == JSON_STRING ? _content.asString : NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonVariant::variantAsFloat() const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
case JSON_UNPARSED:
|
||||
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:
|
||||
return parseFloat<T>(_content.asString);
|
||||
default:
|
||||
return static_cast<T>(_content.asFloat);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool JsonVariant::variantIsBoolean() const {
|
||||
using namespace Internals;
|
||||
return _type == JSON_BOOLEAN;
|
||||
}
|
||||
|
||||
inline bool JsonVariant::variantIsInteger() const {
|
||||
using namespace Internals;
|
||||
|
||||
return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER;
|
||||
}
|
||||
|
||||
inline bool JsonVariant::variantIsFloat() const {
|
||||
using namespace Internals;
|
||||
|
||||
return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER ||
|
||||
_type == JSON_NEGATIVE_INTEGER;
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
@ -1,51 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantOr {
|
||||
public:
|
||||
// Returns the default value if the JsonVariant is undefined of incompatible
|
||||
template <typename T>
|
||||
typename enable_if<!is_integral<T>::value, T>::type 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;
|
||||
}
|
||||
|
||||
// Returns the default value if the JsonVariant is undefined of incompatible
|
||||
// Special case for integers: we also accept double
|
||||
template <typename Integer>
|
||||
typename enable_if<is_integral<Integer>::value, Integer>::type operator|(
|
||||
const Integer &defaultValue) const {
|
||||
if (impl()->template is<double>())
|
||||
return impl()->template as<Integer>();
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,78 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "Strings/StringTypes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
namespace Internals {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArraySubscript;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantSubscripts {
|
||||
public:
|
||||
// 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 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.
|
||||
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
|
||||
// an object.
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString>::value,
|
||||
const JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) const;
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value,
|
||||
JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key);
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<const TString *>::value,
|
||||
JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key);
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString *>::value,
|
||||
const JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) const;
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
28
src/ArduinoJson/Memory/Alignment.hpp
Normal file
28
src/ArduinoJson/Memory/Alignment.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline bool isAligned(void *ptr) {
|
||||
const size_t mask = sizeof(void *) - 1;
|
||||
size_t addr = reinterpret_cast<size_t>(ptr);
|
||||
return (addr & mask) == 0;
|
||||
}
|
||||
|
||||
inline size_t addPadding(size_t bytes) {
|
||||
const size_t mask = sizeof(void *) - 1;
|
||||
return (bytes + mask) & ~mask;
|
||||
}
|
||||
|
||||
template <size_t bytes>
|
||||
struct AddPadding {
|
||||
static const size_t mask = sizeof(void *) - 1;
|
||||
static const size_t value = (bytes + mask) & ~mask;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user