forked from bblanchon/ArduinoJson
Compare commits
109 Commits
5.x
...
v6.8.0-bet
Author | SHA1 | Date | |
---|---|---|---|
169c83431c | |||
5f72c68d87 | |||
b184af6d00 | |||
6f55d1e58f | |||
5aea1363cc | |||
70739f5cfd | |||
933a66a070 | |||
4167b11434 | |||
2a3b51ac3a | |||
e633292df1 | |||
30b94493bb | |||
c51cc91f92 | |||
8b04046321 | |||
11bb5e26ff | |||
9ac2ac303c | |||
f0784d3b41 | |||
3d8ece8c8b | |||
b0fb71f7d8 | |||
a5cd1b1693 | |||
d8a1eec530 | |||
e20c47c57b | |||
b77b203935 | |||
1ad97ebf85 | |||
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 | |||
39e5660c4a | |||
6b985b2d1f | |||
527dc19794 | |||
29e71cbb16 | |||
2d54019f83 | |||
98c8e8e35a | |||
b106b1ed14 | |||
2998a55f0b | |||
e5c4778ff7 | |||
2ec9569b36 | |||
58303d0837 | |||
e3639918eb | |||
6d290bd001 | |||
7683667b3c | |||
9cbc891816 | |||
0454bd1ef6 | |||
f139100b23 | |||
3f666bd5f0 | |||
d53a93e0ae | |||
2059d610a8 | |||
9bbfbd0a6a | |||
6e4f1dc756 | |||
dc13882624 | |||
6bb17d5896 | |||
1a513cbd16 | |||
87fa87d87b | |||
765752261c | |||
037f90aada | |||
1397bec066 | |||
b105e6f7c4 | |||
4fe2b1100e | |||
c3403ed72d | |||
393f352b70 | |||
e86eb0cfdf | |||
a9a730fd74 | |||
4ff6809bc5 | |||
f53fc3e06f | |||
0139354780 | |||
fc2e3a4ab3 | |||
58cb793c96 | |||
4592f23260 | |||
ccb54136a2 | |||
4c9c047ddf | |||
1feb92679d | |||
a13b9e8bdc | |||
cb723840d9 | |||
923d3e8a84 | |||
0d1623edef | |||
cf149940ed | |||
ef55a6ba7c | |||
e3e4aa89ad | |||
b2a8085651 | |||
83d73c93f7 | |||
7a2a64803a | |||
baf5adcf33 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@
|
||||
/fuzzing/*_fuzzer
|
||||
/fuzzing/*_fuzzer.options
|
||||
/fuzzing/*_fuzzer_seed_corpus.zip
|
||||
.vs/
|
||||
|
12
.travis.yml
12
.travis.yml
@ -2,12 +2,6 @@ sudo: false
|
||||
language: cpp
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.4']
|
||||
env: SCRIPT=cmake GCC=4.4
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
@ -37,7 +31,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5']
|
||||
env: SCRIPT=cmake GCC=5
|
||||
env: SCRIPT=cmake GCC=5 # SANITIZE=undefined
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
@ -119,7 +113,7 @@ matrix:
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake SANITIZE=address
|
||||
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=arduino VERSION=1.8.2 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
|
||||
@ -131,4 +125,6 @@ matrix:
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- "fuzzing/json_corpus"
|
||||
- "fuzzing/msgpack_corpus"
|
||||
script: scripts/travis/$SCRIPT.sh
|
||||
|
345
CHANGELOG.md
345
CHANGELOG.md
@ -1,17 +1,301 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v5.13.4
|
||||
-------
|
||||
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
|
||||
|
||||
v5.13.3
|
||||
-------
|
||||
v6.6.0-beta (2018-11-13)
|
||||
-----------
|
||||
|
||||
* Improved float serialization when `-fsingle-precision-constant` is used
|
||||
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
|
||||
* 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 (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()`
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### Non quoted strings
|
||||
>
|
||||
> Non quoted strings are now forbidden in values, but they are still allowed in keys.
|
||||
> For example, `{key:"value"}` is accepted, but `{key:value}` is not.
|
||||
>
|
||||
> #### Preformatted values
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> object["values"] = RawJson("[1,2,3,4]");
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> object["values"] = serialized("[1,2,3,4]");
|
||||
> ```
|
||||
|
||||
v6.1.0-beta (2018-07-02)
|
||||
-----------
|
||||
|
||||
* Return `JsonArray` and `JsonObject` by value instead of reference (issue #309)
|
||||
* Replaced `success()` with `isNull()`
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonObject& obj = doc.to<JsonObject>();
|
||||
> JsonArray& arr = obj.createNestedArray("key");
|
||||
> if (!arr.success()) {
|
||||
> Serial.println("Not enough memory");
|
||||
> return;
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonObject obj = doc.to<JsonObject>();
|
||||
> JsonArray arr = obj.createNestedArray("key");
|
||||
> if (arr.isNull()) {
|
||||
> Serial.println("Not enough memory");
|
||||
> return;
|
||||
> }
|
||||
> ```
|
||||
|
||||
v6.0.1-beta (2018-06-11)
|
||||
-----------
|
||||
|
||||
* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752)
|
||||
|
||||
v6.0.0-beta (2018-06-07)
|
||||
-----------
|
||||
|
||||
* Added `DynamicJsonDocument` and `StaticJsonDocument`
|
||||
* Added `deserializeJson()`
|
||||
* Added `serializeJson()` and `serializeJsonPretty()`
|
||||
* Added `measureJson()` and `measureJsonPretty()`
|
||||
* Added `serializeMsgPack()`, `deserializeMsgPack()` and `measureMsgPack()` (issue #358)
|
||||
* Added example `MsgPackParser.ino` (issue #358)
|
||||
* Added support for non zero-terminated strings (issue #704)
|
||||
* Removed `JsonBuffer::parseArray()`, `parseObject()` and `parse()`
|
||||
* Removed `JsonBuffer::createArray()` and `createObject()`
|
||||
* Removed `printTo()` and `prettyPrintTo()`
|
||||
* Removed `measureLength()` and `measurePrettyLength()`
|
||||
* Removed all deprecated features
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### Deserialization
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonBuffer jb;
|
||||
> JsonObject& obj = jb.parseObject(json);
|
||||
> if (obj.success()) {
|
||||
>
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> DeserializationError error = deserializeJson(doc, json);
|
||||
> if (error) {
|
||||
>
|
||||
> }
|
||||
> JsonObject& obj = doc.as<JsonObject>();
|
||||
> ```
|
||||
>
|
||||
> #### Serialization
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonBuffer jb;
|
||||
> JsonObject& obj = jb.createObject();
|
||||
> obj["key"] = "value";
|
||||
> obj.printTo(Serial);
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument obj;
|
||||
> JsonObject& obj = doc.to<JsonObject>();
|
||||
> obj["key"] = "value";
|
||||
> serializeJson(doc, Serial);
|
||||
> ```
|
||||
|
||||
v5.13.2
|
||||
-------
|
||||
@ -432,52 +716,3 @@ However, you should not see this as an invitation to use the `String` class.
|
||||
The `String` class is **bad** because it uses dynamic memory allocation.
|
||||
Compared to static allocation, it compiles to a bigger, slower program, and is less predictable.
|
||||
You certainly don't want that in an embedded environment!
|
||||
|
||||
v4.6
|
||||
----
|
||||
|
||||
* Fixed segmentation fault in `DynamicJsonBuffer` when memory allocation fails (issue #92)
|
||||
|
||||
v4.5
|
||||
----
|
||||
|
||||
* Fixed buffer overflow when input contains a backslash followed by a terminator (issue #81)
|
||||
|
||||
**Upgrading is recommended** since previous versions contain a potential security risk.
|
||||
|
||||
Special thanks to [Giancarlo Canales Barreto](https://github.com/gcanalesb) for finding this nasty bug.
|
||||
|
||||
v4.4
|
||||
----
|
||||
|
||||
* Added `JsonArray::measureLength()` and `JsonObject::measureLength()` (issue #75)
|
||||
|
||||
v4.3
|
||||
----
|
||||
|
||||
* Added `JsonArray::removeAt()` to remove an element of an array (issue #58)
|
||||
* Fixed stack-overflow in `DynamicJsonBuffer` when parsing huge JSON files (issue #65)
|
||||
* Fixed wrong return value of `parseArray()` and `parseObject()` when allocation fails (issue #68)
|
||||
|
||||
v4.2
|
||||
----
|
||||
|
||||
* Switched back to old library layout (issues #39, #43 and #45)
|
||||
* Removed global new operator overload (issue #40, #45 and #46)
|
||||
* Added an example with EthernetServer
|
||||
|
||||
v4.1
|
||||
----
|
||||
|
||||
* Added DynamicJsonBuffer (issue #19)
|
||||
|
||||
v4.0
|
||||
----
|
||||
|
||||
* Unified parser and generator API (issue #23)
|
||||
* Updated library layout, now requires Arduino 1.0.6 or newer
|
||||
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> API changed significantly since v3, see [Migrating code to the new API](https://arduinojson.org/doc/migration/).
|
||||
|
||||
|
@ -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)
|
||||
|
25
README.md
25
README.md
@ -2,10 +2,10 @@
|
||||
|
||||
---
|
||||
|
||||
[](https://www.ardu-badge.com/ArduinoJson/5.13.4)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master)
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
[](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
|
||||
[](https://www.ardu-badge.com/ArduinoJson/6.7.0-beta)
|
||||
[](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).
|
||||
@ -14,6 +14,7 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
|
||||
* JSON decoding (comments are supported)
|
||||
* JSON encoding (with optional indentation)
|
||||
* MessagePack
|
||||
* Elegant API, easy to use
|
||||
* Fixed memory allocation (zero malloc)
|
||||
* No data duplication (zero copy)
|
||||
@ -63,10 +64,10 @@ Here is a program that parses a JSON document with ArduinoJson.
|
||||
```c++
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
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];
|
||||
@ -80,17 +81,17 @@ See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_
|
||||
Here is a program that generates a JSON document with ArduinoJson:
|
||||
|
||||
```c++
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
DynamicJsonDocument doc(1024);
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
root.printTo(Serial);
|
||||
serializeJson(doc, Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
```
|
||||
@ -111,4 +112,4 @@ The documentation is available on [arduinojson.org](https://arduinojson.org/?utm
|
||||
Do you like this library? Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)!
|
||||
|
||||
What? You don't like it but you *love* it?
|
||||
We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time!
|
||||
We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time!
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 5.13.4.{build}
|
||||
version: 6.4.0.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
@ -15,7 +15,11 @@
|
||||
#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.
|
||||
struct Config {
|
||||
char hostname[64];
|
||||
int port;
|
||||
@ -29,24 +33,23 @@ void loadConfiguration(const char *filename, Config &config) {
|
||||
// Open file for reading
|
||||
File file = SD.open(filename);
|
||||
|
||||
// Allocate the memory pool on the stack.
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<512> jsonBuffer;
|
||||
// Allocate a temporary JsonDocument
|
||||
// Don't forget to change the capacity to match your requirements.
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<512> doc;
|
||||
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.parseObject(file);
|
||||
|
||||
if (!root.success())
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, file);
|
||||
if (error)
|
||||
Serial.println(F("Failed to read file, using default configuration"));
|
||||
|
||||
// Copy values from the JsonObject to the Config
|
||||
config.port = root["port"] | 2731;
|
||||
strlcpy(config.hostname, // <- destination
|
||||
root["hostname"] | "example.com", // <- source
|
||||
sizeof(config.hostname)); // <- destination's capacity
|
||||
// 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
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -62,24 +65,21 @@ void saveConfiguration(const char *filename, const Config &config) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the memory pool on the stack
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Use https://arduinojson.org/assistant/ to compute the capacity.
|
||||
StaticJsonBuffer<256> jsonBuffer;
|
||||
// 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;
|
||||
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.createObject();
|
||||
|
||||
// Set the values
|
||||
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 (root.printTo(file) == 0) {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ void printFile(const char *filename) {
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// Close the file (File's destructor doesn't close the file)
|
||||
// Close the file
|
||||
file.close();
|
||||
}
|
||||
|
||||
@ -130,15 +130,4 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization or deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a case study of a project that has
|
||||
// a complex configuration with nested members.
|
||||
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
// Visit https://arduinojson.org/v6/example/config/ for more.
|
||||
|
@ -11,48 +11,42 @@ void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
// 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;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer(200);
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// Create the root of the object tree.
|
||||
// Add values in the document
|
||||
//
|
||||
// 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.
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
doc["sensor"] = "gps";
|
||||
doc["time"] = 1351824120;
|
||||
|
||||
// Add values in the object
|
||||
// Add an array.
|
||||
//
|
||||
// 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;
|
||||
|
||||
// Add a nested array.
|
||||
//
|
||||
// It's also possible to create the array separately and add it to the
|
||||
// JsonObject but it's less efficient.
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
JsonArray data = doc.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
root.printTo(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();
|
||||
|
||||
root.prettyPrintTo(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,
|
||||
@ -67,15 +61,4 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like serializing directly to a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
// Visit https://arduinojson.org/v6/example/generator/ for more.
|
||||
|
@ -70,24 +70,25 @@ void setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
// Allocate the JSON document
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
|
||||
DynamicJsonBuffer jsonBuffer(capacity);
|
||||
DynamicJsonDocument doc(capacity);
|
||||
|
||||
// Parse JSON object
|
||||
JsonObject& root = jsonBuffer.parseObject(client);
|
||||
if (!root.success()) {
|
||||
Serial.println(F("Parsing failed!"));
|
||||
DeserializationError error = deserializeJson(doc, client);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract values
|
||||
Serial.println(F("Response:"));
|
||||
Serial.println(root["sensor"].as<char*>());
|
||||
Serial.println(root["time"].as<char*>());
|
||||
Serial.println(root["data"][0].as<char*>());
|
||||
Serial.println(root["data"][1].as<char*>());
|
||||
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();
|
||||
@ -97,16 +98,4 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization
|
||||
// showing how to parse the response from Yahoo Weather. In the last chapter,
|
||||
// it shows how to parse the huge documents from OpenWeatherMap
|
||||
// and Weather Underground.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
// Visit https://arduinojson.org/v6/example/http-client/ for more.
|
||||
|
@ -11,47 +11,47 @@ void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the 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.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer(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]}";
|
||||
|
||||
// Root 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.
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, json);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (!root.success()) {
|
||||
Serial.println("parseObject() failed");
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// 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,15 +64,4 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like deserializing directly from a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
// Visit https://arduinojson.org/v6/example/parser/ for more.
|
||||
|
@ -2,15 +2,15 @@
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// 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]
|
||||
// }
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
@ -51,15 +51,12 @@ void loop() {
|
||||
// Read the request (we ignore the content in this example)
|
||||
while (client.available()) client.read();
|
||||
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
// Allocate a temporary JsonDocument
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<500> doc;
|
||||
|
||||
// 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 +66,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,31 +76,22 @@ void loop() {
|
||||
}
|
||||
|
||||
Serial.print(F("Sending: "));
|
||||
root.printTo(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
|
||||
root.prettyPrintTo(client);
|
||||
serializeJsonPretty(doc, client);
|
||||
|
||||
// Disconnect
|
||||
client.stop();
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or an HTTP client.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
// Visit https://arduinojson.org/v6/example/http-server/ for more.
|
||||
|
@ -5,10 +5,10 @@
|
||||
// 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
|
||||
@ -43,15 +43,12 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
// Allocate a temporary JsonDocument
|
||||
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||
StaticJsonDocument<500> doc;
|
||||
|
||||
// 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 +58,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 +72,11 @@ void loop() {
|
||||
Serial.print(remoteIp);
|
||||
Serial.print(F(" on port "));
|
||||
Serial.println(remotePort);
|
||||
root.printTo(Serial);
|
||||
serializeJson(doc, Serial);
|
||||
|
||||
// Send UDP packet
|
||||
udp.beginPacket(remoteIp, remotePort);
|
||||
root.printTo(udp);
|
||||
serializeJson(doc, udp);
|
||||
udp.println();
|
||||
udp.endPacket();
|
||||
|
||||
@ -87,15 +84,4 @@ void loop() {
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or any stream.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
// Visit https://arduinojson.org/v6/example/udp-beacon/ for more.
|
||||
|
75
examples/MsgPackParser/MsgPackParser.ino
Normal file
75
examples/MsgPackParser/MsgPackParser.ino
Normal file
@ -0,0 +1,75 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a MessagePack document with
|
||||
// ArduinoJson.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// 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<200> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject doc(200);
|
||||
|
||||
// MessagePack 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.
|
||||
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]
|
||||
// }
|
||||
|
||||
DeserializationError error = deserializeMsgPack(doc, input);
|
||||
|
||||
// Test if parsing succeeded.
|
||||
if (error) {
|
||||
Serial.print("deserializeMsgPack() failed: ");
|
||||
Serial.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// 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.
|
||||
Serial.println(sensor);
|
||||
Serial.println(time);
|
||||
Serial.println(latitude, 6);
|
||||
Serial.println(longitude, 6);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/msgpack-parser/ for more.
|
@ -6,7 +6,7 @@
|
||||
// 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.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
@ -14,34 +14,34 @@
|
||||
void setup() {
|
||||
#ifdef PROGMEM // <- check that Flash strings are supported
|
||||
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
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.
|
||||
JsonObject& root =
|
||||
jsonBuffer.parseObject(F("{\"sensor\":\"gps\",\"time\":1351824120,"
|
||||
"\"data\":[48.756080,2.302038]}"));
|
||||
// WARNING: the string 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>();
|
||||
|
||||
// You can use a Flash String to get an element of a JsonObject
|
||||
// No duplication is done.
|
||||
long time = root[F("time")];
|
||||
long time = obj[F("time")];
|
||||
|
||||
// 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.
|
||||
root[F("time")] = time;
|
||||
// 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.
|
||||
root["sensor"] = F("gps");
|
||||
// JsonDocument.
|
||||
obj["sensor"] = F("gps");
|
||||
|
||||
// It works with RawJson too:
|
||||
root["sensor"] = RawJson(F("\"gps\""));
|
||||
// It works with serialized() too:
|
||||
obj["sensor"] = serialized(F("\"gps\""));
|
||||
obj["sensor"] = serialized(F("\xA3gps"), 3);
|
||||
|
||||
// You can compare the content of a JsonVariant to a Flash String
|
||||
if (root["sensor"] == F("gps")) {
|
||||
if (obj["sensor"] == F("gps")) {
|
||||
// ...
|
||||
}
|
||||
|
||||
@ -56,15 +56,4 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any memory
|
||||
// problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. It also tells why you
|
||||
// should not abuse Flash strings with ArduinoJson.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
// Visit https://arduinojson.org/v6/example/progmem/ for more.
|
||||
|
@ -5,70 +5,61 @@
|
||||
// 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.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
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]}";
|
||||
JsonObject& root = jsonBuffer.parseObject(input);
|
||||
deserializeJson(doc, input);
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
|
||||
// You can use a String to get an element of a JsonObject
|
||||
// No duplication is done.
|
||||
long time = root[String("time")];
|
||||
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.
|
||||
root[String("time")] = time;
|
||||
// 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.
|
||||
String sensor = root["sensor"];
|
||||
// No duplication is done, at least not in the JsonDocument.
|
||||
String sensor = obj["sensor"];
|
||||
|
||||
// Unfortunately, the following doesn't work (issue #118):
|
||||
// sensor = root["sensor"]; // <- error "ambiguous overload for 'operator='"
|
||||
// sensor = obj["sensor"]; // <- error "ambiguous overload for 'operator='"
|
||||
// As a workaround, you need to replace by:
|
||||
sensor = root["sensor"].as<String>();
|
||||
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.
|
||||
root["sensor"] = sensor;
|
||||
// WARNING: the content of the String will be duplicated in the JsonDocument.
|
||||
obj["sensor"] = sensor;
|
||||
|
||||
// It works with RawJson too:
|
||||
root["sensor"] = RawJson(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.
|
||||
root[String("sen") + "sor"] = String("gp") + "s";
|
||||
// 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
|
||||
if (root["sensor"] == sensor) {
|
||||
if (obj["sensor"] == sensor) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// Lastly, you can print the resulting JSON to a String
|
||||
String output;
|
||||
root.printTo(output);
|
||||
serializeJson(doc, output);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. On several occasions, it
|
||||
// shows how you can avoid String in your program.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
// Visit https://arduinojson.org/v6/example/string/ for more.
|
||||
|
17
fuzzing/CMakeLists.txt
Normal file
17
fuzzing/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2018
|
||||
# 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,19 +1,22 @@
|
||||
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
|
||||
|
||||
CXXFLAGS += -I../src
|
||||
CXXFLAGS += -I../src -DARDUINOJSON_DEBUG
|
||||
|
||||
all: \
|
||||
$(OUT)/json_fuzzer \
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/json_fuzzer.options
|
||||
$(OUT)/json_fuzzer.options \
|
||||
$(OUT)/msgpack_fuzzer \
|
||||
$(OUT)/msgpack_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/msgpack_fuzzer.options
|
||||
|
||||
$(OUT)/json_fuzzer: fuzzer.cpp $(shell find ../src -type f)
|
||||
$(OUT)/%_fuzzer: %_fuzzer.cpp $(shell find ../src -type f)
|
||||
$(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE)
|
||||
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip: seed_corpus/*
|
||||
$(OUT)/%_fuzzer_seed_corpus.zip: %_seed_corpus/*
|
||||
zip -j $@ $?
|
||||
|
||||
$(OUT)/json_fuzzer.options:
|
||||
$(OUT)/%_fuzzer.options:
|
||||
@echo "[libfuzzer]" > $@
|
||||
@echo "max_len = 256" >> $@
|
||||
@echo "timeout = 10" >> $@
|
||||
|
@ -1,26 +0,0 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class memstream : public std::istream {
|
||||
struct membuf : std::streambuf {
|
||||
membuf(const uint8_t *p, size_t l) {
|
||||
setg((char *)p, (char *)p, (char *)p + l);
|
||||
}
|
||||
};
|
||||
membuf _buffer;
|
||||
|
||||
public:
|
||||
memstream(const uint8_t *p, size_t l)
|
||||
: std::istream(&_buffer), _buffer(p, l) {
|
||||
rdbuf(&_buffer);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
memstream json(data, size);
|
||||
JsonVariant variant = jsonBuffer.parse(json);
|
||||
if (variant.success()) {
|
||||
variant.as<std::string>(); // <- serialize to JSON
|
||||
}
|
||||
return 0;
|
||||
}
|
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-2018
|
||||
// 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;
|
||||
}
|
11
fuzzing/json_fuzzer.cpp
Normal file
11
fuzzing/json_fuzzer.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc(4096);
|
||||
DeserializationError error = deserializeJson(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
2
fuzzing/msgpack_corpus/.gitignore
vendored
Normal file
2
fuzzing/msgpack_corpus/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
11
fuzzing/msgpack_fuzzer.cpp
Normal file
11
fuzzing/msgpack_fuzzer.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc(4096);
|
||||
DeserializationError error = deserializeMsgPack(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeMsgPack(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
fuzzing/msgpack_seed_corpus/array16
Normal file
BIN
fuzzing/msgpack_seed_corpus/array16
Normal file
Binary file not shown.
BIN
fuzzing/msgpack_seed_corpus/array32
Normal file
BIN
fuzzing/msgpack_seed_corpus/array32
Normal file
Binary file not shown.
1
fuzzing/msgpack_seed_corpus/false
Normal file
1
fuzzing/msgpack_seed_corpus/false
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/fixarray
Normal file
1
fuzzing/msgpack_seed_corpus/fixarray
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>hello<EFBFBD>world
|
1
fuzzing/msgpack_seed_corpus/fixint_negative
Normal file
1
fuzzing/msgpack_seed_corpus/fixint_negative
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/fixint_positive
Normal file
1
fuzzing/msgpack_seed_corpus/fixint_positive
Normal file
@ -0,0 +1 @@
|
||||
|
1
fuzzing/msgpack_seed_corpus/fixmap
Normal file
1
fuzzing/msgpack_seed_corpus/fixmap
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>one<01>two
|
1
fuzzing/msgpack_seed_corpus/fixstr
Normal file
1
fuzzing/msgpack_seed_corpus/fixstr
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>hello world
|
1
fuzzing/msgpack_seed_corpus/float32
Normal file
1
fuzzing/msgpack_seed_corpus/float32
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>@H<><48>
|
1
fuzzing/msgpack_seed_corpus/float64
Normal file
1
fuzzing/msgpack_seed_corpus/float64
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>@ !<21><><EFBFBD>o
|
1
fuzzing/msgpack_seed_corpus/int16
Normal file
1
fuzzing/msgpack_seed_corpus/int16
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/int32
Normal file
1
fuzzing/msgpack_seed_corpus/int32
Normal file
@ -0,0 +1 @@
|
||||
Ҷi<EFBFBD>.
|
1
fuzzing/msgpack_seed_corpus/int64
Normal file
1
fuzzing/msgpack_seed_corpus/int64
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/int8
Normal file
1
fuzzing/msgpack_seed_corpus/int8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>
|
BIN
fuzzing/msgpack_seed_corpus/map16
Normal file
BIN
fuzzing/msgpack_seed_corpus/map16
Normal file
Binary file not shown.
BIN
fuzzing/msgpack_seed_corpus/map32
Normal file
BIN
fuzzing/msgpack_seed_corpus/map32
Normal file
Binary file not shown.
1
fuzzing/msgpack_seed_corpus/nil
Normal file
1
fuzzing/msgpack_seed_corpus/nil
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
BIN
fuzzing/msgpack_seed_corpus/str16
Normal file
BIN
fuzzing/msgpack_seed_corpus/str16
Normal file
Binary file not shown.
BIN
fuzzing/msgpack_seed_corpus/str32
Normal file
BIN
fuzzing/msgpack_seed_corpus/str32
Normal file
Binary file not shown.
1
fuzzing/msgpack_seed_corpus/str8
Normal file
1
fuzzing/msgpack_seed_corpus/str8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>hello
|
1
fuzzing/msgpack_seed_corpus/true
Normal file
1
fuzzing/msgpack_seed_corpus/true
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/uint16
Normal file
1
fuzzing/msgpack_seed_corpus/uint16
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>09
|
1
fuzzing/msgpack_seed_corpus/uint32
Normal file
1
fuzzing/msgpack_seed_corpus/uint32
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>4Vx
|
1
fuzzing/msgpack_seed_corpus/uint64
Normal file
1
fuzzing/msgpack_seed_corpus/uint64
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/uint8
Normal file
1
fuzzing/msgpack_seed_corpus/uint8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>
|
45
keywords.txt
45
keywords.txt
@ -1,15 +1,36 @@
|
||||
JsonArray KEYWORD1
|
||||
JsonObject KEYWORD1
|
||||
JsonVariant KEYWORD1
|
||||
StaticJsonBuffer KEYWORD1
|
||||
DynamicJsonBuffer KEYWORD1
|
||||
# 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
|
||||
createArray KEYWORD2
|
||||
as KEYWORD2
|
||||
createNestedArray KEYWORD2
|
||||
createNestedObject KEYWORD2
|
||||
createObject KEYWORD2
|
||||
parseArray KEYWORD2
|
||||
parseObject KEYWORD2
|
||||
prettyPrintTo KEYWORD2
|
||||
printTo KEYWORD2
|
||||
success KEYWORD2
|
||||
get KEYWORD2
|
||||
set KEYWORD2
|
||||
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": "5.13.4",
|
||||
"version": "6.8.0-beta",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "https://blog.benoitblanchon.fr"
|
||||
|
@ -1,9 +1,9 @@
|
||||
name=ArduinoJson
|
||||
version=5.13.4
|
||||
version=6.8.0-beta
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ fixed allocation, ✔ zero-copy, ✔ streams, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
||||
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ MessagePack, ✔ fixed allocation, ✔ zero-copy, ✔ streams, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
||||
category=Data Processing
|
||||
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
|
||||
architectures=*
|
||||
|
11
scripts/oss-fuzz/Vagrantfile
vendored
11
scripts/oss-fuzz/Vagrantfile
vendored
@ -2,11 +2,16 @@
|
||||
Vagrant.configure(2) do |config|
|
||||
config.vm.box = "ubuntu/xenial64"
|
||||
|
||||
config.vm.synced_folder "E:\\Git\\Arduino\\libraries\\ArduinoJson", "/host/ArduinoJson"
|
||||
config.vm.synced_folder "../..", "/host/ArduinoJson"
|
||||
config.vm.synced_folder "E:\\Git\\oss-fuzz", "/host/oss-fuzz"
|
||||
|
||||
config.vm.network "forwarded_port", guest: 8001, host: 8001
|
||||
|
||||
config.vm.provider "virtualbox" do |v|
|
||||
v.memory = 2048
|
||||
v.cpus = 2
|
||||
end
|
||||
|
||||
config.vm.provision "shell", privileged: false, inline: <<-SHELL
|
||||
set -x
|
||||
|
||||
@ -18,10 +23,6 @@ Vagrant.configure(2) do |config|
|
||||
git clone https://github.com/google/fuzzer-test-suite.git FTS
|
||||
./FTS/tutorial/install-deps.sh # Get deps
|
||||
./FTS/tutorial/install-clang.sh # Get fresh clang binaries
|
||||
# Get libFuzzer sources and build it
|
||||
svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
|
||||
Fuzzer/build.sh
|
||||
sudo mv libFuzzer.a /usr/local/lib/
|
||||
|
||||
echo "export PROJECT_NAME='arduinojson'" >> $HOME/.profile
|
||||
echo "export CC='clang'" >> $HOME/.profile
|
||||
|
57
scripts/publish.sh
Normal file
57
scripts/publish.sh
Normal file
@ -0,0 +1,57 @@
|
||||
#!/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 \
|
||||
-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 CHANGELOG.md library.json library.properties
|
||||
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"
|
@ -1,4 +1,4 @@
|
||||
#!/bin/sh -eux
|
||||
#!/bin/bash -eux
|
||||
|
||||
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
|
||||
sleep 3
|
||||
@ -6,9 +6,13 @@ export DISPLAY=:1.0
|
||||
|
||||
mkdir -p /tmp/arduino
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tar.xz | tar xJ -C /tmp/arduino --strip 1 ||
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tgz | tar xz -C /tmp/arduino --strip 1
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tgz | tar xz -C /tmp/arduino --strip 1
|
||||
export PATH=$PATH:/tmp/arduino/
|
||||
|
||||
|
||||
if [[ "$BOARD" =~ "arduino:samd:" ]]; then
|
||||
arduino --install-boards arduino:samd
|
||||
fi
|
||||
|
||||
ln -s $PWD /tmp/arduino/libraries/ArduinoJson
|
||||
|
||||
for EXAMPLE in $PWD/examples/*/*.ino; do
|
||||
|
@ -1,20 +1,26 @@
|
||||
#!/bin/bash -eux
|
||||
|
||||
ROOT_DIR=$(dirname $0)/../../
|
||||
INCLUDE_DIR=$ROOT_DIR/src/
|
||||
FUZZING_DIR=$ROOT_DIR/fuzzing/
|
||||
JSON_CORPUS_DIR=$FUZZING_DIR/my_corpus
|
||||
JSON_SEED_CORPUS_DIR=$FUZZING_DIR/seed_corpus
|
||||
|
||||
CXX="clang++-$CLANG"
|
||||
INCLUDE_DIR=${ROOT_DIR}/src/
|
||||
FUZZING_DIR=${ROOT_DIR}/fuzzing/
|
||||
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,fuzzer"
|
||||
|
||||
$CXX $CXXFLAGS -o json_fuzzer -I$INCLUDE_DIR $FUZZING_DIR/fuzzer.cpp
|
||||
fuzz() {
|
||||
NAME="$1"
|
||||
FUZZER="${NAME}_fuzzer"
|
||||
FUZZER_CPP="${FUZZING_DIR}/${NAME}_fuzzer.cpp"
|
||||
CORPUS_DIR="${FUZZING_DIR}/${NAME}_corpus"
|
||||
SEED_CORPUS_DIR="${FUZZING_DIR}/${NAME}_seed_corpus"
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="json_fuzzer.profraw"
|
||||
./json_fuzzer "$JSON_CORPUS_DIR" "$JSON_SEED_CORPUS_DIR" -max_total_time=60
|
||||
clang++-${CLANG} ${CXXFLAGS} -o ${FUZZER} -I$INCLUDE_DIR ${FUZZER_CPP}
|
||||
|
||||
llvm-profdata-$CLANG merge -sparse json_fuzzer.profraw -o json_fuzzer.profdata
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30 -timeout=1
|
||||
|
||||
llvm-cov-$CLANG report ./json_fuzzer -instr-profile=json_fuzzer.profdata
|
||||
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER}.profdata
|
||||
llvm-cov-${CLANG} report ./${FUZZER} -instr-profile=${FUZZER}.profdata
|
||||
}
|
||||
|
||||
fuzz json
|
||||
fuzz msgpack
|
||||
|
57
scripts/wandbox/JsonGeneratorExample.cpp
Normal file
57
scripts/wandbox/JsonGeneratorExample.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// 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/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);
|
||||
|
||||
// Make our document be an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
|
||||
// Add values in the object
|
||||
//
|
||||
// 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;
|
||||
|
||||
// Add an array.
|
||||
//
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
serializeJson(root, std::cout);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
serializeJsonPretty(root, std::cout);
|
||||
// This prints:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [
|
||||
// 48.756080,
|
||||
// 2.302038
|
||||
// ]
|
||||
// }
|
||||
|
||||
return 0;
|
||||
}
|
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-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// Root JSON object
|
||||
//
|
||||
// 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;
|
||||
|
||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject 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.
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 doc["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["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;
|
||||
}
|
71
scripts/wandbox/MsgPackParserExample.cpp
Normal file
71
scripts/wandbox/MsgPackParserExample.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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 doc["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["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"
|
@ -4,16 +4,53 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/version.hpp"
|
||||
#include "ArduinoJson/Namespace.hpp"
|
||||
|
||||
#include "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
#include "ArduinoJson/Array/ArrayRef.hpp"
|
||||
#include "ArduinoJson/Object/ObjectRef.hpp"
|
||||
#include "ArduinoJson/Variant/VariantRef.hpp"
|
||||
|
||||
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonBufferImpl.hpp"
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
|
||||
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
|
||||
|
||||
#include "ArduinoJson/Array/ArrayImpl.hpp"
|
||||
#include "ArduinoJson/Array/ElementProxy.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"
|
||||
|
||||
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::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-2018
|
||||
// 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-2018
|
||||
// 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()->add().template to<ArrayRef>();
|
||||
}
|
||||
|
||||
template <typename TArray>
|
||||
inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
|
||||
return impl()->add().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-2018
|
||||
// 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
|
201
src/ArduinoJson/Array/ArrayRef.hpp
Normal file
201
src/ArduinoJson/Array/ArrayRef.hpp
Normal file
@ -0,0 +1,201 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// 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 {
|
||||
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 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() {
|
||||
return VariantRef(_pool, reinterpret_cast<VariantData*>(_data));
|
||||
}
|
||||
|
||||
operator ArrayConstRef() const {
|
||||
return ArrayConstRef(_data);
|
||||
}
|
||||
|
||||
using ArrayShortcuts::add;
|
||||
VariantRef add() 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();
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T, size_t N>
|
||||
FORCE_INLINE bool copyFrom(T (&array)[N]) const {
|
||||
return copyFrom(array, N);
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T>
|
||||
bool copyFrom(T* array, size_t len) const {
|
||||
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]) const {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < N1; i++) {
|
||||
ArrayRef nestedArray = createNestedArray();
|
||||
for (size_t j = 0; j < N2; j++) {
|
||||
ok &= nestedArray.add(array[i][j]);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Copy a ArrayRef
|
||||
FORCE_INLINE bool copyFrom(ArrayConstRef src) const {
|
||||
if (!_data || !src._data) return false;
|
||||
return _data->copyFrom(*src._data, _pool);
|
||||
}
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T, size_t N>
|
||||
FORCE_INLINE 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 (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 (iterator it = begin(); it != end() && i < N1; ++it) {
|
||||
it->as<ArrayRef>().copyTo(array[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE bool operator==(ArrayRef rhs) const {
|
||||
return arrayEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
// Gets the value at the specified index.
|
||||
FORCE_INLINE VariantRef get(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-2018
|
||||
// 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()->add().set(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(T *value) const {
|
||||
return impl()->add().set(value);
|
||||
}
|
||||
|
||||
private:
|
||||
const TArray *impl() const {
|
||||
return static_cast<const TArray *>(this);
|
||||
}
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
139
src/ArduinoJson/Array/ElementProxy.hpp
Normal file
139
src/ArduinoJson/Array/ElementProxy.hpp
Normal file
@ -0,0 +1,139 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// 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) {
|
||||
getElement().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) {
|
||||
getElement().set(src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue)
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE this_type& operator=(T* src) {
|
||||
getElement().set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return getElement().isNull();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename VariantAs<T>::type as() const {
|
||||
return getElement().template as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is() const {
|
||||
return getElement().template is<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename VariantTo<T>::type to() const {
|
||||
return getElement().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 getElement().set(value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue)
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue* value) const {
|
||||
return getElement().set(value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor& visitor) const {
|
||||
return getElement().accept(visitor);
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return getElement().size();
|
||||
}
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef get(TNestedKey* key) const {
|
||||
return getElement().get(key);
|
||||
}
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef get(const TNestedKey& key) const {
|
||||
return getElement().get(key);
|
||||
}
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef getOrCreate(TNestedKey* key) const {
|
||||
return getElement().getOrCreate(key);
|
||||
}
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef getOrCreate(const TNestedKey& key) const {
|
||||
return getElement().getOrCreate(key);
|
||||
}
|
||||
|
||||
using ArrayShortcuts<ElementProxy>::add;
|
||||
VariantRef add() const {
|
||||
return getElement().add();
|
||||
}
|
||||
|
||||
private:
|
||||
FORCE_INLINE VariantRef getElement() const {
|
||||
return _array.get(_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
|
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-2018
|
||||
// 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-2018
|
||||
// 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 addSlot(pool)->data();
|
||||
}
|
||||
|
||||
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
|
@ -4,6 +4,18 @@
|
||||
|
||||
#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
|
||||
#else
|
||||
#define ARDUINOJSON_HAS_LONG_LONG 0
|
||||
#endif
|
||||
|
||||
// Small or big machine?
|
||||
#ifndef ARDUINOJSON_EMBEDDED_MODE
|
||||
#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
|
||||
@ -25,9 +37,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 +62,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
|
||||
@ -120,21 +120,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
// alignment isn't needed for 8-bit AVR
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
|
||||
#else
|
||||
// but most processors need pointers to be align on word size
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Enable deprecated functions by default
|
||||
#ifndef ARDUINOJSON_ENABLE_DEPRECATED
|
||||
#define ARDUINOJSON_ENABLE_DEPRECATED 1
|
||||
#endif
|
||||
|
||||
// Control the exponentiation threshold for big numbers
|
||||
// CAUTION: cannot be more that 1e9 !!!!
|
||||
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
|
||||
@ -146,6 +131,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
|
||||
#ifndef ARDUINOJSON_LITTLE_ENDIAN
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
|
||||
(defined(__LITTLE_ENDIAN__))
|
||||
#define ARDUINOJSON_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define ARDUINOJSON_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_TAB
|
||||
#define ARDUINOJSON_TAB " "
|
||||
#endif
|
||||
|
@ -1,22 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class JsonBufferAllocated {
|
||||
public:
|
||||
void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() {
|
||||
if (!jsonBuffer) return NULL;
|
||||
return jsonBuffer->alloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *, JsonBuffer *)throw();
|
||||
};
|
||||
}
|
||||
}
|
@ -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,42 +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;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<JsonArray> {
|
||||
typedef JsonArray& type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<const JsonArray> {
|
||||
typedef const JsonArray& type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<JsonObject> {
|
||||
typedef JsonObject& type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<const JsonObject> {
|
||||
typedef const JsonObject& type;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
// 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
|
||||
const char* asString; // asString can be null
|
||||
JsonArray* asArray; // asArray cannot be null
|
||||
JsonObject* asObject; // asObject cannot be null
|
||||
};
|
||||
}
|
||||
}
|
@ -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,27 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_UNDEFINED, // JsonVariant has not been initialized
|
||||
JSON_UNPARSED, // JsonVariant contains an unparsed string
|
||||
JSON_STRING, // JsonVariant stores a const char*
|
||||
JSON_BOOLEAN, // JsonVariant stores a bool
|
||||
JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt
|
||||
JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated
|
||||
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray
|
||||
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
|
||||
JSON_FLOAT // JsonVariant stores a JsonFloat
|
||||
};
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../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 JsonArray and JsonObject
|
||||
template <typename T>
|
||||
class List {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ListNode<T> node_type;
|
||||
typedef ListIterator<T> iterator;
|
||||
typedef ListConstIterator<T> const_iterator;
|
||||
|
||||
// Creates an empty List<T> attached to a JsonBuffer.
|
||||
// The JsonBuffer allows to allocate new nodes.
|
||||
// When buffer is NULL, the List is not able to grow and success() returns
|
||||
// false. This is used to identify bad memory allocations and parsing
|
||||
// failures.
|
||||
explicit List(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {}
|
||||
|
||||
// Returns true if the object is valid
|
||||
// Would return false in the following situation:
|
||||
// - the memory allocation failed (StaticJsonBuffer was too small)
|
||||
// - the JSON parsing failed
|
||||
bool success() const {
|
||||
return _buffer != NULL;
|
||||
}
|
||||
|
||||
// Returns the numbers of elements in the list.
|
||||
// For a JsonObject, 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;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonBuffer *_buffer;
|
||||
|
||||
private:
|
||||
node_type *_firstNode;
|
||||
};
|
||||
}
|
||||
}
|
@ -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 "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;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A type that cannot be copied
|
||||
class NonCopyable {
|
||||
protected:
|
||||
NonCopyable() {}
|
||||
|
||||
private:
|
||||
// copy constructor is private
|
||||
NonCopyable(const NonCopyable&);
|
||||
|
||||
// copy operator is private
|
||||
NonCopyable& operator=(const NonCopyable&);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A type that is meant to be used by reference only (JsonArray and JsonObject)
|
||||
class ReferenceType {
|
||||
public:
|
||||
bool operator==(const ReferenceType& other) const {
|
||||
// two JsonArray are equal if they are the same instance
|
||||
// (we don't compare the content)
|
||||
return this == &other;
|
||||
}
|
||||
|
||||
bool operator!=(const ReferenceType& other) const {
|
||||
return this != &other;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename Source, typename Enable = void>
|
||||
struct ValueSaver {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& destination, Source source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
struct ValueSaver<
|
||||
Source, typename EnableIf<StringTraits<Source>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer* buffer, Destination& dest, Source source) {
|
||||
if (!StringTraits<Source>::is_null(source)) {
|
||||
typename StringTraits<Source>::duplicate_t dup =
|
||||
StringTraits<Source>::duplicate(source, buffer);
|
||||
if (!dup) return false;
|
||||
dest = dup;
|
||||
} else {
|
||||
dest = reinterpret_cast<const char*>(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// const char*, const signed char*, const unsigned char*
|
||||
template <typename Char>
|
||||
struct ValueSaver<
|
||||
Char*, typename EnableIf<!StringTraits<Char*>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& dest, Char* source) {
|
||||
dest = reinterpret_cast<const char*>(source);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
39
src/ArduinoJson/Deserialization/ArduinoStreamReader.hpp
Normal file
39
src/ArduinoJson/Deserialization/ArduinoStreamReader.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct ArduinoStreamReader {
|
||||
Stream& _stream;
|
||||
char _current;
|
||||
bool _ended;
|
||||
|
||||
public:
|
||||
explicit ArduinoStreamReader(Stream& stream)
|
||||
: _stream(stream), _current(0), _ended(false) {}
|
||||
|
||||
char 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;
|
||||
}
|
||||
};
|
||||
|
||||
inline ArduinoStreamReader makeReader(Stream& input) {
|
||||
return ArduinoStreamReader(input);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
59
src/ArduinoJson/Deserialization/CharPointerReader.hpp
Normal file
59
src/ArduinoJson/Deserialization/CharPointerReader.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class UnsafeCharPointerReader {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
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, that's why it's unsafe
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class SafeCharPointerReader {
|
||||
const char* _ptr;
|
||||
const char* _end;
|
||||
|
||||
public:
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
inline UnsafeCharPointerReader makeReader(TChar* input) {
|
||||
return UnsafeCharPointerReader(reinterpret_cast<const char*>(input));
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline SafeCharPointerReader makeReader(TChar* input, size_t n) {
|
||||
return SafeCharPointerReader(reinterpret_cast<const char*>(input), n);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
inline SafeCharPointerReader makeReader(const ::String& input) {
|
||||
return SafeCharPointerReader(input.c_str(), input.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,61 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TInput>
|
||||
void skipSpacesAndComments(TInput& input) {
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
input.move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
switch (input.next()) {
|
||||
// C-style block comment
|
||||
case '*':
|
||||
input.move(); // skip '/'
|
||||
// no need to skip '*'
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '*' && input.next() == '/') {
|
||||
input.move(); // skip '*'
|
||||
input.move(); // skip '/'
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// C++-style line comment
|
||||
case '/':
|
||||
// not need to skip "//"
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '\n') break;
|
||||
}
|
||||
break;
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
113
src/ArduinoJson/Deserialization/DeserializationError.hpp
Normal file
113
src/ArduinoJson/Deserialization/DeserializationError.hpp
Normal file
@ -0,0 +1,113 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class DeserializationError {
|
||||
// safe bool idiom
|
||||
typedef void (DeserializationError::*bool_type)() const;
|
||||
void safeBoolHelper() const {}
|
||||
|
||||
public:
|
||||
enum Code {
|
||||
Ok,
|
||||
IncompleteInput,
|
||||
InvalidInput,
|
||||
NoMemory,
|
||||
NotSupported,
|
||||
TooDeep
|
||||
};
|
||||
|
||||
DeserializationError() {}
|
||||
DeserializationError(Code c) : _code(c) {}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Returns internal enum, useful for switch statement
|
||||
Code code() const {
|
||||
return _code;
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
switch (_code) {
|
||||
case Ok:
|
||||
return "Ok";
|
||||
case TooDeep:
|
||||
return "TooDeep";
|
||||
case NoMemory:
|
||||
return "NoMemory";
|
||||
case InvalidInput:
|
||||
return "InvalidInput";
|
||||
case IncompleteInput:
|
||||
return "IncompleteInput";
|
||||
case NotSupported:
|
||||
return "NotSupported";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Code _code;
|
||||
};
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(std::ostream& s,
|
||||
const DeserializationError& e) {
|
||||
s << e.c_str();
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
|
||||
s << DeserializationError(c).c_str();
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
54
src/ArduinoJson/Deserialization/FlashStringReader.hpp
Normal file
54
src/ArduinoJson/Deserialization/FlashStringReader.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class UnsafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||
|
||||
char read() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// this reader cannot detect the end
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class SafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
const char* _end;
|
||||
|
||||
public:
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
inline UnsafeFlashStringReader makeReader(const __FlashStringHelper* input) {
|
||||
return UnsafeFlashStringReader(input);
|
||||
}
|
||||
|
||||
inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
|
||||
size_t size) {
|
||||
return SafeFlashStringReader(input, size);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
32
src/ArduinoJson/Deserialization/IteratorReader.hpp
Normal file
32
src/ArduinoJson/Deserialization/IteratorReader.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TIterator>
|
||||
class IteratorReader {
|
||||
TIterator _ptr, _end;
|
||||
|
||||
public:
|
||||
explicit IteratorReader(TIterator begin, TIterator end)
|
||||
: _ptr(begin), _end(end) {}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
|
||||
char read() {
|
||||
return char(*_ptr++);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TInput>
|
||||
inline IteratorReader<typename TInput::const_iterator> makeReader(
|
||||
const TInput& input) {
|
||||
return IteratorReader<typename TInput::const_iterator>(input.begin(),
|
||||
input.end());
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,102 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../TypeTraits/IsConst.hpp"
|
||||
#include "StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Parse JSON string to create JsonArrays and JsonObjects
|
||||
// This internal class is not indended to be used directly.
|
||||
// Instead, use JsonBuffer.parseArray() or .parseObject()
|
||||
template <typename TReader, typename TWriter>
|
||||
class JsonParser {
|
||||
public:
|
||||
JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
_reader(reader),
|
||||
_writer(writer),
|
||||
_nestingLimit(nestingLimit) {}
|
||||
|
||||
JsonArray &parseArray();
|
||||
JsonObject &parseObject();
|
||||
|
||||
JsonVariant parseVariant() {
|
||||
JsonVariant result;
|
||||
parseAnythingTo(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonParser &operator=(const JsonParser &); // non-copiable
|
||||
|
||||
static bool eat(TReader &, char charToSkip);
|
||||
FORCE_INLINE bool eat(char charToSkip) {
|
||||
return eat(_reader, charToSkip);
|
||||
}
|
||||
|
||||
const char *parseString();
|
||||
bool parseAnythingTo(JsonVariant *destination);
|
||||
|
||||
inline bool parseArrayTo(JsonVariant *destination);
|
||||
inline bool parseObjectTo(JsonVariant *destination);
|
||||
inline bool parseStringTo(JsonVariant *destination);
|
||||
|
||||
static inline bool isBetween(char c, char min, char max) {
|
||||
return min <= c && c <= max;
|
||||
}
|
||||
|
||||
static inline bool canBeInNonQuotedString(char c) {
|
||||
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
|
||||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) {
|
||||
return c == '\'' || c == '\"';
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
TReader _reader;
|
||||
TWriter _writer;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString, typename Enable = void>
|
||||
struct JsonParserBuilder {
|
||||
typedef typename StringTraits<TString>::Reader InputReader;
|
||||
typedef JsonParser<InputReader, TJsonBuffer &> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TString &json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct JsonParserBuilder<TJsonBuffer, TChar *,
|
||||
typename EnableIf<!IsConst<TChar>::value>::type> {
|
||||
typedef typename StringTraits<TChar *>::Reader TReader;
|
||||
typedef StringWriter<TChar> TWriter;
|
||||
typedef JsonParser<TReader, TWriter> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString>
|
||||
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
|
||||
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
|
||||
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
|
||||
nestingLimit);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,189 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Comments.hpp"
|
||||
#include "JsonParser.hpp"
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
|
||||
TReader &reader, char charToSkip) {
|
||||
skipSpacesAndComments(reader);
|
||||
if (reader.current() != charToSkip) return false;
|
||||
reader.move();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingTo(
|
||||
JsonVariant *destination) {
|
||||
skipSpacesAndComments(_reader);
|
||||
|
||||
switch (_reader.current()) {
|
||||
case '[':
|
||||
return parseArrayTo(destination);
|
||||
|
||||
case '{':
|
||||
return parseObjectTo(destination);
|
||||
|
||||
default:
|
||||
return parseStringTo(destination);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline ArduinoJson::JsonArray &
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray() {
|
||||
if (_nestingLimit == 0) return JsonArray::invalid();
|
||||
_nestingLimit--;
|
||||
|
||||
// Create an empty array
|
||||
JsonArray &array = _buffer->createArray();
|
||||
|
||||
// Check opening braket
|
||||
if (!eat('[')) goto ERROR_MISSING_BRACKET;
|
||||
if (eat(']')) goto SUCCESS_EMPTY_ARRAY;
|
||||
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// 1 - Parse value
|
||||
JsonVariant value;
|
||||
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
|
||||
if (!array.add(value)) goto ERROR_NO_MEMORY;
|
||||
|
||||
// 2 - More values?
|
||||
if (eat(']')) goto SUCCES_NON_EMPTY_ARRAY;
|
||||
if (!eat(',')) goto ERROR_MISSING_COMMA;
|
||||
}
|
||||
|
||||
SUCCESS_EMPTY_ARRAY:
|
||||
SUCCES_NON_EMPTY_ARRAY:
|
||||
_nestingLimit++;
|
||||
return array;
|
||||
|
||||
ERROR_INVALID_VALUE:
|
||||
ERROR_MISSING_BRACKET:
|
||||
ERROR_MISSING_COMMA:
|
||||
ERROR_NO_MEMORY:
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArrayTo(
|
||||
JsonVariant *destination) {
|
||||
JsonArray &array = parseArray();
|
||||
if (!array.success()) return false;
|
||||
|
||||
*destination = array;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline ArduinoJson::JsonObject &
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject() {
|
||||
if (_nestingLimit == 0) return JsonObject::invalid();
|
||||
_nestingLimit--;
|
||||
|
||||
// Create an empty object
|
||||
JsonObject &object = _buffer->createObject();
|
||||
|
||||
// Check opening brace
|
||||
if (!eat('{')) goto ERROR_MISSING_BRACE;
|
||||
if (eat('}')) goto SUCCESS_EMPTY_OBJECT;
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// 1 - Parse key
|
||||
const char *key = parseString();
|
||||
if (!key) goto ERROR_INVALID_KEY;
|
||||
if (!eat(':')) goto ERROR_MISSING_COLON;
|
||||
|
||||
// 2 - Parse value
|
||||
JsonVariant value;
|
||||
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
|
||||
if (!object.set(key, value)) goto ERROR_NO_MEMORY;
|
||||
|
||||
// 3 - More keys/values?
|
||||
if (eat('}')) goto SUCCESS_NON_EMPTY_OBJECT;
|
||||
if (!eat(',')) goto ERROR_MISSING_COMMA;
|
||||
}
|
||||
|
||||
SUCCESS_EMPTY_OBJECT:
|
||||
SUCCESS_NON_EMPTY_OBJECT:
|
||||
_nestingLimit++;
|
||||
return object;
|
||||
|
||||
ERROR_INVALID_KEY:
|
||||
ERROR_INVALID_VALUE:
|
||||
ERROR_MISSING_BRACE:
|
||||
ERROR_MISSING_COLON:
|
||||
ERROR_MISSING_COMMA:
|
||||
ERROR_NO_MEMORY:
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObjectTo(
|
||||
JsonVariant *destination) {
|
||||
JsonObject &object = parseObject();
|
||||
if (!object.success()) return false;
|
||||
|
||||
*destination = object;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline const char *
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
|
||||
typename RemoveReference<TWriter>::type::String str = _writer.startString();
|
||||
|
||||
skipSpacesAndComments(_reader);
|
||||
char c = _reader.current();
|
||||
|
||||
if (isQuote(c)) { // quotes
|
||||
_reader.move();
|
||||
char stopChar = c;
|
||||
for (;;) {
|
||||
c = _reader.current();
|
||||
if (c == '\0') break;
|
||||
_reader.move();
|
||||
|
||||
if (c == stopChar) break;
|
||||
|
||||
if (c == '\\') {
|
||||
// replace char
|
||||
c = Encoding::unescapeChar(_reader.current());
|
||||
if (c == '\0') break;
|
||||
_reader.move();
|
||||
}
|
||||
|
||||
str.append(c);
|
||||
}
|
||||
} else { // no quotes
|
||||
for (;;) {
|
||||
if (!canBeInNonQuotedString(c)) break;
|
||||
_reader.move();
|
||||
str.append(c);
|
||||
c = _reader.current();
|
||||
}
|
||||
}
|
||||
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseStringTo(
|
||||
JsonVariant *destination) {
|
||||
bool hasQuotes = isQuote(_reader.current());
|
||||
const char *value = parseString();
|
||||
if (value == NULL) return false;
|
||||
if (hasQuotes) {
|
||||
*destination = value;
|
||||
} else {
|
||||
*destination = RawJson(value);
|
||||
}
|
||||
return true;
|
||||
}
|
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-2018
|
||||
// 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
|
38
src/ArduinoJson/Deserialization/StdStreamReader.hpp
Normal file
38
src/ArduinoJson/Deserialization/StdStreamReader.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
|
||||
#include <istream>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StdStreamReader {
|
||||
std::istream& _stream;
|
||||
char _current;
|
||||
|
||||
public:
|
||||
explicit StdStreamReader(std::istream& stream)
|
||||
: _stream(stream), _current(0) {}
|
||||
|
||||
bool ended() const {
|
||||
return _stream.eof();
|
||||
}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(_stream.get());
|
||||
}
|
||||
|
||||
private:
|
||||
StdStreamReader& operator=(const StdStreamReader&); // Visual Studio C4512
|
||||
};
|
||||
|
||||
inline StdStreamReader makeReader(std::istream& input) {
|
||||
return StdStreamReader(input);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user