Compare commits

...

102 Commits

Author SHA1 Message Date
a0a451195b Set version to 6.11.1 2019-06-21 08:49:02 +02:00
ce247a5637 Fixed serialized() not working with Flash strings (fixes #1030) 2019-06-21 08:46:32 +02:00
59f9c9747f Add sponsor button on GitHub 2019-06-04 09:14:37 +02:00
fec088e3ed Set version to 6.11.0 2019-05-26 21:11:40 +02:00
4980ee8fb9 Fixed unexpected HTTP/1.0 (closes #944) 2019-05-26 21:07:01 +02:00
2ed77d2cc3 Added support for nullptr (closes #998) 2019-05-26 11:31:51 +02:00
630107ae8a Removed implicit conversion in comparison operators (issue #998) 2019-05-23 21:54:42 +02:00
4eb8074358 Set ARDUINOJSON_ENABLE_NAN and ARDUINOJSON_ENABLE_INFINITY to 0 2019-05-19 17:46:20 +02:00
80a02cd90d Added ARDUINOJSON_ENABLE_INFINITY to enable Infinity in JSON 2019-05-19 15:48:27 +02:00
7427888e05 Added ARDUINOJSON_ENABLE_NAN to enable NaN in JSON (closes #973) 2019-05-18 12:15:36 +02:00
90c1d549a8 Made deserializeJson() more picky about trailing characters (closes #980) 2019-05-16 20:41:07 +02:00
2af003e4e2 Fixed deserializeJson() silently accepting a Stream* (issue #978) 2019-05-09 08:33:09 +02:00
eaf55e174b Fixed invalid result from operator| (closes #981) 2019-05-07 08:12:18 +02:00
0588e578d5 Set version to 6.10.1 2019-04-23 08:47:54 +02:00
12f9aac4ea Fixed "no matching function for call to write(uint8_t)" (closes #972) 2019-04-23 08:46:18 +02:00
81bb3fce97 Fixed build on platformio 2019-04-21 14:35:23 +02:00
6011a2f51a Fixed deserializeJson() not being picky enough (fixes #969) 2019-04-21 14:35:13 +02:00
6071bd07ec Added a link to the FAQ 2019-04-20 12:10:29 +02:00
1c814d3bb6 Fixed warning on Clang 8 2019-03-24 19:39:23 +01:00
9862048a58 Fixed error "attributes are not allowed on a function-definition" 2019-03-24 19:00:23 +01:00
ebc52a5a65 Travis: Added Clang 8 2019-03-24 19:00:23 +01:00
eacad922df Travis: Added Clang 7 2019-03-24 19:00:23 +01:00
d910996613 Travis: Added GCC 8 2019-03-24 19:00:23 +01:00
2fc220fa33 Fixed code samples in the README 2019-03-24 18:21:58 +01:00
8cabda551d Fixed publish.sh not committing appveyor.yml 2019-03-22 22:04:03 +01:00
afd033e9c9 Set version to 6.10.0 2019-03-22 22:01:46 +01:00
6ec5ba521b Added JsonVariant::containsKey() 2019-03-22 21:58:12 +01:00
c8e49a7e4e Added JsonDocument::containsKey() (issue #938) 2019-03-22 08:40:46 +01:00
dee8c8e242 Added BasicJsonDocument to support custom allocator (issue #876) 2019-03-17 21:48:10 +01:00
576543c4b4 Added overflow handling in JsonVariant::as<T>() and JsonVariant::is<T>() 2019-03-06 15:31:37 +01:00
746f2882f7 Removed member call on null 2019-03-05 14:48:33 +01:00
c4cbf9d0bb Don't mark as a "system header" when debugging 2019-03-05 09:19:58 +01:00
49bd51b5f9 Updated version in AppVeyor 2019-03-04 12:21:58 +01:00
e53ae0f9bb Fixed the continuous integration 2019-03-04 12:18:11 +01:00
afdd913a2f Added links to the book page in each example 2019-03-04 12:17:41 +01:00
3df4efd512 Set version to 6.9.1 2019-03-01 18:16:45 +01:00
91dd45c387 Fixed naming conflict with "CAPACITY" (issue #839) 2019-03-01 18:14:23 +01:00
136ee0d576 Marked ArduinoJson.h as a "system header" 2019-03-01 17:31:55 +01:00
1ea8d92cc3 Muted warning "will change in GCC 7.1" (issue #914) 2019-03-01 12:12:47 +01:00
20fcb99830 Fixed warning "conversion may alter value" (issue #914) 2019-03-01 09:15:43 +01:00
f3265d2111 Fixed warning "cast-align" (issue #914) 2019-03-01 09:15:43 +01:00
d6e7709866 Travis: Add g++-arm-linux-gnueabihf 2019-03-01 09:15:43 +01:00
d11019d9e1 Travis: Split build and test scripts 2019-03-01 09:15:43 +01:00
cfd924622e Travis: Define CC and CXX in yaml 2019-03-01 09:15:41 +01:00
27c08b785d Travis: Assume CMake is installed 2019-02-28 17:33:24 +01:00
77f38e4449 Travis: restore build on GCC 4.4 2019-02-28 16:31:08 +01:00
16ddfbc4e0 Fixed strict-aliasing warning in FloatTraits.hpp 2019-02-28 15:37:42 +01:00
8dea900869 Travis: build in Release mode 2019-02-28 15:34:32 +01:00
f342dee2b4 Fixed warning "unused variable" with GCC 4.4 (issue #912) 2019-02-28 15:34:21 +01:00
1d5721f3bd Add an empty cpp file to detect warnings muted by catch.hpp 2019-02-28 15:32:29 +01:00
3170558d6d Added a clear error message for StaticJsonBuffer and DynamicJsonBuffer 2019-02-27 16:38:03 +01:00
3530aa88d6 Updated the examples on wandbox.org 2019-02-26 10:02:52 +01:00
21998890d4 Set version to 6.9.0 2019-02-26 08:43:45 +01:00
c9d6bd76c9 Added JsonDocument::remove() and JsonVariant::remove() 2019-02-25 13:21:10 +01:00
bc2ce178ea Added JsonVariant::clear() 2019-02-25 11:44:22 +01:00
e22e62d184 Added JsonDocument::size() 2019-02-25 11:07:01 +01:00
4181de119c Detect IncompleteInput in false, true, and null 2019-02-18 16:18:11 +01:00
56bf24e1ec Fixed JsonVariant::isNull() not returning true after set((char*)0) 2019-02-18 16:04:51 +01:00
e9b4c6289b Disambiguated the name get() with getElement() and getMember() 2019-02-15 15:53:53 +01:00
7ed92bebd3 Converted JsonArray::copyFrom()/copyTo() to free functions copyArray() 2019-02-15 15:33:04 +01:00
c3f71c1a99 Updated copyright year to 2019 2019-02-15 13:32:04 +01:00
7050ef675d Decode escaped Unicode characters like \u00DE (issue #304, PR #791) 2019-02-15 13:29:30 +01:00
070cd5b6c0 Added more tests of JsonVariant::is<T>() 2019-02-01 11:28:27 +01:00
2c2cc33c94 Updated version in Arduino Library badge 2019-01-30 16:42:21 +01:00
169c83431c Set version to 6.8.0-beta 2019-01-30 16:39:38 +01:00
5f72c68d87 Updated publish script for the "ardu-badge" 2019-01-30 15:23:55 +01:00
b184af6d00 User can now use a JsonString as a key or a value 2019-01-29 17:00:11 +01:00
6f55d1e58f JsonVariant automatically promotes to JsonObject or JsonArray on write 2019-01-29 14:09:09 +01:00
5aea1363cc Merge branch 'master' into 6.x 2019-01-24 21:07:02 +01:00
0685a36f0e Added ArduBadge badge 2019-01-24 20:55:55 +01:00
70739f5cfd Reduced the size of the pretty JSON serializer 2019-01-23 18:19:24 +01:00
933a66a070 Added JsonDocument::operator[] 2019-01-23 11:43:29 +01:00
4167b11434 Create or assign a JsonDocument from a JsonArray/JsonObject/JsonVariant 2019-01-23 10:47:20 +01:00
2a3b51ac3a Fixed uninitialized variant in JsonDocument 2019-01-20 14:35:22 +01:00
e633292df1 Replaced JsonDocument::nestingLimit with a param to deserializeJson() 2019-01-19 14:45:16 +01:00
30b94493bb Added nesting() to JsonArray, JsonDocument, JsonObject, and JsonVariant 2019-01-17 09:55:51 +01:00
c51cc91f92 Added memoryUsage() to JsonArray, JsonObject, and JsonVariant 2019-01-16 09:50:57 +01:00
8b04046321 Import JsonDocument into the ArduinoJson namespace 2019-01-15 12:04:48 +01:00
11bb5e26ff Fixed copying from JsonObjectConst and JsonArrayConst 2019-01-14 11:17:57 +01:00
9ac2ac303c Removed default capacity of DynamicJsonDocument 2019-01-14 10:32:19 +01:00
f0784d3b41 Simplified deserializeJson() and deserializeMsgPack() 2019-01-04 12:33:39 +01:00
3d8ece8c8b Improved syntax highlighting in Arduino IDE 2018-12-14 17:35:40 +01:00
b0fb71f7d8 Import functions in the ArduinoJson namespace to get clearer errors 2018-12-14 17:34:49 +01:00
a5cd1b1693 Set version to 6.7.0-beta 2018-12-07 12:23:02 +01:00
d8a1eec530 Renamed JsonKey to JsonString 2018-12-07 12:08:30 +01:00
e20c47c57b DynamicJsonDocument reallocates memory pool is it's too small 2018-12-07 10:38:58 +01:00
b77b203935 Extracted VariantData and CollectionData classes 2018-12-07 09:16:58 +01:00
1ad97ebf85 Merge branch 'master' into 6.x 2018-12-04 16:52:15 +01:00
ef12c74771 Set version to 5.13.4 2018-12-04 11:36:16 +01:00
0bc03e8071 Removed spurious files in the Particle library 2018-12-04 11:19:22 +01:00
04286f3228 Moved size measurements to github.com/bblanchon/ArduinoJson-size 2018-12-04 10:50:45 +01:00
1d942cdf41 Use singly-linked list to reduce memory usage 2018-12-01 12:05:51 +01:00
aaf0d5c3c5 Renamed and moved internal files 2018-11-30 17:53:54 +01:00
04e8acd844 Store offset between slots to reduce memory usage 2018-11-30 14:28:00 +01:00
8ff48dde73 Moved size measurements to github.com/bblanchon/ArduinoJson-size 2018-11-30 14:27:35 +01:00
41b2e629f7 Increased test coverage 2018-11-30 14:27:35 +01:00
a60162ba76 Removed the indirection via StringSlot 2018-11-30 14:27:35 +01:00
45f4e5ac20 Restored the monotonic allocator 2018-11-30 14:27:33 +01:00
637f7a5bfa Removed template parameter of CharPointerReader and StringMover 2018-11-16 16:24:36 +01:00
399ccec645 Added a CSV showing the evolution of the size of the sample programs 2018-11-16 15:08:53 +01:00
2bd280df80 Removed the automatic expansion of DynamicJsonDocument 2018-11-16 10:26:59 +01:00
c832edbda3 Added script to compile samples on wandbox.org 2018-11-14 18:02:01 +01:00
372 changed files with 10044 additions and 6895 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1 @@
custom: https://arduinojson.org/book/

View File

@ -2,122 +2,124 @@ sudo: false
language: cpp
matrix:
include:
- compiler: gcc
addons:
- addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.4']
env: SCRIPT=test _CC=gcc-4.4 _CXX=g++-4.4
- addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.6']
env: SCRIPT=cmake GCC=4.6
- compiler: gcc
addons:
env: SCRIPT=test _CC=gcc-4.6 _CXX=g++-4.6
- addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.7']
env: SCRIPT=cmake GCC=4.7
- compiler: gcc
addons:
env: SCRIPT=test _CC=gcc-4.7 _CXX=g++-4.7
- addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.8']
env: SCRIPT=cmake GCC=4.8 SANITIZE=address
- compiler: gcc
addons:
env: SCRIPT=test _CC=gcc-4.8 _CXX=g++-4.8 SANITIZE=address
- addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9']
env: SCRIPT=cmake GCC=4.9 SANITIZE=leak
- compiler: gcc
addons:
env: SCRIPT=test _CC=gcc-4.9 _CXX=g++-4.9 SANITIZE=leak
- addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5']
env: SCRIPT=cmake GCC=5 # SANITIZE=undefined
- compiler: gcc
addons:
env: SCRIPT=test _CC=gcc-5 _CXX=g++-5 # SANITIZE=undefined
- addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6']
env: SCRIPT=cmake GCC=6
- compiler: gcc
addons:
env: SCRIPT=test _CC=gcc-6 _CXX=g++-6
- addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-7']
env: SCRIPT=cmake GCC=7
- compiler: clang
env: SCRIPT=cmake
- compiler: clang
addons:
env: SCRIPT=test _CC=gcc-7 _CXX=g++-7
- addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-8']
env: SCRIPT=test _CC=gcc-8 _CXX=g++-8
- addons:
apt:
packages: ['g++-arm-linux-gnueabihf']
env: SCRIPT=build _CC=arm-linux-gnueabihf-gcc _CXX=arm-linux-gnueabihf-g++
- env: SCRIPT=test _CC=clang _CXX=clang++
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5']
packages: ['clang-3.5']
env: SCRIPT=cmake CLANG=3.5 SANITIZE=address
- compiler: clang
addons:
env: SCRIPT=test _CC=clang-3.5 _CXX=clang++-3.5 SANITIZE=address
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.6']
packages: ['clang-3.6']
env: SCRIPT=cmake CLANG=3.6 SANITIZE=leak
- compiler: clang
addons:
env: SCRIPT=test _CC=clang-3.6 _CXX=clang++-3.6 SANITIZE=leak
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.7']
packages: ['clang-3.7']
env: SCRIPT=cmake CLANG=3.7
- compiler: clang
addons:
env: SCRIPT=test _CC=clang-3.7 _CXX=clang++-3.7
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
packages: ['clang-3.8']
env: SCRIPT=cmake CLANG=3.8 SANITIZE=undefined
- compiler: clang
addons:
env: SCRIPT=test _CC=clang-3.8 _CXX=clang++-3.8 SANITIZE=undefined
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-3.9']
packages: ['clang-3.9']
env: SCRIPT=cmake CLANG=3.9
- compiler: clang
addons:
env: SCRIPT=test _CC=clang-3.9 _CXX=clang++-3.9
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-4.0']
packages: ['clang-4.0']
env: SCRIPT=cmake CLANG=4.0
- compiler: clang
addons:
env: SCRIPT=test _CC=clang-4.0 _CXX=clang++-4.0
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-5.0']
packages: ['clang-5.0']
env: SCRIPT=cmake CLANG=5.0
- compiler: clang
addons:
env: SCRIPT=test _CC=clang-5.0 _CXX=clang++-5.0
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
packages: ['clang-6.0']
env: SCRIPT=cmake CLANG=6.0
- compiler: gcc
env: SCRIPT=coverage
env: SCRIPT=test _CC=clang-6.0 _CXX=clang++-6.0
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-7']
packages: ['clang-7']
env: SCRIPT=test _CC=clang-7 _CXX=clang++-7
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-8']
packages: ['clang-8']
env: SCRIPT=test _CC=clang-8 _CXX=clang++-8
- env: SCRIPT=coverage
- os: osx
osx_image: xcode7.3
compiler: clang
env: SCRIPT=cmake
env: SCRIPT=test
- os: osx
osx_image: xcode8.3
compiler: clang
env: SCRIPT=cmake
env: SCRIPT=test
- os: osx
osx_image: xcode9.4
compiler: clang
env: SCRIPT=cmake
env: SCRIPT=test
- os: osx
osx_image: xcode10
compiler: clang
env: SCRIPT=cmake SANITIZE=address
env: SCRIPT=test SANITIZE=address
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:samd:mkr1000
- env: SCRIPT=platformio BOARD=uno
- env: SCRIPT=platformio BOARD=esp01
- compiler: clang
addons:
- addons:
apt:
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
packages: ['clang-6.0','llvm-6.0']

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#include "src/ArduinoJson.h"

View File

@ -1,6 +1,188 @@
ArduinoJson: change log
=======================
v6.11.1 (2019-06-21)
-------
* Fixed `serialized()` not working with Flash strings (issue #1030)
v6.11.0 (2019-05-26)
-------
* Fixed `deserializeJson()` silently accepting a `Stream*` (issue #978)
* Fixed invalid result from `operator|` (issue #981)
* Made `deserializeJson()` more picky about trailing characters (issue #980)
* Added `ARDUINOJSON_ENABLE_NAN` (default=0) to enable NaN in JSON (issue #973)
* Added `ARDUINOJSON_ENABLE_INFINITY` (default=0) to enable Infinity in JSON
* Removed implicit conversion in comparison operators (issue #998)
* Added lexicographical comparison for `JsonVariant`
* Added support for `nullptr` (issue #998)
> ### BREAKING CHANGES
>
> #### NaN and Infinity
>
> The JSON specification allows neither NaN not Infinity, but previous
> versions of ArduinoJson supported it. Now, ArduinoJson behaves like most
> other libraries: a NaN or and Infinity in the `JsonDocument`, becomes
> a `null` in the output JSON. Also, `deserializeJson()` returns
> `InvalidInput` if the JSON document contains NaN or Infinity.
>
> This version still supports NaN and Infinity in JSON documents, but
> it's disabled by default to be compatible with other JSON parsers.
> If you need the old behavior back, define `ARDUINOJSON_ENABLE_NAN` and
> `ARDUINOJSON_ENABLE_INFINITY` to `1`;:
>
> ```c++
> #define ARDUINOJSON_ENABLE_NAN 1
> #define ARDUINOJSON_ENABLE_INFINITY 1
> #include <ArduinoJson.h>
> ```
>
> #### The "or" operator
>
> This version slightly changes the behavior of the | operator when the
> variant contains a float and the user requests an integer.
>
> Older versions returned the floating point value truncated.
> Now, it returns the default value.
>
> ```c++
> // suppose variant contains 1.2
> int value = variant | 3;
>
> // old behavior:
> value == 1
>
> // new behavior
> value == 3
> ```
>
> If you need the old behavior, you must add `if (variant.is<float>())`.
v6.10.1 (2019-04-23)
-------
* Fixed error "attributes are not allowed on a function-definition"
* Fixed `deserializeJson()` not being picky enough (issue #969)
* Fixed error "no matching function for call to write(uint8_t)" (issue #972)
v6.10.0 (2019-03-22)
-------
* Fixed an integer overflow in the JSON deserializer
* Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`.
- `as<T>()` returns `0` if the integer `T` overflows
- `is<T>()` returns `false` if the integer `T` overflows
* Added `BasicJsonDocument` to support custom allocator (issue #876)
* Added `JsonDocument::containsKey()` (issue #938)
* Added `JsonVariant::containsKey()`
v6.9.1 (2019-03-01)
------
* Fixed warning "unused variable" with GCC 4.4 (issue #912)
* Fixed warning "cast increases required alignment" (issue #914)
* Fixed warning "conversion may alter value" (issue #914)
* Fixed naming conflict with "CAPACITY" (issue #839)
* Muted warning "will change in GCC 7.1" (issue #914)
* Added a clear error message for `StaticJsonBuffer` and `DynamicJsonBuffer`
* Marked ArduinoJson.h as a "system header"
v6.9.0 (2019-02-26)
------
* Decode escaped Unicode characters like \u00DE (issue #304, PR #791)
Many thanks to Daniel Schulte (aka @trilader) who implemented this feature.
* Added option ARDUINOJSON_DECODE_UNICODE to enable it
* Converted `JsonArray::copyFrom()/copyTo()` to free functions `copyArray()`
* Renamed `JsonArray::copyFrom()` and `JsonObject::copyFrom()` to `set()`
* Renamed `JsonArray::get()` to `getElement()`
* Renamed `JsonArray::add()` (without arg) to `addElement()`
* Renamed `JsonObject::get()` to `getMember()`
* Renamed `JsonObject::getOrCreate()` to `getOrAddMember()`
* Fixed `JsonVariant::isNull()` not returning `true` after `set((char*)0)`
* Fixed segfault after `variant.set(serialized((char*)0))`
* Detect `IncompleteInput` in `false`, `true`, and `null`
* Added `JsonDocument::size()`
* Added `JsonDocument::remove()`
* Added `JsonVariant::clear()`
* Added `JsonVariant::remove()`
v6.8.0-beta (2019-01-30)
-----------
* Import functions in the ArduinoJson namespace to get clearer errors
* Improved syntax highlighting in Arduino IDE
* Removed default capacity of `DynamicJsonDocument`
* `JsonArray::copyFrom()` accepts `JsonArrayConst`
* `JsonVariant::set()` accepts `JsonArrayConst` and `JsonObjectConst`
* `JsonDocument` was missing in the ArduinoJson namespace
* Added `memoryUsage()` to `JsonArray`, `JsonObject`, and `JsonVariant`
* Added `nesting()` to `JsonArray`, `JsonDocument`, `JsonObject`, and `JsonVariant`
* Replaced `JsonDocument::nestingLimit` with an additional parameter
to `deserializeJson()` and `deserializeMsgPack()`
* Fixed uninitialized variant in `JsonDocument`
* Fixed `StaticJsonDocument` copy constructor and copy assignment
* The copy constructor of `DynamicJsonDocument` chooses the capacity according to the memory usage of the source, not from the capacity of the source.
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
* Added `JsonDocument::isNull()`
* Added `JsonDocument::operator[]`
* Added `ARDUINOJSON_TAB` to configure the indentation character
* Reduced the size of the pretty JSON serializer
* Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant`
* `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write.
Calling `JsonVariant::to<T>()` is not required anymore.
* `JsonDocument` now support the same operations as `JsonVariant`.
Calling `JsonDocument::as<T>()` is not required anymore.
* Fixed example `JsonHttpClient.ino`
* User can now use a `JsonString` as a key or a value
> ### BREAKING CHANGES
>
> #### `DynamicJsonDocument`'s constructor
>
> The parameter to the constructor of `DynamicJsonDocument` is now mandatory
>
> Old code:
>
> ```c++
> DynamicJsonDocument doc;
> ```
>
> New code:
>
> ```c++
> DynamicJsonDocument doc(1024);
> ```
>
> #### Nesting limit
>
> `JsonDocument::nestingLimit` was replaced with a new parameter to `deserializeJson()` and `deserializeMsgPack()`.
>
> Old code:
>
> ```c++
> doc.nestingLimit = 15;
> deserializeJson(doc, input);
> ```
>
> New code:
>
> ```c++
> deserializeJson(doc, input, DeserializationOption::NestingLimit(15));
> ```
v6.7.0-beta (2018-12-07)
-----------
* Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity.
* Restored the monotonic allocator because the code was getting too big
* Reduced the memory usage
* Reduced the code size
* Renamed `JsonKey` to `JsonString`
* Removed spurious files in the Particle library
v6.6.0-beta (2018-11-13)
-----------
@ -9,7 +191,7 @@ v6.6.0-beta (2018-11-13)
* 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
* ~~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)

View File

@ -1,5 +1,5 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2018
# Copyright Benoit Blanchon 2014-2019
# MIT License
cmake_minimum_required(VERSION 3.0)
@ -7,8 +7,8 @@ project(ArduinoJson)
enable_testing()
add_definitions(-DARDUINOJSON_DEBUG)
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_definitions(-DARDUINOJSON_DEBUG)
add_compile_options(-g -O0)
endif()

View File

@ -1,7 +1,7 @@
The MIT License (MIT)
---------------------
Copyright © 2014-2018 Benoit BLANCHON
Copyright © 2014-2019 Benoit BLANCHON
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -2,7 +2,11 @@
---
[![Build status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=6.x) [![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.11.1)](https://www.ardu-badge.com/ArduinoJson/6.11.1)
[![Build Status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson)
[![Coverage Status](https://coveralls.io/repos/github/bblanchon/ArduinoJson/badge.svg?branch=6.x)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
[![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
@ -60,14 +64,13 @@ Here is a program that parses a JSON document with ArduinoJson.
```c++
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
deserializeJson(doc, json);
JsonObjectRef root = doc.as<JsonObject>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
const char* sensor = doc["sensor"];
long time = doc["time"];
double latitude = doc["data"][0];
double longitude = doc["data"][1];
```
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme)
@ -77,13 +80,12 @@ See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_
Here is a program that generates a JSON document with ArduinoJson:
```c++
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
JsonObject root = doc.to<JsonObject>();
root["sensor"] = "gps";
root["time"] = 1351824120;
doc["sensor"] = "gps";
doc["time"] = 1351824120;
JsonArray data = root.createNestedArray("data");
JsonArray data = doc.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);

View File

@ -1,4 +1,4 @@
version: 6.4.0.{build}
version: 6.11.1.{build}
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
@ -17,4 +17,4 @@ before_build:
build_script:
- cmake --build . --config %CONFIGURATION%
test_script:
- ctest --output-on-failure .
- ctest -C %CONFIGURATION% --output-on-failure .

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to store your project configuration in a file.
@ -10,12 +10,19 @@
// "hostname": "examples.com",
// "port": 2731
// }
//
// https://arduinojson.org/v6/example/config/
#include <ArduinoJson.h>
#include <SD.h>
#include <SPI.h>
// Configuration that we'll store on disk
// Our configuration structure.
//
// Never use a JsonDocument to store the configuration!
// A JsonDocument is *not* a permanent storage; it's only a temporary storage
// used during the serialization phase. See:
// https://arduinojson.org/v6/faq/why-must-i-create-a-separate-config-object/
struct Config {
char hostname[64];
int port;
@ -29,9 +36,9 @@ void loadConfiguration(const char *filename, Config &config) {
// Open file for reading
File file = SD.open(filename);
// Allocate the document on the stack.
// Allocate a temporary JsonDocument
// Don't forget to change the capacity to match your requirements.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<512> doc;
// Deserialize the JSON document
@ -39,16 +46,13 @@ void loadConfiguration(const char *filename, Config &config) {
if (error)
Serial.println(F("Failed to read file, using default configuration"));
// Get the root object in the document
JsonObject root = doc.as<JsonObject>();
// Copy values from the JsonDocument to the Config
config.port = doc["port"] | 2731;
strlcpy(config.hostname, // <- destination
doc["hostname"] | "example.com", // <- source
sizeof(config.hostname)); // <- destination's capacity
// Copy values from the JsonObject to the Config
config.port = root["port"] | 2731;
strlcpy(config.hostname, // <- destination
root["hostname"] | "example.com", // <- source
sizeof(config.hostname)); // <- destination's capacity
// Close the file (File's destructor doesn't close the file)
// Close the file (Curiously, File's destructor doesn't close the file)
file.close();
}
@ -64,24 +68,21 @@ void saveConfiguration(const char *filename, const Config &config) {
return;
}
// Allocate the document on the stack.
// Allocate a temporary JsonDocument
// Don't forget to change the capacity to match your requirements.
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonDocument<256> doc;
// Make our document contain an object
JsonObject root = doc.to<JsonObject>();
// Set the values in the object
root["hostname"] = config.hostname;
root["port"] = config.port;
// Set the values in the document
doc["hostname"] = config.hostname;
doc["port"] = config.port;
// Serialize JSON to file
if (serializeJson(doc, file) == 0) {
Serial.println(F("Failed to write to file"));
}
// Close the file (File's destructor doesn't close the file)
// Close the file
file.close();
}
@ -100,7 +101,7 @@ void printFile(const char *filename) {
}
Serial.println();
// Close the file (File's destructor doesn't close the file)
// Close the file
file.close();
}
@ -132,4 +133,15 @@ void loop() {
// not used in this example
}
// Visit https://arduinojson.org/v6/example/config/ for more.
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization or deserialization problem.
//
// The book "Mastering ArduinoJson" contains a case study of a project that has
// a complex configuration with nested members.
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤

View File

@ -1,8 +1,10 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to generate a JSON document with ArduinoJson.
//
// https://arduinojson.org/v6/example/generator/
#include <ArduinoJson.h>
@ -15,7 +17,7 @@ void setup() {
//
// Inside the brackets, 200 is the RAM allocated to this document.
// Don't forget to change this value to match your requirement.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be
@ -23,30 +25,30 @@ void setup() {
//
// DynamicJsonDocument doc(200);
// Make our document be an object
JsonObject root = doc.to<JsonObject>();
// Add values in the object
// Add values in the document
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root.set<long>("time", 1351824120);
root["sensor"] = "gps";
root["time"] = 1351824120;
doc["sensor"] = "gps";
doc["time"] = 1351824120;
// Add an array.
//
JsonArray data = root.createNestedArray("data");
JsonArray data = doc.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
serializeJson(root, Serial);
// This prints:
// Generate the minified JSON and send it to the Serial port.
//
serializeJson(doc, Serial);
// The above line prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
// Start a new line
Serial.println();
serializeJsonPretty(root, Serial);
// This prints:
// Generate the prettified JSON and send it to the Serial port.
//
serializeJsonPretty(doc, Serial);
// The above line prints:
// {
// "sensor": "gps",
// "time": 1351824120,
@ -61,4 +63,15 @@ void loop() {
// not used in this example
}
// Visit https://arduinojson.org/v6/example/generator/ for more.
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
// It begins with a simple example, like the one above, and then adds more
// features like serializing directly to a file or an HTTP request.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to parse a JSON document in an HTTP response.
@ -15,6 +15,8 @@
// 2.302038
// ]
// }
//
// https://arduinojson.org/v6/example/http-client/
#include <ArduinoJson.h>
#include <Ethernet.h>
@ -57,7 +59,8 @@ void setup() {
// Check HTTP status
char status[32] = {0};
client.readBytesUntil('\r', status, sizeof(status));
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
// It should be "HTTP/1.0 200 OK" or "HTTP/1.1 200 OK"
if (strcmp(status + 9, "200 OK") != 0) {
Serial.print(F("Unexpected response: "));
Serial.println(status);
return;
@ -71,7 +74,7 @@ void setup() {
}
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
DynamicJsonDocument doc(capacity);
@ -84,12 +87,11 @@ void setup() {
}
// Extract values
JsonObject root = doc.as<JsonObject>();
Serial.println(F("Response:"));
Serial.println(root["sensor"].as<char*>());
Serial.println(root["time"].as<char*>());
Serial.println(root["data"][0].as<char*>());
Serial.println(root["data"][1].as<char*>());
Serial.println(doc["sensor"].as<char*>());
Serial.println(doc["time"].as<long>());
Serial.println(doc["data"][0].as<float>(), 6);
Serial.println(doc["data"][1].as<float>(), 6);
// Disconnect
client.stop();
@ -99,4 +101,16 @@ void loop() {
// not used in this example
}
// Visit https://arduinojson.org/v6/example/http-client/ for more.
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on deserialization
// showing how to parse the response from GitHub's API. In the last chapter,
// it shows how to parse the huge documents from OpenWeatherMap
// and Reddit.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤

View File

@ -1,8 +1,10 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to deserialize a JSON document with ArduinoJson.
//
// https://arduinojson.org/v6/example/parser/
#include <ArduinoJson.h>
@ -13,9 +15,9 @@ void setup() {
// Allocate the JSON document
//
// Inside the brackets, 200 is the size of the memory pool in bytes.
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonDocument<N> allocates memory on the stack, it can be
@ -25,9 +27,12 @@ void setup() {
// JSON input string.
//
// It's better to use a char[] as shown here.
// If you use a const char* or a String, ArduinoJson will
// have to make a copy of the input in the JsonBuffer.
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
// the minimal amount of memory because the JsonDocument stores pointers to
// the input buffer.
// If you use another type of input, ArduinoJson must copy the strings from
// the input to the JsonDocument, so you need to increase the capacity of the
// JsonDocument.
char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
@ -41,17 +46,14 @@ void setup() {
return;
}
// Get the root object in the document
JsonObject root = doc.as<JsonObject>();
// Fetch values.
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root["time"].as<long>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
// In other case, you can do doc["time"].as<long>();
const char* sensor = doc["sensor"];
long time = doc["time"];
double latitude = doc["data"][0];
double longitude = doc["data"][1];
// Print values.
Serial.println(sensor);
@ -64,4 +66,15 @@ void loop() {
// not used in this example
}
// Visit https://arduinojson.org/v6/example/parser/ for more.
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// deserialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
// It begins with a simple example, like the one above, and then adds more
// features like deserializing directly from a file or an HTTP request.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤

View File

@ -1,17 +1,19 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to implement an HTTP server that sends JSON document
// in the responses.
// This example shows how to implement an HTTP server that sends a JSON document
// in the response.
// It uses the Ethernet library but can be easily adapted for Wifi.
//
// It sends the value of the analog and digital pins.
// The JSON document looks like the following:
// The JSON document contains the values of the analog and digital pins.
// It looks like that:
// {
// "analog": [ 0, 1, 2, 3, 4, 5 ],
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
// "analog": [0, 76, 123, 158, 192, 205],
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
// }
//
// https://arduinojson.org/v6/example/http-server/
#include <ArduinoJson.h>
#include <Ethernet.h>
@ -51,15 +53,12 @@ void loop() {
// Read the request (we ignore the content in this example)
while (client.available()) client.read();
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
// Allocate a temporary JsonDocument
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<500> doc;
// Make our document represent an object
JsonObject root = doc.to<JsonObject>();
// Create the "analog" array
JsonArray analogValues = root.createNestedArray("analog");
JsonArray analogValues = doc.createNestedArray("analog");
for (int pin = 0; pin < 6; pin++) {
// Read the analog input
int value = analogRead(pin);
@ -69,7 +68,7 @@ void loop() {
}
// Create the "digital" array
JsonArray digitalValues = root.createNestedArray("digital");
JsonArray digitalValues = doc.createNestedArray("digital");
for (int pin = 0; pin < 14; pin++) {
// Read the digital input
int value = digitalRead(pin);
@ -79,20 +78,33 @@ void loop() {
}
Serial.print(F("Sending: "));
serializeJson(root, Serial);
serializeJson(doc, Serial);
Serial.println();
// Write response headers
client.println("HTTP/1.0 200 OK");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.println(F("HTTP/1.0 200 OK"));
client.println(F("Content-Type: application/json"));
client.println(F("Connection: close"));
client.print(F("Content-Length: "));
client.println(measureJsonPretty(doc));
client.println();
// Write JSON document
serializeJsonPretty(root, client);
serializeJsonPretty(doc, client);
// Disconnect
client.stop();
}
// Visit https://arduinojson.org/v6/example/http-server/ for more.
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
// It begins with a simple example, then adds more features like serializing
// directly to a file or an HTTP client.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤

View File

@ -1,14 +1,14 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to send a JSON document to a UDP socket.
// At regular interval, it sends a UDP packet that contains the status of
// analog and digital pins.
// The JSON document looks like the following:
// It looks like that:
// {
// "analog": [ 0, 1, 2, 3, 4, 5 ],
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
// "analog": [0, 76, 123, 158, 192, 205],
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
// }
//
// If you want to test this program, you need to be able to receive the UDP
@ -16,6 +16,8 @@
// For example, you can run netcat on your computer
// $ ncat -ulp 8888
// See https://nmap.org/ncat/
//
// https://arduinojson.org/v6/example/udp-beacon/
#include <ArduinoJson.h>
#include <Ethernet.h>
@ -43,15 +45,12 @@ void setup() {
}
void loop() {
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
// Allocate a temporary JsonDocument
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<500> doc;
// Make our document represent an object
JsonObject root = doc.to<JsonObject>();
// Create the "analog" array
JsonArray analogValues = root.createNestedArray("analog");
JsonArray analogValues = doc.createNestedArray("analog");
for (int pin = 0; pin < 6; pin++) {
// Read the analog input
int value = analogRead(pin);
@ -61,7 +60,7 @@ void loop() {
}
// Create the "digital" array
JsonArray digitalValues = root.createNestedArray("digital");
JsonArray digitalValues = doc.createNestedArray("digital");
for (int pin = 0; pin < 14; pin++) {
// Read the digital input
int value = digitalRead(pin);
@ -75,11 +74,11 @@ void loop() {
Serial.print(remoteIp);
Serial.print(F(" on port "));
Serial.println(remotePort);
serializeJson(root, Serial);
serializeJson(doc, Serial);
// Send UDP packet
udp.beginPacket(remoteIp, remotePort);
serializeJson(root, udp);
serializeJson(doc, udp);
udp.println();
udp.endPacket();
@ -87,4 +86,15 @@ void loop() {
delay(10000);
}
// Visit https://arduinojson.org/v6/example/udp-beacon/ for more.
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
// It begins with a simple example, then adds more features like serializing
// directly to a file or any stream.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤

View File

@ -1,9 +1,11 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to deserialize a MessagePack document with
// ArduinoJson.
//
// https://arduinojson.org/v6/example/msgpack-parser/
#include <ArduinoJson.h>
@ -14,9 +16,9 @@ void setup() {
// Allocate the JSON document
//
// Inside the brackets, 200 is the size of the memory pool in bytes.
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be
@ -26,9 +28,12 @@ void setup() {
// MessagePack input string.
//
// It's better to use a char[] as shown here.
// If you use a const char* or a String, ArduinoJson will
// have to make a copy of the input in the JsonBuffer.
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
// the minimal amount of memory because the JsonDocument stores pointers to
// the input buffer.
// If you use another type of input, ArduinoJson must copy the strings from
// the input to the JsonDocument, so you need to increase the capacity of the
// JsonDocument.
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
@ -40,31 +45,23 @@ void setup() {
// "data": [48.75608, 2.302038]
// }
// doc of the object tree.
//
// It's a reference to the JsonObject, the actual bytes are inside the
// JsonBuffer with all the other nodes of the object tree.
// Memory is freed when jsonBuffer goes out of scope.
DeserializationError error = deserializeMsgPack(doc, input);
// Test if parsing succeeds.
// Test if parsing succeeded.
if (error) {
Serial.print("deserializeMsgPack() failed: ");
Serial.println(error.c_str());
return;
}
// Get the root object in the document
JsonObject root = doc.as<JsonObject>();
// Fetch values.
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root["time"].as<long>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
// In other case, you can do doc["time"].as<long>();
const char* sensor = doc["sensor"];
long time = doc["time"];
double latitude = doc["data"][0];
double longitude = doc["data"][1];
// Print values.
Serial.println(sensor);
@ -76,5 +73,3 @@ void setup() {
void loop() {
// not used in this example
}
// Visit https://arduinojson.org/v6/example/msgpack-parser/ for more.

View File

@ -1,24 +1,25 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows the different ways you can use Flash strings with
// ArduinoJson.
//
// Use Flash strings sparingly, because ArduinoJson duplicates them in the
// JsonBuffer. Prefer plain old char*, as they are more efficient in term of
// JsonDocument. Prefer plain old char*, as they are more efficient in term of
// code size, speed, and memory usage.
//
// https://arduinojson.org/v6/example/progmem/
#include <ArduinoJson.h>
void setup() {
#ifdef PROGMEM // <- check that Flash strings are supported
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
// You can use a Flash String as your JSON input.
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
// WARNING: the strings in the input will be duplicated in the JsonDocument.
deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120,"
"\"data\":[48.756080,2.302038]}"));
JsonObject obj = doc.as<JsonObject>();
@ -29,12 +30,12 @@ void setup() {
// You can use a Flash String to set an element of a JsonObject
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
// JsonDocument.
obj[F("time")] = time;
// You can set a Flash String to a JsonObject or JsonArray:
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
// JsonDocument.
obj["sensor"] = F("gps");
// It works with serialized() too:
@ -57,4 +58,15 @@ void loop() {
// not used in this example
}
// Visit https://arduinojson.org/v6/example/progmem/ for more.
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any memory
// problem.
//
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
// how your microcontroller stores strings in memory. It also tells why you
// should not abuse Flash strings with ArduinoJson.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤

View File

@ -1,20 +1,22 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows the different ways you can use String with ArduinoJson.
//
// Use String objects sparingly, because ArduinoJson duplicates them in the
// JsonBuffer. Prefer plain old char[], as they are more efficient in term of
// JsonDocument. Prefer plain old char[], as they are more efficient in term of
// code size, speed, and memory usage.
//
// https://arduinojson.org/v6/example/string/
#include <ArduinoJson.h>
void setup() {
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
// You can use a String as your JSON input.
// WARNING: the content of the String will be duplicated in the JsonBuffer.
// WARNING: the string in the input will be duplicated in the JsonDocument.
String input =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
deserializeJson(doc, input);
@ -25,11 +27,11 @@ void setup() {
long time = obj[String("time")];
// You can use a String to set an element of a JsonObject
// WARNING: the content of the String will be duplicated in the JsonBuffer.
// WARNING: the content of the String will be duplicated in the JsonDocument.
obj[String("time")] = time;
// You can get a String from a JsonObject or JsonArray:
// No duplication is done, at least not in the JsonBuffer.
// No duplication is done, at least not in the JsonDocument.
String sensor = obj["sensor"];
// Unfortunately, the following doesn't work (issue #118):
@ -38,14 +40,14 @@ void setup() {
sensor = obj["sensor"].as<String>();
// You can set a String to a JsonObject or JsonArray:
// WARNING: the content of the String will be duplicated in the JsonBuffer.
// WARNING: the content of the String will be duplicated in the JsonDocument.
obj["sensor"] = sensor;
// It works with serialized() too:
obj["sensor"] = serialized(sensor);
// You can also concatenate strings
// WARNING: the content of the String will be duplicated in the JsonBuffer.
// WARNING: the content of the String will be duplicated in the JsonDocument.
obj[String("sen") + "sor"] = String("gp") + "s";
// You can compare the content of a JsonObject with a String
@ -62,4 +64,14 @@ void loop() {
// not used in this example
}
// Visit https://arduinojson.org/v6/example/string/ for more.
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any problem.
//
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
// how your microcontroller stores strings in memory. On several occasions, it
// shows how you can avoid String in your program.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤

View File

@ -1,7 +1,11 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2018
# Copyright Benoit Blanchon 2014-2019
# MIT License
if(MSVC)
add_compile_options(-D_CRT_SECURE_NO_WARNINGS)
endif()
add_executable(msgpack_fuzzer
msgpack_fuzzer.cpp
fuzzer_main.cpp

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
// This file is NOT use by Google's OSS fuzz

View File

@ -1,7 +1,7 @@
#include <ArduinoJson.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeJson(doc, data, size);
if (!error) {
std::string json;

View File

@ -0,0 +1 @@
9720730739393920739

View File

@ -1,7 +1,7 @@
#include <ArduinoJson.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeMsgPack(doc, data, size);
if (!error) {
std::string json;

View File

@ -1,17 +1,36 @@
# Macros
JSON_ARRAY_SIZE KEYWORD2
JSON_OBJECT_SIZE KEYWORD2
JSON_STRING_SIZE KEYWORD2
# Free functions
deserializeJson KEYWORD2
deserializeMsgPack KEYWORD2
serialized KEYWORD2
serializeJson KEYWORD2
serializeJsonPretty KEYWORD2
serializeMsgPack KEYWORD2
# Methods
add KEYWORD2
as KEYWORD2
createNestedArray KEYWORD2
createNestedObject KEYWORD2
deserializeJson KEYWORD2
deserializeMsgPack KEYWORD2
DynamicJsonDocument KEYWORD1
get KEYWORD2
JsonArray KEYWORD1
JsonObject KEYWORD1
JsonVariant KEYWORD1
serializeMsgPack KEYWORD2
serializeJson KEYWORD2
serializeJsonPretty KEYWORD2
set KEYWORD2
StaticJsonDocument KEYWORD1
to KEYWORD2
# Type names
DeserializationError KEYWORD1 DATA_TYPE
DynamicJsonDocument KEYWORD1 DATA_TYPE
JsonArray KEYWORD1 DATA_TYPE
JsonArrayConst KEYWORD1 DATA_TYPE
JsonFloat KEYWORD1 DATA_TYPE
JsonInteger KEYWORD1 DATA_TYPE
JsonObject KEYWORD1 DATA_TYPE
JsonObjectConst KEYWORD1 DATA_TYPE
JsonString KEYWORD1 DATA_TYPE
JsonUInt KEYWORD1 DATA_TYPE
JsonVariant KEYWORD1 DATA_TYPE
JsonVariantConst KEYWORD1 DATA_TYPE
StaticJsonDocument KEYWORD1 DATA_TYPE

View File

@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"version": "6.6.0-beta",
"version": "6.11.1",
"authors": {
"name": "Benoit Blanchon",
"url": "https://blog.benoitblanchon.fr"

View File

@ -1,5 +1,5 @@
name=ArduinoJson
version=6.6.0-beta
version=6.11.1
author=Benoit Blanchon <blog.benoitblanchon.fr>
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
sentence=An efficient and elegant JSON library for Arduino.

View File

@ -1,42 +0,0 @@
#!/bin/bash
set -eu
OUTPUT="$(pwd)/sizes.csv"
echo "Tag;Date;Parser;Generator" > $OUTPUT
cd $(dirname $(dirname $0))
git tag | while read TAG
do
git checkout -q tags/$TAG
DATE=$(git log -1 --date=short --pretty=format:%cd)
PARSER_SIZE=$(arduino --verify examples/JsonParserExample/JsonParserExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
if [ -e 'examples/JsonGeneratorExample/JsonGeneratorExample.ino' ]; then
GENERATOR_SIZE=$(arduino --verify examples/JsonGeneratorExample/JsonGeneratorExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
else
GENERATOR_SIZE=""
fi
echo $TAG
if [ ! -z "$PARSER_SIZE" ]
then
echo "JsonParserExample = $PARSER_SIZE bytes"
else
echo "JsonParserExample compilation failed."
fi
if [ ! -z "$GENERATOR_SIZE" ]
then
echo "JsonGeneratorExample = $GENERATOR_SIZE bytes"
else
echo "JsonGeneratorExample compilation failed."
fi
echo "$TAG;$DATE;$PARSER_SIZE;$GENERATOR_SIZE" >> $OUTPUT
done

View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -eu
SOURCE_DIR="$(dirname "$0")/.."
WORK_DIR=$(mktemp -d)
trap 'rm -rf "$WORK_DIR"' EXIT
cp "$SOURCE_DIR/README.md" "$WORK_DIR/README.md"
cp "$SOURCE_DIR/CHANGELOG.md" "$WORK_DIR/CHANGELOG.md"
cp "$SOURCE_DIR/library.properties" "$WORK_DIR/library.properties"
cp "$SOURCE_DIR/LICENSE.md" "$WORK_DIR/LICENSE.txt"
cp -r "$SOURCE_DIR/src" "$WORK_DIR/"
cp -r "$SOURCE_DIR/examples" "$WORK_DIR/"
cd "$WORK_DIR"
particle library upload
particle library publish

View File

@ -7,19 +7,27 @@ cd "$(dirname "$0")/.."
VERSION="$1"
DATE=$(date +%F)
TAG="v$VERSION"
VERSION_REGEX="[0-9a-z\\.\\-]+"
update_version_in_source () {
IFS=".-" read MAJOR MINOR REVISION EXTRA < <(echo "$VERSION")
UNDERLINE=$(printf -- '-%.0s' $(seq 1 ${#TAG}))
sed -i~ -bE "s/version=$VERSION_REGEX/version=$VERSION/; s|ardu-badge.com/ArduinoJson/$VERSION_REGEX|ardu-badge.com/ArduinoJson/$VERSION|; " README.md
rm README.md*~
sed -i~ -bE "4s/HEAD/$TAG ($DATE)/; 5s/-+/$UNDERLINE/" CHANGELOG.md
rm CHANGELOG.md*~
sed -i~ -bE "s/\"version\":.*$/\"version\": \"$VERSION\",/" library.json
rm library.json*~
sed -i~ -bE "s/version=.*$/version=$VERSION/" library.properties
rm library.properties*~
sed -i~ -bE "s/version: .*$/version: $VERSION.{build}/" appveyor.yml
rm appveyor.yml*~
sed -i~ -bE \
-e "s/ARDUINOJSON_VERSION .*$/ARDUINOJSON_VERSION \"$VERSION\"/" \
-e "s/ARDUINOJSON_VERSION_MAJOR .*$/ARDUINOJSON_VERSION_MAJOR $MAJOR/" \
@ -30,7 +38,7 @@ update_version_in_source () {
}
commit_new_version () {
git add src/ArduinoJson/version.hpp CHANGELOG.md library.json library.properties
git add src/ArduinoJson/version.hpp README.md CHANGELOG.md library.json library.properties appveyor.yml
git commit -m "Set version to $VERSION"
}
@ -47,3 +55,7 @@ update_version_in_source
commit_new_version
add_tag
push
scripts/build-arduino-package.sh
scripts/build-single-header.sh
scripts/wandbox/publish.sh "../ArduinoJson-$TAG.h"

14
scripts/travis/build.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh -ex
export CC="$_CC"
export CXX="$_CXX"
if [ -n "$SANITIZE" ]; then
export CXXFLAGS="-fsanitize=$SANITIZE"
BUILD_TYPE="Debug"
else
BUILD_TYPE="Release"
fi
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .
cmake --build .

View File

@ -1,30 +0,0 @@
#!/bin/sh -ex
if [ $(uname) = 'Darwin' ]; then
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Darwin-x86_64.tar.gz
CMAKE=/tmp/CMake.app/Contents/bin/cmake
CTEST=/tmp/CMake.app/Contents/bin/ctest
else
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.tar.gz
CMAKE=/tmp/bin/cmake
CTEST=/tmp/bin/ctest
fi
curl -sS $URL | tar xz -C /tmp --strip 1
if [ -n "$GCC" ]; then
export CC="gcc-$GCC"
export CXX="g++-$GCC"
fi
if [ -n "$CLANG" ]; then
export CC="clang-$CLANG"
export CXX="clang++-$CLANG"
fi
if [ -n "$SANITIZE" ]; then
export CXXFLAGS="-fsanitize=$SANITIZE"
fi
$CMAKE .
$CMAKE --build .
$CTEST --output-on-failure .

View File

@ -1,8 +1,6 @@
#!/bin/sh -eux
curl https://cmake.org/files/v3.4/cmake-3.4.0-Linux-x86_64.tar.gz | tar xz -C /tmp --strip 1
/tmp/bin/cmake -DCOVERAGE=true .
cmake -DCOVERAGE=true .
make
make test

View File

@ -3,7 +3,7 @@
ROOT_DIR=$(dirname $0)/../../
INCLUDE_DIR=${ROOT_DIR}/src/
FUZZING_DIR=${ROOT_DIR}/fuzzing/
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,fuzzer"
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,undefined,fuzzer -fno-sanitize-recover=all"
fuzz() {
NAME="$1"

View File

@ -4,6 +4,18 @@ pip install --user platformio
rm -r test
case $BOARD in
uno)
platformio lib install 868 # SD library
platformio lib install 872 # Ethernet library
;;
esp01)
platformio lib uninstall 161 || true
platformio lib uninstall 868 || true
platformio lib uninstall 872 || true
;;
esac
for EXAMPLE in $PWD/examples/*/*.ino;
do
platformio ci $EXAMPLE -l '.' -b $BOARD

4
scripts/travis/test.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh -ex
"$(dirname "$0")/build.sh"
ctest --output-on-failure .

View File

@ -0,0 +1,60 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to generate a JSON document with ArduinoJson.
#include <iostream>
#include "ArduinoJson.h"
int main() {
// Allocate the JSON document
//
// Inside the brackets, 200 is the RAM allocated to this document.
// Don't forget to change this value to match your requirement.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be
// replaced by DynamicJsonDocument which allocates in the heap.
//
// DynamicJsonDocument doc(200);
// StaticJsonObject allocates memory on the stack, it can be
// replaced by DynamicJsonDocument which allocates in the heap.
//
// DynamicJsonDocument doc(200);
// Add values in the document
//
doc["sensor"] = "gps";
doc["time"] = 1351824120;
// Add an array.
//
JsonArray data = doc.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
// Generate the minified JSON and send it to STDOUT
//
serializeJson(doc, std::cout);
// The above line prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
// Start a new line
std::cout << std::endl;
// Generate the prettified JSON and send it to STDOUT
//
serializeJsonPretty(doc, std::cout);
// The above line prints:
// {
// "sensor": "gps",
// "time": 1351824120,
// "data": [
// 48.756080,
// 2.302038
// ]
// }
}

View File

@ -0,0 +1,59 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to deserialize a JSON document with ArduinoJson.
#include <iostream>
#include "ArduinoJson.h"
int main() {
// Allocate the JSON document
//
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<300> doc;
// StaticJsonDocument<N> allocates memory on the stack, it can be
// replaced by DynamicJsonDocument which allocates in the heap.
//
// DynamicJsonDocument doc(200);
// JSON input string.
//
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
// the minimal amount of memory because the JsonDocument stores pointers to
// the input buffer.
// If you use another type of input, ArduinoJson must copy the strings from
// the input to the JsonDocument, so you need to increase the capacity of the
// JsonDocument.
char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
// Deserialize the JSON document
DeserializationError error = deserializeJson(doc, json);
// Test if parsing succeeds.
if (error) {
std::cerr << "deserializeJson() failed: " << error.c_str() << std::endl;
return 1;
}
// Fetch values.
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do doc["time"].as<long>();
const char* sensor = doc["sensor"];
long time = doc["time"];
double latitude = doc["data"][0];
double longitude = doc["data"][1];
// Print values.
std::cout << sensor << std::endl;
std::cout << time << std::endl;
std::cout << latitude << std::endl;
std::cout << longitude << std::endl;
return 0;
}

View File

@ -0,0 +1,68 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to generate a JSON document with ArduinoJson.
#include <iostream>
#include "ArduinoJson.h"
int main() {
// Allocate the JSON document
//
// Inside the brackets, 300 is the size of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonDocument<300> doc;
// StaticJsonObject allocates memory on the stack, it can be
// replaced by DynamicJsonObject which allocates in the heap.
//
// DynamicJsonObject doc(200);
// MessagePack input string.
//
// It's better to use a char[] as shown here.
// If you use a const char* or a String, ArduinoJson will
// have to make a copy of the input in the JsonBuffer.
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
112, 203, 64, 2, 106, 146, 230, 33, 49, 169};
// This MessagePack document contains:
// {
// "sensor": "gps",
// "time": 1351824120,
// "data": [48.75608, 2.302038]
// }
// doc of the object tree.
//
// It's a reference to the JsonObject, the actual bytes are inside the
// JsonBuffer with all the other nodes of the object tree.
// Memory is freed when jsonBuffer goes out of scope.
DeserializationError error = deserializeMsgPack(doc, input);
// Test if parsing succeeds.
if (error) {
std::cerr << "deserializeMsgPack() failed: " << error.c_str() << std::endl;
return 1;
}
// Fetch values.
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do doc["time"].as<long>();
const char* sensor = doc["sensor"];
long time = doc["time"];
double latitude = doc["data"][0];
double longitude = doc["data"][1];
// Print values.
std::cout << sensor << std::endl;
std::cout << time << std::endl;
std::cout << latitude << std::endl;
std::cout << longitude << std::endl;
return 0;
}

View 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"

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once

View File

@ -1,22 +1,34 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#ifndef ARDUINOJSON_DEBUG
#ifdef __clang__
#pragma clang system_header
#elif defined __GNUC__
#pragma GCC system_header
#endif
#endif
#include "ArduinoJson/Namespace.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonDocument.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/JsonVariant.hpp"
#include "ArduinoJson/Array/ArrayRef.hpp"
#include "ArduinoJson/Object/ObjectRef.hpp"
#include "ArduinoJson/Variant/VariantRef.hpp"
#include "ArduinoJson/Data/VariantAsImpl.hpp"
#include "ArduinoJson/JsonArrayImpl.hpp"
#include "ArduinoJson/JsonArraySubscript.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/JsonObjectSubscript.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp"
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
#include "ArduinoJson/Array/ArrayImpl.hpp"
#include "ArduinoJson/Array/ElementProxy.hpp"
#include "ArduinoJson/Array/Utilities.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Object/MemberProxy.hpp"
#include "ArduinoJson/Object/ObjectImpl.hpp"
#include "ArduinoJson/Variant/VariantAsImpl.hpp"
#include "ArduinoJson/Variant/VariantImpl.hpp"
#include "ArduinoJson/Json/JsonDeserializer.hpp"
#include "ArduinoJson/Json/JsonSerializer.hpp"
@ -24,20 +36,34 @@
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
#include "ArduinoJson/compatibility.hpp"
namespace ArduinoJson {
typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
typedef ARDUINOJSON_NAMESPACE::String JsonString;
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
using ARDUINOJSON_NAMESPACE::BasicJsonDocument;
using ARDUINOJSON_NAMESPACE::copyArray;
using ARDUINOJSON_NAMESPACE::DeserializationError;
using ARDUINOJSON_NAMESPACE::deserializeJson;
using ARDUINOJSON_NAMESPACE::deserializeMsgPack;
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
using ARDUINOJSON_NAMESPACE::JsonArray;
using ARDUINOJSON_NAMESPACE::JsonArrayConst;
using ARDUINOJSON_NAMESPACE::JsonFloat;
using ARDUINOJSON_NAMESPACE::JsonInteger;
using ARDUINOJSON_NAMESPACE::JsonKey;
using ARDUINOJSON_NAMESPACE::JsonObject;
using ARDUINOJSON_NAMESPACE::JsonObjectConst;
using ARDUINOJSON_NAMESPACE::JsonPair;
using ARDUINOJSON_NAMESPACE::JsonUInt;
using ARDUINOJSON_NAMESPACE::JsonVariant;
using ARDUINOJSON_NAMESPACE::JsonVariantConst;
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

View File

@ -0,0 +1,29 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Collection/CollectionData.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) {
return arr ? arr->add(pool) : 0;
}
template <typename Visitor>
inline void arrayAccept(const CollectionData *arr, Visitor &visitor) {
if (arr)
visitor.visitArray(*arr);
else
visitor.visitNull();
}
inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
if (lhs == rhs) return true;
if (!lhs || !rhs) return false;
return lhs->equalsArray(*rhs);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,22 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Object/ObjectRef.hpp"
#include "ArrayRef.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TArray>
inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const {
return impl()->addElement().template to<ArrayRef>();
}
template <typename TArray>
inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
return impl()->addElement().template to<ObjectRef>();
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,121 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Variant/SlotFunctions.hpp"
#include "../Variant/VariantRef.hpp"
namespace ARDUINOJSON_NAMESPACE {
class VariantPtr {
public:
VariantPtr(MemoryPool *pool, VariantData *data) : _variant(pool, data) {}
VariantRef *operator->() {
return &_variant;
}
VariantRef &operator*() {
return _variant;
}
private:
VariantRef _variant;
};
class ArrayIterator {
public:
ArrayIterator() : _slot(0) {}
explicit ArrayIterator(MemoryPool *pool, VariantSlot *slot)
: _pool(pool), _slot(slot) {}
VariantRef operator*() const {
return VariantRef(_pool, _slot->data());
}
VariantPtr operator->() {
return VariantPtr(_pool, _slot->data());
}
bool operator==(const ArrayIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const ArrayIterator &other) const {
return _slot != other._slot;
}
ArrayIterator &operator++() {
_slot = _slot->next();
return *this;
}
ArrayIterator &operator+=(size_t distance) {
_slot = _slot->next(distance);
return *this;
}
VariantSlot *internal() {
return _slot;
}
private:
MemoryPool *_pool;
VariantSlot *_slot;
};
class VariantConstPtr {
public:
VariantConstPtr(const VariantData *data) : _variant(data) {}
VariantConstRef *operator->() {
return &_variant;
}
VariantConstRef &operator*() {
return _variant;
}
private:
VariantConstRef _variant;
};
class ArrayConstRefIterator {
public:
ArrayConstRefIterator() : _slot(0) {}
explicit ArrayConstRefIterator(const VariantSlot *slot) : _slot(slot) {}
VariantConstRef operator*() const {
return VariantConstRef(_slot->data());
}
VariantConstPtr operator->() {
return VariantConstPtr(_slot->data());
}
bool operator==(const ArrayConstRefIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const ArrayConstRefIterator &other) const {
return _slot != other._slot;
}
ArrayConstRefIterator &operator++() {
_slot = _slot->next();
return *this;
}
ArrayConstRefIterator &operator+=(size_t distance) {
_slot = _slot->next(distance);
return *this;
}
const VariantSlot *internal() {
return _slot;
}
private:
const VariantSlot *_slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,153 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Variant/VariantData.hpp"
#include "ArrayFunctions.hpp"
#include "ArrayIterator.hpp"
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
namespace ARDUINOJSON_NAMESPACE {
class ObjectRef;
template <typename>
class ElementProxy;
template <typename TData>
class ArrayRefBase {
public:
operator VariantConstRef() const {
const void* data = _data; // prevent warning cast-align
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
arrayAccept(_data, visitor);
}
FORCE_INLINE bool isNull() const {
return _data == 0;
}
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0;
}
FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0;
}
protected:
ArrayRefBase(TData* data) : _data(data) {}
TData* _data;
};
class ArrayConstRef : public ArrayRefBase<const CollectionData>,
public Visitable {
friend class ArrayRef;
typedef ArrayRefBase<const CollectionData> base_type;
public:
typedef ArrayConstRefIterator iterator;
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_data->head());
}
FORCE_INLINE iterator end() const {
return iterator();
}
FORCE_INLINE ArrayConstRef() : base_type(0) {}
FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {}
FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
return arrayEquals(_data, rhs._data);
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return getElement(index);
}
FORCE_INLINE VariantConstRef getElement(size_t index) const {
return VariantConstRef(_data ? _data->get(index) : 0);
}
};
class ArrayRef : public ArrayRefBase<CollectionData>,
public ArrayShortcuts<ArrayRef>,
public Visitable {
typedef ArrayRefBase<CollectionData> base_type;
public:
typedef ArrayIterator iterator;
FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {}
FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data)
: base_type(data), _pool(pool) {}
operator VariantRef() {
void* data = _data; // prevent warning cast-align
return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
}
operator ArrayConstRef() const {
return ArrayConstRef(_data);
}
VariantRef addElement() const {
return VariantRef(_pool, arrayAdd(_data, _pool));
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_pool, _data->head());
}
FORCE_INLINE iterator end() const {
return iterator();
}
// Copy a ArrayRef
FORCE_INLINE bool set(ArrayConstRef src) const {
if (!_data || !src._data) return false;
return _data->copyFrom(*src._data, _pool);
}
FORCE_INLINE bool operator==(ArrayRef rhs) const {
return arrayEquals(_data, rhs._data);
}
// Gets the value at the specified index.
FORCE_INLINE VariantRef getElement(size_t index) const {
return VariantRef(_pool, _data ? _data->get(index) : 0);
}
// Removes element at specified position.
FORCE_INLINE void remove(iterator it) const {
if (!_data) return;
_data->remove(it.internal());
}
// Removes element at specified index.
FORCE_INLINE void remove(size_t index) const {
if (!_data) return;
_data->remove(index);
}
private:
MemoryPool* _pool;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,47 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Polyfills/attributes.hpp"
#include "../Polyfills/type_traits.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Forward declarations.
template <typename>
class ElementProxy;
template <typename TArray>
class ArrayShortcuts {
public:
// Returns the element at specified index if the variant is an array.
FORCE_INLINE ElementProxy<const TArray &> operator[](size_t index) const;
FORCE_INLINE ObjectRef createNestedObject() const;
FORCE_INLINE ArrayRef createNestedArray() const;
// Adds the specified value at the end of the array.
//
// bool add(TValue);
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ObjectRef
template <typename T>
FORCE_INLINE bool add(const T &value) const {
return impl()->addElement().set(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const __FlashStringHelper*
template <typename T>
FORCE_INLINE bool add(T *value) const {
return impl()->addElement().set(value);
}
private:
const TArray *impl() const {
return static_cast<const TArray *>(this);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,165 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Configuration.hpp"
#include "../Operators/VariantOperators.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE {
template <typename TArray>
class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
public Visitable {
typedef ElementProxy<TArray> this_type;
public:
FORCE_INLINE ElementProxy(TArray array, size_t index)
: _array(array), _index(index) {}
FORCE_INLINE this_type& operator=(const this_type& src) {
getUpstreamElement().set(src.as<VariantConstRef>());
return *this;
}
// Replaces the value
//
// operator=(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ArrayRef, ObjectRef
template <typename T>
FORCE_INLINE this_type& operator=(const T& src) {
getUpstreamElement().set(src);
return *this;
}
//
// operator=(TValue)
// TValue = char*, const char*, const __FlashStringHelper*
template <typename T>
FORCE_INLINE this_type& operator=(T* src) {
getUpstreamElement().set(src);
return *this;
}
FORCE_INLINE void clear() const {
getUpstreamElement().clear();
}
FORCE_INLINE bool isNull() const {
return getUpstreamElement().isNull();
}
template <typename T>
FORCE_INLINE typename VariantAs<T>::type as() const {
return getUpstreamElement().template as<T>();
}
template <typename T>
FORCE_INLINE bool is() const {
return getUpstreamElement().template is<T>();
}
template <typename T>
FORCE_INLINE typename VariantTo<T>::type to() const {
return getUpstreamElement().template to<T>();
}
// Replaces the value
//
// bool set(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ArrayRef, ObjectRef
template <typename TValue>
FORCE_INLINE bool set(const TValue& value) const {
return getUpstreamElement().set(value);
}
//
// bool set(TValue)
// TValue = char*, const char*, const __FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(TValue* value) const {
return getUpstreamElement().set(value);
}
template <typename Visitor>
void accept(Visitor& visitor) const {
return getUpstreamElement().accept(visitor);
}
FORCE_INLINE size_t size() const {
return getUpstreamElement().size();
}
template <typename TNestedKey>
VariantRef getMember(TNestedKey* key) const {
return getUpstreamElement().getMember(key);
}
template <typename TNestedKey>
VariantRef getMember(const TNestedKey& key) const {
return getUpstreamElement().getMember(key);
}
template <typename TNestedKey>
VariantRef getOrAddMember(TNestedKey* key) const {
return getUpstreamElement().getOrAddMember(key);
}
template <typename TNestedKey>
VariantRef getOrAddMember(const TNestedKey& key) const {
return getUpstreamElement().getOrAddMember(key);
}
VariantRef addElement() const {
return getUpstreamElement().addElement();
}
VariantRef getElement(size_t index) const {
return getUpstreamElement().getElement(index);
}
FORCE_INLINE void remove(size_t index) const {
getUpstreamElement().remove(index);
}
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) const {
getUpstreamElement().remove(key);
}
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) const {
getUpstreamElement().remove(key);
}
private:
FORCE_INLINE VariantRef getUpstreamElement() const {
return _array.getElement(_index);
}
TArray _array;
const size_t _index;
};
template <typename TArray>
inline ElementProxy<const TArray&> ArrayShortcuts<TArray>::operator[](
size_t index) const {
return ElementProxy<const TArray&>(*impl(), index);
}
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)
#endif

View File

@ -0,0 +1,66 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "ArrayRef.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Copy a 1D array to a JsonArray
template <typename T, size_t N>
inline bool copyArray(T (&src)[N], ArrayRef dst) {
return copyArray(src, N, dst);
}
// Copy a 1D array to a JsonArray
template <typename T>
inline bool copyArray(T* src, size_t len, ArrayRef dst) {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= dst.add(src[i]);
}
return ok;
}
// Copy a 2D array to a JsonArray
template <typename T, size_t N1, size_t N2>
inline bool copyArray(T (&src)[N1][N2], ArrayRef dst) {
bool ok = true;
for (size_t i = 0; i < N1; i++) {
ArrayRef nestedArray = dst.createNestedArray();
for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(src[i][j]);
}
}
return ok;
}
// Copy a JsonArray to a 1D array
template <typename T, size_t N>
inline size_t copyArray(ArrayConstRef src, T (&dst)[N]) {
return copyArray(src, dst, N);
}
// Copy a JsonArray to a 1D array
template <typename T>
inline size_t copyArray(ArrayConstRef src, T* dst, size_t len) {
size_t i = 0;
for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < len;
++it)
dst[i++] = *it;
return i;
}
// Copy a JsonArray to a 2D array
template <typename T, size_t N1, size_t N2>
inline void copyArray(ArrayConstRef src, T (&dst)[N1][N2]) {
size_t i = 0;
for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < N1;
++it) {
copyArray(it->as<ArrayConstRef>(), dst[i++]);
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,70 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class MemoryPool;
class VariantData;
class VariantSlot;
class CollectionData {
VariantSlot *_head;
VariantSlot *_tail;
public:
// Must be a POD!
// - no constructor
// - no destructor
// - no virtual
// - no inheritance
VariantSlot *addSlot(MemoryPool *);
VariantData *add(MemoryPool *pool);
template <typename TAdaptedString>
VariantData *add(TAdaptedString key, MemoryPool *pool);
void clear();
template <typename TAdaptedString>
bool containsKey(const TAdaptedString &key) const;
bool copyFrom(const CollectionData &src, MemoryPool *pool);
bool equalsArray(const CollectionData &other) const;
bool equalsObject(const CollectionData &other) const;
VariantData *get(size_t index) const;
template <typename TAdaptedString>
VariantData *get(TAdaptedString key) const;
VariantSlot *head() const {
return _head;
}
void remove(size_t index);
template <typename TAdaptedString>
void remove(TAdaptedString key) {
remove(getSlot(key));
}
void remove(VariantSlot *slot);
size_t memoryUsage() const;
size_t nesting() const;
size_t size() const;
private:
VariantSlot *getSlot(size_t index) const;
template <typename TAdaptedString>
VariantSlot *getSlot(TAdaptedString key) const;
VariantSlot *getPreviousSlot(VariantSlot *) const;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,163 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Variant/VariantData.hpp"
#include "CollectionData.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
VariantSlot* slot = pool->allocVariant();
if (!slot) return 0;
if (_tail) {
_tail->setNextNotNull(slot);
_tail = slot;
} else {
_head = slot;
_tail = slot;
}
slot->clear();
return slot;
}
inline VariantData* CollectionData::add(MemoryPool* pool) {
return slotData(addSlot(pool));
}
template <typename TAdaptedString>
inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) {
VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool)) return 0;
return slot->data();
}
inline void CollectionData::clear() {
_head = 0;
_tail = 0;
}
template <typename TAdaptedString>
inline bool CollectionData::containsKey(const TAdaptedString& key) const {
return getSlot(key) != 0;
}
inline bool CollectionData::copyFrom(const CollectionData& src,
MemoryPool* pool) {
clear();
for (VariantSlot* s = src._head; s; s = s->next()) {
VariantData* var;
if (s->key() != 0) {
if (s->ownsKey())
var = add(RamStringAdapter(s->key()), pool);
else
var = add(ConstRamStringAdapter(s->key()), pool);
} else {
var = add(pool);
}
if (!var) return false;
if (!var->copyFrom(*s->data(), pool)) return false;
}
return true;
}
inline bool CollectionData::equalsObject(const CollectionData& other) const {
size_t count = 0;
for (VariantSlot* slot = _head; slot; slot = slot->next()) {
VariantData* v1 = slot->data();
VariantData* v2 = other.get(adaptString(slot->key()));
if (!variantEquals(v1, v2)) return false;
count++;
}
return count == other.size();
}
inline bool CollectionData::equalsArray(const CollectionData& other) const {
VariantSlot* s1 = _head;
VariantSlot* s2 = other._head;
for (;;) {
if (s1 == s2) return true;
if (!s1 || !s2) return false;
if (!variantEquals(s1->data(), s2->data())) return false;
s1 = s1->next();
s2 = s2->next();
}
}
template <typename TAdaptedString>
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
VariantSlot* slot = _head;
while (slot) {
if (key.equals(slot->key())) break;
slot = slot->next();
}
return slot;
}
inline VariantSlot* CollectionData::getSlot(size_t index) const {
return _head->next(index);
}
inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
VariantSlot* current = _head;
while (current) {
VariantSlot* next = current->next();
if (next == target) return current;
current = next;
}
return 0;
}
template <typename TAdaptedString>
inline VariantData* CollectionData::get(TAdaptedString key) const {
VariantSlot* slot = getSlot(key);
return slot ? slot->data() : 0;
}
inline VariantData* CollectionData::get(size_t index) const {
VariantSlot* slot = getSlot(index);
return slot ? slot->data() : 0;
}
inline void CollectionData::remove(VariantSlot* slot) {
if (!slot) return;
VariantSlot* prev = getPreviousSlot(slot);
VariantSlot* next = slot->next();
if (prev)
prev->setNext(next);
else
_head = next;
if (!next) _tail = prev;
}
inline void CollectionData::remove(size_t index) {
remove(getSlot(index));
}
inline size_t CollectionData::memoryUsage() const {
size_t total = 0;
for (VariantSlot* s = _head; s; s = s->next()) {
total += sizeof(VariantSlot) + s->data()->memoryUsage();
if (s->ownsKey()) total += strlen(s->key()) + 1;
}
return total;
}
inline size_t CollectionData::nesting() const {
size_t maxChildNesting = 0;
for (VariantSlot* s = _head; s; s = s->next()) {
size_t childNesting = s->data()->nesting();
if (childNesting > maxChildNesting) maxChildNesting = childNesting;
}
return maxChildNesting + 1;
}
inline size_t CollectionData::size() const {
return slotSize(_head);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
@ -12,8 +12,10 @@
#if __cplusplus >= 201103L
#define ARDUINOJSON_HAS_LONG_LONG 1
#define ARDUINOJSON_HAS_NULLPTR 1
#else
#define ARDUINOJSON_HAS_LONG_LONG 0
#define ARDUINOJSON_HAS_NULLPTR 0
#endif
// Small or big machine?
@ -53,11 +55,6 @@
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
#endif
// Default capacity for DynamicJsonDocument
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
#define ARDUINOJSON_DEFAULT_POOL_SIZE 1024
#endif
#else // ARDUINOJSON_EMBEDDED_MODE
// On a computer we have plenty of memory so we can use doubles
@ -89,37 +86,42 @@
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
#endif
// Default capacity for DynamicJsonDocument
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
#define ARDUINOJSON_DEFAULT_POOL_SIZE 16384
#endif
#endif // ARDUINOJSON_EMBEDDED_MODE
#ifdef ARDUINO
// Enable support for Arduino String
// Enable support for Arduino's String class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
#endif
// Enable support for Arduino Stream
// Enable support for Arduino's Stream class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
#endif
// Enable support for Arduino's Print class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1
#endif
#else // ARDUINO
// Disable support for Arduino String
// Enable support for Arduino's String class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
#endif
// Disable support for Arduino Stream
// Enable support for Arduino's Stream class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
#endif
// Enable support for Arduino's Print class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
#endif
#endif // ARDUINO
#ifndef ARDUINOJSON_ENABLE_PROGMEM
@ -130,6 +132,21 @@
#endif
#endif
// Convert unicode escape sequence (\u0123) to UTF-8
#ifndef ARDUINOJSON_DECODE_UNICODE
#define ARDUINOJSON_DECODE_UNICODE 0
#endif
// Support NaN in JSON
#ifndef ARDUINOJSON_ENABLE_NAN
#define ARDUINOJSON_ENABLE_NAN 0
#endif
// Support Infinity in JSON
#ifndef ARDUINOJSON_ENABLE_INFINITY
#define ARDUINOJSON_ENABLE_INFINITY 0
#endif
// Control the exponentiation threshold for big numbers
// CAUTION: cannot be more that 1e9 !!!!
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
@ -144,9 +161,13 @@
#ifndef ARDUINOJSON_LITTLE_ENDIAN
#if defined(_MSC_VER) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
(defined(__LITTLE_ENDIAN__))
defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64)
#define ARDUINOJSON_LITTLE_ENDIAN 1
#else
#define ARDUINOJSON_LITTLE_ENDIAN 0
#endif
#endif
#ifndef ARDUINOJSON_TAB
#define ARDUINOJSON_TAB " "
#endif

View File

@ -1,114 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariantData.hpp"
#include "SlotFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline JsonVariantData* arrayAdd(JsonArrayData* arr, MemoryPool* pool) {
if (!arr) return 0;
VariantSlot* slot = pool->allocVariant();
if (!slot) return 0;
slot->next = 0;
slot->value.type = JSON_NULL;
if (arr->tail) {
slot->prev = arr->tail;
arr->tail->next = slot;
arr->tail = slot;
} else {
slot->prev = 0;
arr->head = slot;
arr->tail = slot;
}
slot->value.keyIsOwned = false;
return &slot->value;
}
inline VariantSlot* arrayGetSlot(const JsonArrayData* arr, size_t index) {
if (!arr) return 0;
return slotAdvance(arr->head, index);
}
inline JsonVariantData* arrayGet(const JsonArrayData* arr, size_t index) {
VariantSlot* slot = arrayGetSlot(arr, index);
return slot ? &slot->value : 0;
}
inline void arrayRemove(JsonArrayData* arr, VariantSlot* slot,
MemoryPool* pool) {
if (!arr || !slot) return;
if (slot->prev)
slot->prev->next = slot->next;
else
arr->head = slot->next;
if (slot->next)
slot->next->prev = slot->prev;
else
arr->tail = slot->prev;
slotFree(slot, pool);
}
inline void arrayRemove(JsonArrayData* arr, size_t index, MemoryPool* pool) {
arrayRemove(arr, arrayGetSlot(arr, index), pool);
}
inline void arrayClear(JsonArrayData* arr) {
if (!arr) return;
arr->head = 0;
arr->tail = 0;
}
bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
inline bool arrayCopy(JsonArrayData* dst, const JsonArrayData* src,
MemoryPool* pool) {
if (!dst || !src) return false;
arrayClear(dst);
for (VariantSlot* s = src->head; s; s = s->next) {
if (!variantCopy(arrayAdd(dst, pool), &s->value, pool)) return false;
}
return true;
}
bool variantEquals(const JsonVariantData*, const JsonVariantData*);
inline bool arrayEquals(const JsonArrayData* a1, const JsonArrayData* a2) {
if (a1 == a2) return true;
if (!a1 || !a2) return false;
VariantSlot* s1 = a1->head;
VariantSlot* s2 = a2->head;
for (;;) {
if (s1 == s2) return true;
if (!s1 || !s2) return false;
if (!variantEquals(&s1->value, &s2->value)) return false;
s1 = s1->next;
s2 = s2->next;
}
}
inline size_t arraySize(const JsonArrayData* arr) {
if (!arr) return 0;
return slotSize(arr->head);
}
inline void arrayFree(JsonArrayData* arr, MemoryPool* pool) {
ARDUINOJSON_ASSERT(arr);
VariantSlot* cur = arr->head;
while (cur) {
VariantSlot* next = cur->next;
slotFree(cur, pool);
cur = next;
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,49 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class JsonArray;
class JsonArrayConst;
class JsonObject;
class JsonObjectConst;
class JsonVariant;
class JsonVariantConst;
// 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;
};
// A metafunction that returns the type of the value returned by
// JsonVariant::as<T>()
template <typename T>
struct JsonVariantConstAs {
typedef typename JsonVariantAs<T>::type type;
};
template <>
struct JsonVariantConstAs<JsonVariant> {
typedef JsonVariantConst type;
};
template <>
struct JsonVariantConstAs<JsonObject> {
typedef JsonObjectConst type;
};
template <>
struct JsonVariantConstAs<JsonArray> {
typedef JsonArrayConst type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,81 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h> // ptrdiff_t, size_t
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"
namespace ARDUINOJSON_NAMESPACE {
enum JsonVariantType {
JSON_NULL,
JSON_LINKED_RAW,
JSON_OWNED_RAW,
JSON_LINKED_STRING,
JSON_OWNED_STRING,
JSON_BOOLEAN,
JSON_POSITIVE_INTEGER,
JSON_NEGATIVE_INTEGER,
JSON_ARRAY,
JSON_OBJECT,
JSON_FLOAT
};
struct JsonObjectData {
struct VariantSlot *head;
struct VariantSlot *tail;
};
struct JsonArrayData {
struct VariantSlot *head;
struct VariantSlot *tail;
};
struct RawData {
const char *data;
size_t size;
};
// A union that defines the actual content of a JsonVariantData.
// The enum JsonVariantType determines which member is in use.
union JsonVariantContent {
JsonFloat asFloat;
JsonUInt asInteger;
JsonArrayData asArray;
JsonObjectData asObject;
const char *asString;
struct StringSlot *asOwnedString;
struct StringSlot *asOwnedRaw;
struct {
const char *data;
size_t size;
} asRaw;
};
// this struct must be a POD type to prevent error calling offsetof on clang
struct JsonVariantData {
bool keyIsOwned : 1;
JsonVariantType type : 7;
JsonVariantContent content;
};
inline JsonVariantData *getVariantData(JsonArrayData *arr) {
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
offsetof(JsonVariantContent, asArray);
if (!arr) return 0;
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(arr) -
offset);
}
inline JsonVariantData *getVariantData(JsonObjectData *obj) {
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
offsetof(JsonVariantContent, asObject);
if (!obj) return 0;
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(obj) -
offset);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,30 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class JsonArray;
class JsonObject;
class JsonVariant;
// A metafunction that returns the type of the value returned by
// JsonVariant::to<T>()
template <typename T>
struct JsonVariantTo {};
template <>
struct JsonVariantTo<JsonArray> {
typedef JsonArray type;
};
template <>
struct JsonVariantTo<JsonObject> {
typedef JsonObject type;
};
template <>
struct JsonVariantTo<JsonVariant> {
typedef JsonVariant type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,128 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Memory/MemoryPool.hpp"
#include "JsonVariantData.hpp"
#include "SlotFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline VariantSlot* objectFindSlot(const JsonObjectData* obj, TKey key) {
if (!obj) return 0;
VariantSlot* slot = obj->head;
while (slot) {
if (key.equals(slotGetKey(slot))) break;
slot = slot->next;
}
return slot;
}
template <typename TKey>
inline bool objectContainsKey(const JsonObjectData* obj, const TKey& key) {
return objectFindSlot(obj, key) != 0;
}
template <typename TKey>
inline JsonVariantData* objectAdd(JsonObjectData* obj, TKey key,
MemoryPool* pool) {
VariantSlot* slot = pool->allocVariant();
if (!slot) return 0;
slot->next = 0;
slot->value.type = JSON_NULL;
if (obj->tail) {
slot->prev = obj->tail;
obj->tail->next = slot;
obj->tail = slot;
} else {
slot->prev = 0;
obj->head = slot;
obj->tail = slot;
}
if (!slotSetKey(slot, key, pool)) return 0;
return &slot->value;
}
template <typename TKey>
inline JsonVariantData* objectSet(JsonObjectData* obj, TKey key,
MemoryPool* pool) {
if (!obj) return 0;
// ignore null key
if (key.isNull()) return 0;
// search a matching key
VariantSlot* slot = objectFindSlot(obj, key);
if (slot) return &slot->value;
return objectAdd(obj, key, pool);
}
template <typename TKey>
inline JsonVariantData* objectGet(const JsonObjectData* obj, TKey key) {
VariantSlot* slot = objectFindSlot(obj, key);
return slot ? &slot->value : 0;
}
inline void objectClear(JsonObjectData* obj) {
if (!obj) return;
obj->head = 0;
obj->tail = 0;
}
inline void objectRemove(JsonObjectData* obj, VariantSlot* slot,
MemoryPool* pool) {
if (!obj) return;
if (!slot) return;
if (slot->prev)
slot->prev->next = slot->next;
else
obj->head = slot->next;
if (slot->next)
slot->next->prev = slot->prev;
else
obj->tail = slot->prev;
slotFree(slot, pool);
}
inline size_t objectSize(const JsonObjectData* obj) {
if (!obj) return 0;
return slotSize(obj->head);
}
// bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
inline bool objectCopy(JsonObjectData* dst, const JsonObjectData* src,
MemoryPool* pool) {
if (!dst || !src) return false;
objectClear(dst);
for (VariantSlot* s = src->head; s; s = s->next) {
JsonVariantData* var;
if (s->value.keyIsOwned)
var = objectAdd(dst, ZeroTerminatedRamString(s->ownedKey->value), pool);
else
var = objectAdd(dst, ZeroTerminatedRamStringConst(s->linkedKey), pool);
if (!variantCopy(var, &s->value, pool)) return false;
}
return true;
}
inline bool objectEquals(const JsonObjectData* o1, const JsonObjectData* o2) {
if (o1 == o2) return true;
if (!o1 || !o2) return false;
for (VariantSlot* s = o1->head; s; s = s->next) {
JsonVariantData* v1 = &s->value;
JsonVariantData* v2 = objectGet(o2, makeString(slotGetKey(s)));
if (!variantEquals(v1, v2)) return false;
}
return true;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,77 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Memory/MemoryPool.hpp"
#include "../Polyfills/assert.hpp"
#include "../Strings/StringTypes.hpp"
#include "JsonVariantData.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) {
StringSlot* slot = key.save(pool);
if (!slot) return false;
var->ownedKey = slot;
var->value.keyIsOwned = true;
return true;
}
inline bool slotSetKey(VariantSlot* var, ZeroTerminatedRamStringConst key,
MemoryPool*) {
var->linkedKey = key.c_str();
var->value.keyIsOwned = false;
return true;
}
inline bool slotSetKey(VariantSlot* var, StringInMemoryPool key, MemoryPool*) {
var->ownedKey = key.slot();
var->value.keyIsOwned = true;
return true;
}
inline const char* slotGetKey(const VariantSlot* var) {
return var->value.keyIsOwned ? var->ownedKey->value : var->linkedKey;
}
inline const VariantSlot* slotAdvance(const VariantSlot* var, size_t distance) {
while (distance && var) {
var = var->next;
distance--;
}
return var;
}
inline VariantSlot* slotAdvance(VariantSlot* var, size_t distance) {
while (distance && var) {
var = var->next;
distance--;
}
return var;
}
inline size_t slotSize(const VariantSlot* var) {
size_t n = 0;
while (var) {
n++;
var = var->next;
}
return n;
}
void variantFree(JsonVariantData* var, MemoryPool* pool);
inline void slotFree(VariantSlot* var, MemoryPool* pool) {
ARDUINOJSON_ASSERT(var != 0);
ARDUINOJSON_ASSERT(pool != 0);
variantFree(&var->value, pool);
if (var->value.keyIsOwned) pool->freeString(var->ownedKey);
pool->freeVariant(var);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,48 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Serialization/DynamicStringWriter.hpp"
#include "VariantFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
class JsonVariantConst;
template <typename T>
inline typename enable_if<is_integral<T>::value, T>::type variantAs(
const JsonVariantData* _data) {
return variantAsIntegral<T>(_data);
}
template <typename T>
inline typename enable_if<is_same<T, bool>::value, T>::type variantAs(
const JsonVariantData* _data) {
return variantAsBoolean(_data);
}
template <typename T>
inline typename enable_if<is_floating_point<T>::value, T>::type variantAs(
const JsonVariantData* _data) {
return variantAsFloat<T>(_data);
}
template <typename T>
inline typename enable_if<is_same<T, const char*>::value ||
is_same<T, char*>::value,
const char*>::type
variantAs(const JsonVariantData* _data) {
return variantAsString(_data);
}
template <typename T>
inline typename enable_if<is_same<JsonVariantConst, T>::value, T>::type
variantAs(const JsonVariantData* _data);
template <typename T>
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
const JsonVariantData* _data);
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,29 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../JsonVariant.hpp"
#include "../Serialization/DynamicStringWriter.hpp"
#include "VariantFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline typename enable_if<is_same<JsonVariantConst, T>::value, T>::type
variantAs(const JsonVariantData* _data) {
return JsonVariantConst(_data);
}
template <typename T>
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
const JsonVariantData* _data) {
const char* cstr = variantAsString(_data);
if (cstr) return T(cstr);
T s;
serializeJson(JsonVariantConst(_data), s);
return s;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,341 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Numbers/parseFloat.hpp"
#include "../Numbers/parseInteger.hpp"
#include "../SerializedValue.hpp"
#include "ArrayFunctions.hpp"
#include "JsonVariantData.hpp"
#include "ObjectFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline void variantFree(JsonVariantData* var, MemoryPool* pool) {
ARDUINOJSON_ASSERT(var != 0);
ARDUINOJSON_ASSERT(pool != 0);
switch (var->type) {
case JSON_ARRAY:
case JSON_OBJECT:
arrayFree(&var->content.asArray, pool);
break;
case JSON_OWNED_STRING:
case JSON_OWNED_RAW:
pool->freeString(var->content.asOwnedString);
break;
default:
break;
}
}
template <typename T>
inline T variantAsIntegral(const JsonVariantData* var) {
if (!var) return 0;
switch (var->type) {
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return T(var->content.asInteger);
case JSON_NEGATIVE_INTEGER:
return T(~var->content.asInteger + 1);
case JSON_LINKED_STRING:
return parseInteger<T>(var->content.asString);
case JSON_OWNED_STRING:
return parseInteger<T>(var->content.asOwnedString->value);
case JSON_FLOAT:
return T(var->content.asFloat);
default:
return 0;
}
}
inline bool variantAsBoolean(const JsonVariantData* var) {
return variantAsIntegral<int>(var) != 0;
}
// T = float/double
template <typename T>
inline T variantAsFloat(const JsonVariantData* var) {
if (!var) return 0;
switch (var->type) {
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return static_cast<T>(var->content.asInteger);
case JSON_NEGATIVE_INTEGER:
return -static_cast<T>(var->content.asInteger);
case JSON_LINKED_STRING:
return parseFloat<T>(var->content.asString);
case JSON_OWNED_STRING:
return parseFloat<T>(var->content.asOwnedString->value);
case JSON_FLOAT:
return static_cast<T>(var->content.asFloat);
default:
return 0;
}
}
inline const char* variantAsString(const JsonVariantData* var) {
if (!var) return 0;
switch (var->type) {
case JSON_LINKED_STRING:
return var->content.asString;
case JSON_OWNED_STRING:
return var->content.asOwnedString->value;
default:
return 0;
}
}
inline JsonArrayData* variantAsArray(JsonVariantData* var) {
if (var && var->type == JSON_ARRAY)
return &var->content.asArray;
else
return 0;
}
inline const JsonArrayData* variantAsArray(const JsonVariantData* var) {
if (var && var->type == JSON_ARRAY)
return &var->content.asArray;
else
return 0;
}
inline JsonObjectData* variantAsObject(JsonVariantData* var) {
if (var && var->type == JSON_OBJECT)
return &var->content.asObject;
else
return 0;
}
inline const JsonObjectData* variantAsObject(const JsonVariantData* var) {
if (var && var->type == JSON_OBJECT)
return &var->content.asObject;
else
return 0;
}
inline bool variantSetBoolean(JsonVariantData* var, bool value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_BOOLEAN;
var->content.asInteger = static_cast<JsonUInt>(value);
return true;
}
inline bool variantSetFloat(JsonVariantData* var, JsonFloat value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_FLOAT;
var->content.asFloat = value;
return true;
}
template <typename T>
inline bool variantSetSignedInteger(JsonVariantData* var, T value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
if (value >= 0) {
var->type = JSON_POSITIVE_INTEGER;
var->content.asInteger = static_cast<JsonUInt>(value);
} else {
var->type = JSON_NEGATIVE_INTEGER;
var->content.asInteger = ~static_cast<JsonUInt>(value) + 1;
}
return true;
}
inline bool variantSetUnsignedInteger(JsonVariantData* var, JsonUInt value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_POSITIVE_INTEGER;
var->content.asInteger = static_cast<JsonUInt>(value);
return true;
}
inline bool variantSetLinkedRaw(JsonVariantData* var,
SerializedValue<const char*> value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_LINKED_RAW;
var->content.asRaw.data = value.data();
var->content.asRaw.size = value.size();
return true;
}
template <typename T>
inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
StringSlot* slot = makeString(value.data(), value.size()).save(pool);
if (slot) {
var->type = JSON_OWNED_RAW;
var->content.asOwnedRaw = slot;
return true;
} else {
var->type = JSON_NULL;
return false;
}
}
template <typename T>
inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
StringSlot* slot = value.save(pool);
if (slot) {
var->type = JSON_OWNED_STRING;
var->content.asOwnedString = slot;
return true;
} else {
var->type = JSON_NULL;
return false;
}
}
inline bool variantSetOwnedString(JsonVariantData* var, StringSlot* slot,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_OWNED_STRING;
var->content.asOwnedString = slot;
return true;
}
inline bool variantSetString(JsonVariantData* var, const char* value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_LINKED_STRING;
var->content.asString = value;
return true;
}
inline void variantSetNull(JsonVariantData* var, MemoryPool* pool) {
if (!var) return;
variantFree(var, pool);
var->type = JSON_NULL;
}
inline JsonArrayData* variantToArray(JsonVariantData* var, MemoryPool* pool) {
if (!var) return 0;
variantFree(var, pool);
var->type = JSON_ARRAY;
var->content.asArray.head = 0;
var->content.asArray.tail = 0;
return &var->content.asArray;
}
inline JsonObjectData* variantToObject(JsonVariantData* var, MemoryPool* pool) {
if (!var) return 0;
variantFree(var, pool);
var->type = JSON_OBJECT;
var->content.asObject.head = 0;
var->content.asObject.tail = 0;
return &var->content.asObject;
}
inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src,
MemoryPool* pool) {
if (!dst) return false;
if (!src) {
variantFree(dst, pool);
dst->type = JSON_NULL;
return true;
}
switch (src->type) {
case JSON_ARRAY:
return arrayCopy(variantToArray(dst, pool), &src->content.asArray, pool);
case JSON_OBJECT:
return objectCopy(variantToObject(dst, pool), &src->content.asObject,
pool);
case JSON_OWNED_STRING:
return variantSetString(
dst, makeString(src->content.asOwnedString->value), pool);
case JSON_OWNED_RAW:
return variantSetOwnedRaw(dst,
serialized(src->content.asOwnedRaw->value,
src->content.asOwnedRaw->size),
pool);
default:
variantFree(dst, pool);
// caution: don't override keyIsOwned
dst->type = src->type;
dst->content = src->content;
return true;
}
}
inline bool variantIsInteger(const JsonVariantData* var) {
return var && (var->type == JSON_POSITIVE_INTEGER ||
var->type == JSON_NEGATIVE_INTEGER);
}
inline bool variantIsFloat(const JsonVariantData* var) {
return var &&
(var->type == JSON_FLOAT || var->type == JSON_POSITIVE_INTEGER ||
var->type == JSON_NEGATIVE_INTEGER);
}
inline bool variantIsString(const JsonVariantData* var) {
return var &&
(var->type == JSON_LINKED_STRING || var->type == JSON_OWNED_STRING);
}
inline bool variantIsArray(const JsonVariantData* var) {
return var && var->type == JSON_ARRAY;
}
inline bool variantIsObject(const JsonVariantData* var) {
return var && var->type == JSON_OBJECT;
}
inline bool variantIsNull(const JsonVariantData* var) {
return var == 0 || var->type == JSON_NULL;
}
inline bool variantEquals(const JsonVariantData* a, const JsonVariantData* b) {
if (a == b) return true;
if (!a || !b) return false;
if (a->type != b->type) return false;
switch (a->type) {
case JSON_LINKED_RAW:
case JSON_LINKED_STRING:
return !strcmp(a->content.asString, b->content.asString);
case JSON_OWNED_RAW:
case JSON_OWNED_STRING:
return a->content.asOwnedString->size == b->content.asOwnedString->size &&
!memcmp(a->content.asOwnedString->value,
b->content.asOwnedString->value,
a->content.asOwnedString->size);
case JSON_BOOLEAN:
case JSON_POSITIVE_INTEGER:
case JSON_NEGATIVE_INTEGER:
return a->content.asInteger == b->content.asInteger;
case JSON_ARRAY:
return arrayEquals(&a->content.asArray, &b->content.asArray);
case JSON_OBJECT:
return objectEquals(&a->content.asObject, &b->content.asObject);
case JSON_FLOAT:
return a->content.asFloat == b->content.asFloat;
case JSON_NULL:
default:
return true;
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
@ -12,22 +12,14 @@ namespace ARDUINOJSON_NAMESPACE {
struct ArduinoStreamReader {
Stream& _stream;
char _current;
bool _ended;
public:
explicit ArduinoStreamReader(Stream& stream)
: _stream(stream), _current(0), _ended(false) {}
explicit ArduinoStreamReader(Stream& stream) : _stream(stream) {}
char read() {
int read() {
// don't use _stream.read() as it ignores the timeout
char c = 0;
_ended = _stream.readBytes(&c, 1) == 0;
return c;
}
bool ended() const {
return _ended;
uint8_t c;
return _stream.readBytes(&c, 1) ? c : -1;
}
};

View File

@ -1,61 +1,66 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <typename TChar>
template <typename T>
struct IsCharOrVoid {
static const bool value =
is_same<T, void>::value || is_same<T, char>::value ||
is_same<T, unsigned char>::value || is_same<T, signed char>::value;
};
template <typename T>
struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
class UnsafeCharPointerReader {
const TChar* _ptr;
const char* _ptr;
public:
explicit UnsafeCharPointerReader(const TChar* ptr)
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")) {}
explicit UnsafeCharPointerReader(const char* ptr)
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")) {}
char read() {
return static_cast<char>(*_ptr++);
}
bool ended() const {
// we cannot know
return false;
int read() {
return static_cast<unsigned char>(*_ptr++);
}
};
template <typename TChar>
class SafeCharPointerReader {
const TChar* _ptr;
const TChar* _end;
const char* _ptr;
const char* _end;
public:
explicit SafeCharPointerReader(const TChar* ptr, size_t len)
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")),
_end(_ptr + len) {}
explicit SafeCharPointerReader(const char* ptr, size_t len)
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")), _end(_ptr + len) {}
char read() {
return static_cast<char>(*_ptr++);
}
bool ended() const {
return _ptr == _end;
int read() {
if (_ptr < _end)
return static_cast<unsigned char>(*_ptr++);
else
return -1;
}
};
template <typename TChar>
inline UnsafeCharPointerReader<TChar> makeReader(TChar* input) {
return UnsafeCharPointerReader<TChar>(input);
inline typename enable_if<IsCharOrVoid<TChar>::value,
UnsafeCharPointerReader>::type
makeReader(TChar* input) {
return UnsafeCharPointerReader(reinterpret_cast<const char*>(input));
}
template <typename TChar>
inline SafeCharPointerReader<TChar> makeReader(TChar* input, size_t n) {
return SafeCharPointerReader<TChar>(input, n);
inline
typename enable_if<IsCharOrVoid<TChar>::value, SafeCharPointerReader>::type
makeReader(TChar* input, size_t n) {
return SafeCharPointerReader(reinterpret_cast<const char*>(input), n);
}
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
inline SafeCharPointerReader<char> makeReader(const String& input) {
return SafeCharPointerReader<char>(input.c_str(), input.length());
inline SafeCharPointerReader makeReader(const ::String& input) {
return SafeCharPointerReader(input.c_str(), input.length());
}
#endif

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
@ -14,14 +14,9 @@ class UnsafeFlashStringReader {
explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr)
: _ptr(reinterpret_cast<const char*>(ptr)) {}
char read() {
int read() {
return pgm_read_byte_near(_ptr++);
}
bool ended() const {
// this reader cannot detect the end
return false;
}
};
class SafeFlashStringReader {
@ -32,12 +27,11 @@ class SafeFlashStringReader {
explicit SafeFlashStringReader(const __FlashStringHelper* ptr, size_t size)
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
char read() {
return pgm_read_byte_near(_ptr++);
}
bool ended() const {
return _ptr == _end;
int read() {
if (_ptr < _end)
return pgm_read_byte_near(_ptr++);
else
return -1;
}
};

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
@ -14,12 +14,11 @@ class IteratorReader {
explicit IteratorReader(TIterator begin, TIterator end)
: _ptr(begin), _end(end) {}
bool ended() const {
return _ptr == _end;
}
char read() {
return char(*_ptr++);
int read() {
if (_ptr < _end)
return static_cast<unsigned char>(*_ptr++);
else
return -1;
}
};

View File

@ -0,0 +1,17 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Configuration.hpp"
namespace ARDUINOJSON_NAMESPACE {
struct NestingLimit {
NestingLimit() : value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
explicit NestingLimit(uint8_t n) : value(n) {}
uint8_t value;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
@ -18,12 +18,8 @@ class StdStreamReader {
explicit StdStreamReader(std::istream& stream)
: _stream(stream), _current(0) {}
bool ended() const {
return _stream.eof();
}
char read() {
return static_cast<char>(_stream.get());
int read() {
return _stream.get();
}
private:

View File

@ -1,76 +1,76 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../StringStorage/StringStorage.hpp"
#include "./ArduinoStreamReader.hpp"
#include "./CharPointerReader.hpp"
#include "./DeserializationError.hpp"
#include "./FlashStringReader.hpp"
#include "./IteratorReader.hpp"
#include "./StdStreamReader.hpp"
#include "ArduinoStreamReader.hpp"
#include "CharPointerReader.hpp"
#include "DeserializationError.hpp"
#include "FlashStringReader.hpp"
#include "IteratorReader.hpp"
#include "NestingLimit.hpp"
#include "StdStreamReader.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <template <typename, typename> class TDeserializer,
typename TMemoryPool, typename TReader, typename TWriter>
TDeserializer<TReader, TWriter> makeDeserializer(TMemoryPool &memoryPool,
template <template <typename, typename> class TDeserializer, typename TReader,
typename TWriter>
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
TReader reader, TWriter writer,
uint8_t nestingLimit) {
return TDeserializer<TReader, TWriter>(memoryPool, reader, writer,
nestingLimit);
return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit);
}
// DeserializationError deserialize(TDocument& doc, TString input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = const std::string&, const String&
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TString>
// deserialize(JsonDocument&, const std::string&);
// deserialize(JsonDocument&, const String&);
template <template <typename, typename> class TDeserializer, typename TString>
typename enable_if<!is_array<TString>::value, DeserializationError>::type
deserialize(TDocument &doc, const TString &input) {
deserialize(JsonDocument &doc, const TString &input,
NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
//
// DeserializationError deserialize(TDocument& doc, TChar* input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TChar* = char*, const char*, const FlashStringHelper*
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TChar>
DeserializationError deserialize(TDocument &doc, TChar *input) {
// deserialize(JsonDocument&, char*);
// deserialize(JsonDocument&, const char*);
// deserialize(JsonDocument&, const __FlashStringHelper*);
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
//
// DeserializationError deserialize(TDocument& doc, TChar* input, size_t
// inputSize);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TChar* = char*, const char*, const FlashStringHelper*
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TChar>
DeserializationError deserialize(TDocument &doc, TChar *input,
size_t inputSize) {
// deserialize(JsonDocument&, char*, size_t);
// deserialize(JsonDocument&, const char*, size_t);
// deserialize(JsonDocument&, const __FlashStringHelper*, size_t);
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
size_t inputSize, NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input, inputSize),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
//
// DeserializationError deserialize(TDocument& doc, TStream input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TStream = std::istream&, Stream&
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TStream>
DeserializationError deserialize(TDocument &doc, TStream &input) {
// deserialize(JsonDocument&, std::istream&);
// deserialize(JsonDocument&, Stream&);
template <template <typename, typename> class TDeserializer, typename TStream>
DeserializationError deserialize(JsonDocument &doc, TStream &input,
NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,89 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "JsonDocument.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TAllocator>
class AllocatorOwner {
protected:
AllocatorOwner() {}
AllocatorOwner(const AllocatorOwner& src) : _allocator(src._allocator) {}
AllocatorOwner(TAllocator allocator) : _allocator(allocator) {}
void* allocate(size_t n) {
return _allocator.allocate(n);
}
void deallocate(void* p) {
_allocator.deallocate(p);
}
private:
TAllocator _allocator;
};
template <typename TAllocator>
class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
public:
explicit BasicJsonDocument(size_t capa, TAllocator allocator = TAllocator())
: AllocatorOwner<TAllocator>(allocator), JsonDocument(allocPool(capa)) {}
BasicJsonDocument(const BasicJsonDocument& src)
: AllocatorOwner<TAllocator>(src),
JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
template <typename T>
BasicJsonDocument(const T& src,
typename enable_if<IsVisitable<T>::value>::type* = 0)
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
// disambiguate
BasicJsonDocument(VariantRef src)
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
~BasicJsonDocument() {
freePool();
}
BasicJsonDocument& operator=(const BasicJsonDocument& src) {
reallocPoolIfTooSmall(src.memoryUsage());
set(src);
return *this;
}
template <typename T>
BasicJsonDocument& operator=(const T& src) {
reallocPoolIfTooSmall(src.memoryUsage());
set(src);
return *this;
}
private:
MemoryPool allocPool(size_t requiredSize) {
size_t capa = addPadding(requiredSize);
return MemoryPool(reinterpret_cast<char*>(this->allocate(capa)), capa);
}
void reallocPoolIfTooSmall(size_t requiredSize) {
if (requiredSize <= capacity()) return;
freePool();
replacePool(allocPool(addPadding(requiredSize)));
}
void freePool() {
this->deallocate(memoryPool().buffer());
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,25 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "BasicJsonDocument.hpp"
#include <stdlib.h> // malloc, free
namespace ARDUINOJSON_NAMESPACE {
struct DefaultAllocator {
void* allocate(size_t n) {
return malloc(n);
}
void deallocate(void* p) {
free(p);
}
};
typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,307 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Memory/MemoryPool.hpp"
#include "../Object/ObjectRef.hpp"
#include "../Variant/VariantRef.hpp"
#include "../Variant/VariantTo.hpp"
#include "../Array/ElementProxy.hpp"
#include "../Object/MemberProxy.hpp"
namespace ARDUINOJSON_NAMESPACE {
class JsonDocument : public Visitable {
public:
template <typename Visitor>
void accept(Visitor& visitor) const {
return getVariant().accept(visitor);
}
template <typename T>
typename VariantAs<T>::type as() {
return getVariant().template as<T>();
}
template <typename T>
typename VariantConstAs<T>::type as() const {
return getVariant().template as<T>();
}
void clear() {
_pool.clear();
_data.setNull();
}
template <typename T>
bool is() const {
return getVariant().template is<T>();
}
bool isNull() const {
return getVariant().isNull();
}
size_t memoryUsage() const {
return _pool.size();
}
size_t nesting() const {
return _data.nesting();
}
size_t capacity() const {
return _pool.capacity();
}
size_t size() const {
return _data.size();
}
bool set(const JsonDocument& src) {
return to<VariantRef>().set(src.as<VariantRef>());
}
template <typename T>
typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set(
const T& src) {
return to<VariantRef>().set(src);
}
template <typename T>
typename VariantTo<T>::type to() {
clear();
return getVariant().template to<T>();
}
// for internal use only
MemoryPool& memoryPool() {
return _pool;
}
VariantData& data() {
return _data;
}
ArrayRef createNestedArray() {
return addElement().to<ArrayRef>();
}
// createNestedArray(char*)
// createNestedArray(const char*)
// createNestedArray(const __FlashStringHelper*)
template <typename TChar>
ArrayRef createNestedArray(TChar* key) {
return getOrAddMember(key).template to<ArrayRef>();
}
// createNestedArray(const std::string&)
// createNestedArray(const String&)
template <typename TString>
ArrayRef createNestedArray(const TString& key) {
return getOrAddMember(key).template to<ArrayRef>();
}
ObjectRef createNestedObject() {
return addElement().to<ObjectRef>();
}
// createNestedObject(char*)
// createNestedObject(const char*)
// createNestedObject(const __FlashStringHelper*)
template <typename TChar>
ObjectRef createNestedObject(TChar* key) {
return getOrAddMember(key).template to<ObjectRef>();
}
// createNestedObject(const std::string&)
// createNestedObject(const String&)
template <typename TString>
ObjectRef createNestedObject(const TString& key) {
return getOrAddMember(key).template to<ObjectRef>();
}
// containsKey(char*) const
// containsKey(const char*) const
// containsKey(const __FlashStringHelper*) const
template <typename TChar>
bool containsKey(TChar* key) const {
return !getMember(key).isUndefined();
}
// containsKey(const std::string&) const
// containsKey(const String&) const
template <typename TString>
bool containsKey(const TString& key) const {
return !getMember(key).isUndefined();
}
// operator[](const std::string&)
// operator[](const String&)
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value,
MemberProxy<JsonDocument&, const TString&> >::type
operator[](const TString& key) {
return MemberProxy<JsonDocument&, const TString&>(*this, key);
}
// operator[](char*)
// operator[](const char*)
// operator[](const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<JsonDocument&, TChar*> >::type
operator[](TChar* key) {
return MemberProxy<JsonDocument&, TChar*>(*this, key);
}
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString& key) const {
return getMember(key);
}
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
operator[](TChar* key) const {
return getMember(key);
}
FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
return ElementProxy<JsonDocument&>(*this, index);
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return getElement(index);
}
FORCE_INLINE VariantRef getElement(size_t index) {
return VariantRef(&_pool, _data.getElement(index));
}
FORCE_INLINE VariantConstRef getElement(size_t index) const {
return VariantConstRef(_data.getElement(index));
}
// JsonVariantConst getMember(char*) const
// JsonVariantConst getMember(const char*) const
// JsonVariantConst getMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantConstRef getMember(TChar* key) const {
return VariantConstRef(_data.getMember(adaptString(key)));
}
// JsonVariantConst getMember(const std::string&) const
// JsonVariantConst getMember(const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
getMember(const TString& key) const {
return VariantConstRef(_data.getMember(adaptString(key)));
}
// JsonVariant getMember(char*)
// JsonVariant getMember(const char*)
// JsonVariant getMember(const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE VariantRef getMember(TChar* key) {
return VariantRef(&_pool, _data.getMember(adaptString(key)));
}
// JsonVariant getMember(const std::string&)
// JsonVariant getMember(const String&)
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
getMember(const TString& key) {
return VariantRef(&_pool, _data.getMember(adaptString(key)));
}
// getOrAddMember(char*)
// getOrAddMember(const char*)
// getOrAddMember(const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE VariantRef getOrAddMember(TChar* key) {
return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
}
// getOrAddMember(const std::string&)
// getOrAddMember(const String&)
template <typename TString>
FORCE_INLINE VariantRef getOrAddMember(const TString& key) {
return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
}
FORCE_INLINE VariantRef addElement() {
return VariantRef(&_pool, _data.addElement(&_pool));
}
template <typename TValue>
FORCE_INLINE bool add(const TValue& value) {
return addElement().set(value);
}
// add(char*) const
// add(const char*) const
// add(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE bool add(TChar* value) {
return addElement().set(value);
}
FORCE_INLINE void remove(size_t index) {
_data.remove(index);
}
// remove(char*)
// remove(const char*)
// remove(const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) {
_data.remove(adaptString(key));
}
// remove(const std::string&)
// remove(const String&)
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) {
_data.remove(adaptString(key));
}
protected:
JsonDocument(MemoryPool pool) : _pool(pool) {
_data.setNull();
}
JsonDocument(char* buf, size_t capa) : _pool(buf, capa) {
_data.setNull();
}
void replacePool(MemoryPool pool) {
_pool = pool;
}
private:
VariantRef getVariant() {
return VariantRef(&_pool, &_data);
}
VariantConstRef getVariant() const {
return VariantConstRef(&_data);
}
MemoryPool _pool;
VariantData _data;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,51 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "JsonDocument.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <size_t desiredCapacity>
class StaticJsonDocument : public JsonDocument {
static const size_t _capacity =
AddPadding<Max<1, desiredCapacity>::value>::value;
public:
StaticJsonDocument() : JsonDocument(_buffer, _capacity) {}
StaticJsonDocument(const StaticJsonDocument& src)
: JsonDocument(_buffer, _capacity) {
set(src);
}
template <typename T>
StaticJsonDocument(const T& src,
typename enable_if<IsVisitable<T>::value>::type* = 0)
: JsonDocument(_buffer, _capacity) {
set(src);
}
// disambiguate
StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, _capacity) {
set(src);
}
StaticJsonDocument operator=(const StaticJsonDocument& src) {
set(src);
return *this;
}
template <typename T>
StaticJsonDocument operator=(const T& src) {
set(src);
return *this;
}
private:
char _buffer[_capacity];
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once

View File

@ -1,69 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
// Decorator on top of Print to allow indented output.
// This class is used by serializeJsonPretty() but can also be used
// for your own purpose, like logging.
template <typename Print>
class IndentedPrint {
public:
explicit IndentedPrint(Print &p) : sink(&p) {
level = 0;
tabSize = 2;
isNewLine = true;
}
size_t write(uint8_t c) {
size_t n = 0;
if (isNewLine) n += writeTabs();
n += sink->write(c);
isNewLine = c == '\n';
return n;
}
size_t write(const uint8_t *s, size_t n) {
// TODO: optimize
size_t bytesWritten = 0;
while (n > 0) {
bytesWritten += write(*s++);
n--;
}
return bytesWritten;
}
// Adds one level of indentation
void indent() {
if (level < MAX_LEVEL) level++;
}
// Removes one level of indentation
void unindent() {
if (level > 0) level--;
}
// Set the number of space printed for each level of indentation
void setTabSize(uint8_t n) {
if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE;
}
private:
Print *sink;
uint8_t level : 4;
uint8_t tabSize : 3;
bool isNewLine : 1;
size_t writeTabs() {
size_t n = 0;
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
return n;
}
static const int MAX_LEVEL = 15; // because it's only 4 bits
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,16 +1,16 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Deserialization/deserialize.hpp"
#include "../JsonVariant.hpp"
#include "../Memory/MemoryPool.hpp"
#include "../Numbers/isFloat.hpp"
#include "../Numbers/isInteger.hpp"
#include "../Numbers/parseNumber.hpp"
#include "../Polyfills/type_traits.hpp"
#include "./EscapeSequence.hpp"
#include "../Variant/VariantData.hpp"
#include "EscapeSequence.hpp"
#include "Utf8.hpp"
namespace ARDUINOJSON_NAMESPACE {
@ -18,30 +18,24 @@ template <typename TReader, typename TStringStorage>
class JsonDeserializer {
typedef typename remove_reference<TStringStorage>::type::StringBuilder
StringBuilder;
typedef typename StringBuilder::StringType StringType;
public:
JsonDeserializer(MemoryPool &memoryPool, TReader reader,
JsonDeserializer(MemoryPool &pool, TReader reader,
TStringStorage stringStorage, uint8_t nestingLimit)
: _memoryPool(&memoryPool),
: _pool(&pool),
_reader(reader),
_stringStorage(stringStorage),
_nestingLimit(nestingLimit),
_loaded(false) {}
DeserializationError parse(JsonVariant variant) {
DeserializationError err = skipSpacesAndComments();
if (err) return err;
DeserializationError parse(VariantData &variant) {
DeserializationError err = parseVariant(variant);
switch (current()) {
case '[':
return parseArray(variant);
case '{':
return parseObject(variant);
default:
return parseValue(variant);
if (!err && _current != 0 && !variant.isEnclosed()) {
// We don't detect trailing characters earlier, so we need to check now
err = DeserializationError::InvalidInput;
}
return err;
}
private:
@ -49,10 +43,8 @@ class JsonDeserializer {
char current() {
if (!_loaded) {
if (_reader.ended())
_current = 0;
else
_current = _reader.read();
int c = _reader.read();
_current = static_cast<char>(c > 0 ? c : 0);
_loaded = true;
}
return _current;
@ -68,11 +60,28 @@ class JsonDeserializer {
return true;
}
DeserializationError parseArray(JsonVariant variant) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
DeserializationError parseVariant(VariantData &variant) {
DeserializationError err = skipSpacesAndComments();
if (err) return err;
JsonArray array = variant.to<JsonArray>();
if (array.isNull()) return DeserializationError::NoMemory;
switch (current()) {
case '[':
return parseArray(variant.toArray());
case '{':
return parseObject(variant.toObject());
case '\"':
case '\'':
return parseStringValue(variant);
default:
return parseNumericValue(variant);
}
}
DeserializationError parseArray(CollectionData &array) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
// Check opening braket
if (!eat('[')) return DeserializationError::InvalidInput;
@ -87,12 +96,12 @@ class JsonDeserializer {
// Read each value
for (;;) {
// Allocate slot in array
JsonVariant value = array.add();
if (value.isInvalid()) return DeserializationError::NoMemory;
VariantData *value = array.add(_pool);
if (!value) return DeserializationError::NoMemory;
// 1 - Parse value
_nestingLimit--;
err = parse(value);
err = parseVariant(*value);
_nestingLimit++;
if (err) return err;
@ -106,12 +115,9 @@ class JsonDeserializer {
}
}
DeserializationError parseObject(JsonVariant variant) {
DeserializationError parseObject(CollectionData &object) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonObject object = variant.to<JsonObject>();
if (object.isNull()) return DeserializationError::NoMemory;
// Check opening brace
if (!eat('{')) return DeserializationError::InvalidInput;
@ -124,23 +130,24 @@ class JsonDeserializer {
// Read each key value pair
for (;;) {
// Allocate slot in object
VariantSlot *slot = object.addSlot(_pool);
if (!slot) return DeserializationError::NoMemory;
// Parse key
StringType key;
const char *key;
err = parseKey(key);
if (err) return err;
slot->setOwnedKey(make_not_null(key));
// Skip spaces
err = skipSpacesAndComments();
if (err) return err; // Colon
if (!eat(':')) return DeserializationError::InvalidInput;
// Allocate slot in object
JsonVariant value = object.set(key);
if (value.isInvalid()) return DeserializationError::NoMemory;
// Parse value
_nestingLimit--;
err = parse(value);
err = parseVariant(*slot->data());
_nestingLimit++;
if (err) return err;
@ -158,15 +165,7 @@ class JsonDeserializer {
}
}
DeserializationError parseValue(JsonVariant variant) {
if (isQuote(current())) {
return parseStringValue(variant);
} else {
return parseNumericValue(variant);
}
}
DeserializationError parseKey(StringType &key) {
DeserializationError parseKey(const char *&key) {
if (isQuote(current())) {
return parseQuotedString(key);
} else {
@ -174,15 +173,15 @@ class JsonDeserializer {
}
}
DeserializationError parseStringValue(JsonVariant variant) {
StringType value;
DeserializationError parseStringValue(VariantData &variant) {
const char *value;
DeserializationError err = parseQuotedString(value);
if (err) return err;
variant.set(value);
variant.setOwnedString(make_not_null(value));
return DeserializationError::Ok;
}
DeserializationError parseQuotedString(StringType &result) {
DeserializationError parseQuotedString(const char *&result) {
StringBuilder builder = _stringStorage.startString();
const char stopChar = current();
@ -197,7 +196,18 @@ class JsonDeserializer {
if (c == '\\') {
c = current();
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == 'u') return DeserializationError::NotSupported;
if (c == 'u') {
#if ARDUINOJSON_DECODE_UNICODE
uint16_t codepoint;
move();
DeserializationError err = parseCodepoint(codepoint);
if (err) return err;
Utf8::encodeCodepoint(codepoint, builder);
continue;
#else
return DeserializationError::NotSupported;
#endif
}
// replace char
c = EscapeSequence::unescapeChar(c);
if (c == '\0') return DeserializationError::InvalidInput;
@ -208,11 +218,11 @@ class JsonDeserializer {
}
result = builder.complete();
if (result.isNull()) return DeserializationError::NoMemory;
if (!result) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
DeserializationError parseNonQuotedString(StringType &result) {
DeserializationError parseNonQuotedString(const char *&result) {
StringBuilder builder = _stringStorage.startString();
char c = current();
@ -229,11 +239,11 @@ class JsonDeserializer {
}
result = builder.complete();
if (result.isNull()) return DeserializationError::NoMemory;
if (!result) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
DeserializationError parseNumericValue(JsonVariant result) {
DeserializationError parseNumericValue(VariantData &result) {
char buffer[64];
uint8_t n = 0;
@ -245,18 +255,51 @@ class JsonDeserializer {
}
buffer[n] = 0;
if (isInteger(buffer)) {
result.set(parseInteger<JsonInteger>(buffer));
} else if (isFloat(buffer)) {
result.set(parseFloat<JsonFloat>(buffer));
} else if (!strcmp(buffer, "true")) {
result.set(true);
} else if (!strcmp(buffer, "false")) {
result.set(false);
} else if (!strcmp(buffer, "null")) {
// already null
} else {
return DeserializationError::InvalidInput;
c = buffer[0];
if (c == 't') { // true
result.setBoolean(true);
return n == 4 ? DeserializationError::Ok
: DeserializationError::IncompleteInput;
}
if (c == 'f') { // false
result.setBoolean(false);
return n == 5 ? DeserializationError::Ok
: DeserializationError::IncompleteInput;
}
if (c == 'n') { // null
// the variant is already null
return n == 4 ? DeserializationError::Ok
: DeserializationError::IncompleteInput;
}
ParsedNumber<Float, UInt> num = parseNumber<Float, UInt>(buffer);
switch (num.type()) {
case VALUE_IS_NEGATIVE_INTEGER:
result.setNegativeInteger(num.uintValue);
return DeserializationError::Ok;
case VALUE_IS_POSITIVE_INTEGER:
result.setPositiveInteger(num.uintValue);
return DeserializationError::Ok;
case VALUE_IS_FLOAT:
result.setFloat(num.floatValue);
return DeserializationError::Ok;
}
return DeserializationError::InvalidInput;
}
DeserializationError parseCodepoint(uint16_t &codepoint) {
codepoint = 0;
for (uint8_t i = 0; i < 4; ++i) {
char digit = current();
if (!digit) return DeserializationError::IncompleteInput;
uint8_t value = decodeHex(digit);
if (value > 0x0F) return DeserializationError::InvalidInput;
codepoint = uint16_t((codepoint << 4) | value);
move();
}
return DeserializationError::Ok;
}
@ -274,6 +317,12 @@ class JsonDeserializer {
return c == '\'' || c == '\"';
}
static inline uint8_t decodeHex(char c) {
if (c < 'A') return uint8_t(c - '0');
c = char(c & ~0x20); // uppercase
return uint8_t(c - 'A' + 10);
}
DeserializationError skipSpacesAndComments() {
for (;;) {
switch (current()) {
@ -333,7 +382,7 @@ class JsonDeserializer {
}
}
MemoryPool *_memoryPool;
MemoryPool *_pool;
TReader _reader;
TStringStorage _stringStorage;
uint8_t _nestingLimit;
@ -341,24 +390,31 @@ class JsonDeserializer {
bool _loaded;
};
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, const TInput &input) {
return deserialize<JsonDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, const TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input) {
return deserialize<JsonDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, TInput *input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input,
size_t inputSize) {
return deserialize<JsonDeserializer>(doc, input, inputSize);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, TInput *input, size_t inputSize,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput &input) {
return deserialize<JsonDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,91 +1,100 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Misc/Visitable.hpp"
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "../Visitable.hpp"
#include "JsonWriter.hpp"
#include "TextFormatter.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class JsonSerializer {
public:
JsonSerializer(TWriter &writer) : _writer(writer) {}
JsonSerializer(TWriter &writer) : _formatter(writer) {}
void visitFloat(JsonFloat value) {
_writer.writeFloat(value);
}
FORCE_INLINE void visitArray(const CollectionData &array) {
write('[');
void visitArray(JsonArrayConst array) {
_writer.beginArray();
VariantSlot *slot = array.head();
JsonArrayConst::iterator it = array.begin();
while (it != array.end()) {
it->accept(*this);
while (slot != 0) {
slot->data()->accept(*this);
++it;
if (it == array.end()) break;
slot = slot->next();
if (slot == 0) break;
_writer.writeComma();
write(',');
}
_writer.endArray();
write(']');
}
void visitObject(JsonObjectConst object) {
_writer.beginObject();
void visitObject(const CollectionData &object) {
write('{');
JsonObjectConst::iterator it = object.begin();
while (it != object.end()) {
_writer.writeString(it->key());
_writer.writeColon();
it->value().accept(*this);
VariantSlot *slot = object.head();
++it;
if (it == object.end()) break;
while (slot != 0) {
_formatter.writeString(slot->key());
write(':');
slot->data()->accept(*this);
_writer.writeComma();
slot = slot->next();
if (slot == 0) break;
write(',');
}
_writer.endObject();
write('}');
}
void visitFloat(Float value) {
_formatter.writeFloat(value);
}
void visitString(const char *value) {
_writer.writeString(value);
_formatter.writeString(value);
}
void visitRawJson(const char *data, size_t n) {
// TODO
for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]);
_formatter.writeRaw(data, n);
}
void visitNegativeInteger(JsonUInt value) {
_writer.writeRaw('-');
_writer.writeInteger(value);
void visitNegativeInteger(UInt value) {
_formatter.writeNegativeInteger(value);
}
void visitPositiveInteger(JsonUInt value) {
_writer.writeInteger(value);
void visitPositiveInteger(UInt value) {
_formatter.writePositiveInteger(value);
}
void visitBoolean(bool value) {
_writer.writeBoolean(value);
_formatter.writeBoolean(value);
}
void visitNull() {
_writer.writeRaw("null");
_formatter.writeRaw("null");
}
size_t bytesWritten() const {
return _writer.bytesWritten();
return _formatter.bytesWritten();
}
protected:
void write(char c) {
_formatter.writeRaw(c);
}
void write(const char *s) {
_formatter.writeRaw(s);
}
private:
JsonWriter<TWriter> _writer;
TextFormatter<TWriter> _formatter;
};
template <typename TSource, typename TDestination>

View File

@ -1,40 +1,71 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Configuration.hpp"
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "./IndentedPrint.hpp"
#include "./JsonSerializer.hpp"
#include "./Prettyfier.hpp"
#include "JsonSerializer.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TPrint>
class PrettyJsonSerializer_Base {
public:
PrettyJsonSerializer_Base(TPrint &output)
: _indentedPrint(output), _prettyfier(_indentedPrint) {}
template <typename TWriter>
class PrettyJsonSerializer : public JsonSerializer<TWriter> {
typedef JsonSerializer<TWriter> base;
protected:
IndentedPrint<TPrint> _indentedPrint;
Prettyfier<TPrint> _prettyfier;
};
template <typename TPrint>
class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>,
public JsonSerializer<Prettyfier<TPrint> > {
public:
PrettyJsonSerializer(TPrint &output)
: PrettyJsonSerializer_Base<TPrint>(output),
JsonSerializer<Prettyfier<TPrint> >(
PrettyJsonSerializer_Base<TPrint>::_prettyfier) {}
PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
void visitArray(const CollectionData &array) {
VariantSlot *slot = array.head();
if (!slot) return base::write("[]");
base::write("[\r\n");
_nesting++;
while (slot != 0) {
indent();
slot->data()->accept(*this);
slot = slot->next();
base::write(slot ? ",\r\n" : "\r\n");
}
_nesting--;
indent();
base::write("]");
}
void visitObject(const CollectionData &object) {
VariantSlot *slot = object.head();
if (!slot) return base::write("{}");
base::write("{\r\n");
_nesting++;
while (slot != 0) {
indent();
base::visitString(slot->key());
base::write(": ");
slot->data()->accept(*this);
slot = slot->next();
base::write(slot ? ",\r\n" : "\r\n");
}
_nesting--;
indent();
base::write("}");
}
private:
void indent() {
for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB);
}
uint8_t _nesting;
};
template <typename TSource, typename TDestination>
size_t serializeJsonPretty(TSource &source, TDestination &destination) {
size_t serializeJsonPretty(const TSource &source, TDestination &destination) {
return serialize<PrettyJsonSerializer>(source, destination);
}

View File

@ -1,143 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "IndentedPrint.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Converts a compact JSON string into an indented one.
template <typename TWriter>
class Prettyfier {
public:
explicit Prettyfier(IndentedPrint<TWriter>& p) : _sink(p) {
_previousChar = 0;
_inString = false;
}
size_t write(uint8_t c) {
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(char(c));
_previousChar = char(c);
return n;
}
size_t write(const uint8_t* s, size_t n) {
// TODO: optimize
size_t bytesWritten = 0;
while (n > 0) {
bytesWritten += write(*s++);
n--;
}
return bytesWritten;
}
private:
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
bool inEmptyBlock() {
return _previousChar == '{' || _previousChar == '[';
}
size_t handleStringChar(uint8_t c) {
bool isQuote = c == '"' && _previousChar != '\\';
if (isQuote) _inString = false;
return _sink.write(c);
}
size_t handleMarkupChar(char c) {
switch (c) {
case '{':
case '[':
return writeBlockOpen(c);
case '}':
case ']':
return writeBlockClose(c);
case ':':
return writeColon();
case ',':
return writeComma();
case '"':
return writeQuoteOpen();
default:
return writeNormalChar(c);
}
}
size_t writeBlockClose(char c) {
size_t n = 0;
n += unindentIfNeeded();
n += write(c);
return n;
}
size_t writeBlockOpen(char c) {
size_t n = 0;
n += indentIfNeeded();
n += write(c);
return n;
}
size_t writeColon() {
size_t n = 0;
n += write(": ");
return n;
}
size_t writeComma() {
size_t n = 0;
n += write(",\r\n");
return n;
}
size_t writeQuoteOpen() {
_inString = true;
size_t n = 0;
n += indentIfNeeded();
n += write('"');
return n;
}
size_t writeNormalChar(char c) {
size_t n = 0;
n += indentIfNeeded();
n += write(c);
return n;
}
size_t indentIfNeeded() {
if (!inEmptyBlock()) return 0;
_sink.indent();
return write("\r\n");
}
size_t unindentIfNeeded() {
if (inEmptyBlock()) return 0;
_sink.unindent();
return write("\r\n");
}
size_t write(char c) {
return _sink.write(static_cast<uint8_t>(c));
}
template <size_t N>
size_t write(const char (&s)[N]) {
return _sink.write(reinterpret_cast<const uint8_t*>(s), N - 1);
}
char _previousChar;
IndentedPrint<TWriter>& _sink;
bool _inString;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,49 +1,28 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <stdint.h>
#include <string.h> // for strlen
#include "../Data/JsonInteger.hpp"
#include "../Numbers/FloatParts.hpp"
#include "../Numbers/Integer.hpp"
#include "../Polyfills/attributes.hpp"
#include "./EscapeSequence.hpp"
#include "EscapeSequence.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class JsonWriter {
class TextFormatter {
public:
explicit JsonWriter(TWriter &writer) : _writer(writer), _length(0) {}
explicit TextFormatter(TWriter &writer) : _writer(writer), _length(0) {}
// Returns the number of bytes sent to the TWriter implementation.
size_t bytesWritten() const {
return _length;
}
void beginArray() {
writeRaw('[');
}
void endArray() {
writeRaw(']');
}
void beginObject() {
writeRaw('{');
}
void endObject() {
writeRaw('}');
}
void writeColon() {
writeRaw(':');
}
void writeComma() {
writeRaw(',');
}
void writeBoolean(bool value) {
if (value)
writeRaw("true");
@ -71,35 +50,49 @@ class JsonWriter {
}
}
template <typename TFloat>
void writeFloat(TFloat value) {
if (isnan(value)) return writeRaw("NaN");
template <typename T>
void writeFloat(T value) {
if (isnan(value)) return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
#if ARDUINOJSON_ENABLE_INFINITY
if (value < 0.0) {
writeRaw('-');
value = -value;
}
if (isinf(value)) return writeRaw("Infinity");
#else
if (isinf(value)) return writeRaw("null");
FloatParts<TFloat> parts(value);
if (value < 0.0) {
writeRaw('-');
value = -value;
}
#endif
writeInteger(parts.integral);
FloatParts<T> parts(value);
writePositiveInteger(parts.integral);
if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces);
if (parts.exponent < 0) {
writeRaw("e-");
writeInteger(-parts.exponent);
writePositiveInteger(-parts.exponent);
}
if (parts.exponent > 0) {
writeRaw('e');
writeInteger(parts.exponent);
writePositiveInteger(parts.exponent);
}
}
template <typename UInt>
void writeInteger(UInt value) {
void writeNegativeInteger(UInt value) {
writeRaw('-');
writePositiveInteger(value);
}
template <typename T>
void writePositiveInteger(T value) {
char buffer[22];
char *end = buffer + sizeof(buffer);
char *begin = end;
@ -107,7 +100,7 @@ class JsonWriter {
// write the string in reverse order
do {
*--begin = char(value % 10 + '0');
value = UInt(value / 10);
value = T(value / 10);
} while (value);
// and dump it in the right order
@ -134,10 +127,16 @@ class JsonWriter {
void writeRaw(const char *s) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
}
void writeRaw(const char *s, size_t n) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), n);
}
void writeRaw(const char *begin, const char *end) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(begin),
static_cast<size_t>(end - begin));
}
template <size_t N>
void writeRaw(const char (&s)[N]) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
@ -151,6 +150,6 @@ class JsonWriter {
size_t _length;
private:
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
TextFormatter &operator=(const TextFormatter &); // cannot be assigned
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,26 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
namespace Utf8 {
template <typename TStringBuilder>
inline void encodeCodepoint(uint16_t codepoint, TStringBuilder &str) {
if (codepoint < 0x80) {
str.append(char(codepoint));
return;
}
if (codepoint >= 0x00000800) {
str.append(char(0xe0 /*0b11100000*/ | (codepoint >> 12)));
str.append(char(((codepoint >> 6) & 0x3f /*0b00111111*/) | 0x80));
} else {
str.append(char(0xc0 /*0b11000000*/ | (codepoint >> 6)));
}
str.append(char((codepoint & 0x3f /*0b00111111*/) | 0x80));
}
} // namespace Utf8
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,221 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/ArrayFunctions.hpp"
#include "Data/JsonVariantData.hpp"
#include "JsonArrayIterator.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 JsonObject;
class JsonArraySubscript;
template <typename TData>
class JsonArrayProxy {
public:
FORCE_INLINE bool isNull() const {
return _data == 0;
}
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
return JsonVariantConst(arrayGet(_data, index));
}
FORCE_INLINE size_t size() const {
return arraySize(_data);
}
protected:
JsonArrayProxy(TData* data) : _data(data) {}
TData* _data;
};
class JsonArrayConst : public JsonArrayProxy<const JsonArrayData>,
public Visitable {
friend class JsonArray;
typedef JsonArrayProxy<const JsonArrayData> proxy_type;
public:
typedef JsonArrayConstIterator iterator;
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
if (_data)
visitor.visitArray(*this);
else
visitor.visitNull();
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_data->head);
}
FORCE_INLINE iterator end() const {
return iterator();
}
FORCE_INLINE JsonArrayConst() : proxy_type(0) {}
FORCE_INLINE JsonArrayConst(const JsonArrayData* data) : proxy_type(data) {}
FORCE_INLINE bool operator==(JsonArrayConst rhs) const {
return arrayEquals(_data, rhs._data);
}
};
class JsonArray : public JsonArrayProxy<JsonArrayData>, public Visitable {
typedef JsonArrayProxy<JsonArrayData> proxy_type;
public:
typedef JsonArrayIterator iterator;
FORCE_INLINE JsonArray() : proxy_type(0), _memoryPool(0) {}
FORCE_INLINE JsonArray(MemoryPool* pool, JsonArrayData* data)
: proxy_type(data), _memoryPool(pool) {}
operator JsonVariant() {
return JsonVariant(_memoryPool, getVariantData(_data));
}
operator JsonArrayConst() const {
return JsonArrayConst(_data);
}
// Adds the specified value at the end of the array.
//
// bool add(TValue);
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonObject
template <typename T>
FORCE_INLINE bool add(const T& value) const {
return add().set(value);
}
// Adds the specified value at the end of the array.
FORCE_INLINE bool add(JsonArray value) const {
return add().set(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
FORCE_INLINE bool add(T* value) const {
return add().set(value);
}
JsonVariant add() const {
return JsonVariant(_memoryPool, arrayAdd(_data, _memoryPool));
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_memoryPool, _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++) {
JsonArray nestedArray = createNestedArray();
for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(array[i][j]);
}
}
return ok;
}
// Copy a JsonArray
FORCE_INLINE bool copyFrom(JsonArray src) const {
return arrayCopy(_data, src._data, _memoryPool);
}
// 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<JsonArray>().copyTo(array[i++]);
}
}
FORCE_INLINE JsonArray createNestedArray() const;
FORCE_INLINE JsonObject createNestedObject() const;
FORCE_INLINE JsonArraySubscript operator[](size_t index) const;
FORCE_INLINE bool operator==(JsonArray rhs) const {
return arrayEquals(_data, rhs._data);
}
// Gets the value at the specified index.
FORCE_INLINE JsonVariant get(size_t index) const {
return JsonVariant(_memoryPool, arrayGet(_data, index));
}
// Removes element at specified position.
FORCE_INLINE void remove(iterator it) const {
arrayRemove(_data, it.internal(), _memoryPool);
}
// Removes element at specified index.
FORCE_INLINE void remove(size_t index) const {
arrayRemove(_data, index, _memoryPool);
}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
JsonArrayConst(_data).accept(visitor);
}
private:
template <typename TValueRef>
FORCE_INLINE bool add_impl(TValueRef value) const {
return add().set(value);
}
MemoryPool* _memoryPool;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,19 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "JsonObject.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline JsonArray JsonArray::createNestedArray() const {
return add().to<JsonArray>();
}
inline JsonObject JsonArray::createNestedObject() const {
return add().to<JsonObject>();
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,122 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/SlotFunctions.hpp"
#include "JsonVariant.hpp"
namespace ARDUINOJSON_NAMESPACE {
class JsonVariantPtr {
public:
JsonVariantPtr(MemoryPool *memoryPool, JsonVariantData *data)
: _variant(memoryPool, data) {}
JsonVariant *operator->() {
return &_variant;
}
JsonVariant &operator*() {
return _variant;
}
private:
JsonVariant _variant;
};
class JsonArrayIterator {
public:
JsonArrayIterator() : _slot(0) {}
explicit JsonArrayIterator(MemoryPool *memoryPool, VariantSlot *slot)
: _memoryPool(memoryPool), _slot(slot) {}
JsonVariant operator*() const {
return JsonVariant(_memoryPool, &_slot->value);
}
JsonVariantPtr operator->() {
return JsonVariantPtr(_memoryPool, &_slot->value);
}
bool operator==(const JsonArrayIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonArrayIterator &other) const {
return _slot != other._slot;
}
JsonArrayIterator &operator++() {
_slot = _slot->next;
return *this;
}
JsonArrayIterator &operator+=(size_t distance) {
_slot = slotAdvance(_slot, distance);
return *this;
}
VariantSlot *internal() {
return _slot;
}
private:
MemoryPool *_memoryPool;
VariantSlot *_slot;
};
class JsonVariantConstPtr {
public:
JsonVariantConstPtr(const JsonVariantData *data) : _variant(data) {}
JsonVariantConst *operator->() {
return &_variant;
}
JsonVariantConst &operator*() {
return _variant;
}
private:
JsonVariantConst _variant;
};
class JsonArrayConstIterator {
public:
JsonArrayConstIterator() : _slot(0) {}
explicit JsonArrayConstIterator(const VariantSlot *slot) : _slot(slot) {}
JsonVariantConst operator*() const {
return JsonVariantConst(&_slot->value);
}
JsonVariantConstPtr operator->() {
return JsonVariantConstPtr(&_slot->value);
}
bool operator==(const JsonArrayConstIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonArrayConstIterator &other) const {
return _slot != other._slot;
}
JsonArrayConstIterator &operator++() {
_slot = _slot->next;
return *this;
}
JsonArrayConstIterator &operator+=(size_t distance) {
_slot = slotAdvance(_slot, distance);
return *this;
}
const VariantSlot *internal() {
return _slot;
}
private:
const VariantSlot *_slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,113 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Configuration.hpp"
#include "JsonVariantBase.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE {
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript>,
public Visitable {
public:
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
: _array(array), _index(index) {}
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
get_impl().set(src.as<JsonVariantConst>());
return *this;
}
// Replaces the value
//
// operator=(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename T>
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
get_impl().set(src);
return *this;
}
//
// operator=(TValue)
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
FORCE_INLINE JsonArraySubscript& operator=(T* src) {
get_impl().set(src);
return *this;
}
FORCE_INLINE bool isNull() const {
return get_impl().isNull();
}
template <typename T>
FORCE_INLINE typename JsonVariantAs<T>::type as() const {
return get_impl().as<T>();
}
template <typename T>
FORCE_INLINE bool is() const {
return get_impl().is<T>();
}
template <typename T>
FORCE_INLINE typename JsonVariantTo<T>::type to() const {
return get_impl().to<T>();
}
// Replaces the value
//
// bool set(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue>
FORCE_INLINE bool set(const TValue& value) const {
return get_impl().set(value);
}
//
// bool set(TValue)
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(TValue* value) const {
return get_impl().set(value);
}
template <typename Visitor>
void accept(Visitor& visitor) const {
return get_impl().accept(visitor);
}
FORCE_INLINE size_t size() const {
return get_impl().size();
}
private:
FORCE_INLINE JsonVariant get_impl() const {
return _array.get(_index);
}
JsonArray _array;
const size_t _index;
};
template <typename TImpl>
inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
size_t index) const {
return impl()->template as<JsonArray>()[index];
}
inline JsonArraySubscript JsonArray::operator[](size_t index) const {
return JsonArraySubscript(*this, index);
}
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)
#endif

View File

@ -1,131 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/JsonVariantTo.hpp"
#include "JsonVariant.hpp"
#include "Memory/DynamicMemoryPool.hpp"
#include "Memory/StaticMemoryPool.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TMemoryPool>
class JsonDocument : public Visitable {
public:
uint8_t nestingLimit;
JsonDocument() : nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
template <typename Visitor>
void accept(Visitor& visitor) const {
return getVariant().accept(visitor);
}
template <typename T>
typename JsonVariantAs<T>::type as() {
return getVariant().template as<T>();
}
template <typename T>
typename JsonVariantConstAs<T>::type as() const {
return getVariant().template as<T>();
}
void clear() {
_memoryPool.clear();
_rootData.type = JSON_NULL;
}
template <typename T>
bool is() const {
return getVariant().template is<T>();
}
size_t memoryUsage() const {
return _memoryPool.size();
}
TMemoryPool& memoryPool() {
return _memoryPool;
}
template <typename T>
typename JsonVariantTo<T>::type to() {
clear();
return getVariant().template to<T>();
}
protected:
template <typename T>
void copy(const JsonDocument<T>& src) {
nestingLimit = src.nestingLimit;
to<JsonVariant>().set(src.template as<JsonVariant>());
}
private:
JsonVariant getVariant() {
return JsonVariant(&_memoryPool, &_rootData);
}
JsonVariantConst getVariant() const {
return JsonVariantConst(&_rootData);
}
TMemoryPool _memoryPool;
JsonVariantData _rootData;
};
class DynamicJsonDocument : public JsonDocument<DynamicMemoryPool> {
public:
DynamicJsonDocument() {}
DynamicJsonDocument(size_t capacity) {
memoryPool().reserve(capacity);
}
DynamicJsonDocument(const DynamicJsonDocument& src) {
memoryPool().reserve(src.memoryUsage());
copy(src);
}
template <typename T>
DynamicJsonDocument(const JsonDocument<T>& src) {
memoryPool().reserve(src.memoryUsage());
copy(src);
}
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
copy(src);
return *this;
}
template <typename T>
DynamicJsonDocument& operator=(const JsonDocument<T>& src) {
copy(src);
return *this;
}
};
template <size_t CAPACITY>
class StaticJsonDocument : public JsonDocument<StaticMemoryPool<CAPACITY> > {
public:
StaticJsonDocument() {}
template <typename T>
StaticJsonDocument(const JsonDocument<T>& src) {
this->copy(src);
}
StaticMemoryPoolBase& memoryPool() {
return JsonDocument<StaticMemoryPool<CAPACITY> >::memoryPool();
}
template <typename T>
StaticJsonDocument operator=(const JsonDocument<T>& src) {
this->copy(src);
return *this;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,33 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class JsonKey {
public:
JsonKey(const VariantSlot* slot) : _slot(slot) {}
operator const char*() const {
return c_str();
}
const char* c_str() const {
return _slot ? slotGetKey(_slot) : 0;
}
bool isNull() const {
return _slot == 0 || _slot->linkedKey == 0;
}
friend bool operator==(JsonKey lhs, const char* rhs) {
if (lhs.isNull()) return rhs == 0;
return rhs ? !strcmp(lhs, rhs) : false;
}
private:
const VariantSlot* _slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,290 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/ObjectFunctions.hpp"
#include "JsonObjectIterator.hpp"
// Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
namespace ARDUINOJSON_NAMESPACE {
template <typename TData>
class JsonObjectProxy {
public:
// Tells weither the specified key is present and associated with a value.
//
// bool containsKey(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE bool containsKey(const TKey& key) const {
return objectContainsKey(_data, makeString(key));
}
//
// bool containsKey(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TKey>
FORCE_INLINE bool containsKey(TKey* key) const {
return objectContainsKey(_data, makeString(key));
}
FORCE_INLINE bool isNull() const {
return _data == 0;
}
FORCE_INLINE size_t size() const {
return objectSize(_data);
}
protected:
JsonObjectProxy(TData* data) : _data(data) {}
TData* _data;
};
class JsonObjectConst : public JsonObjectProxy<const JsonObjectData>,
public Visitable {
friend class JsonObject;
typedef JsonObjectProxy<const JsonObjectData> proxy_type;
public:
typedef JsonObjectConstIterator iterator;
JsonObjectConst() : proxy_type(0) {}
JsonObjectConst(const JsonObjectData* data) : proxy_type(data) {}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
if (_data)
visitor.visitObject(*this);
else
visitor.visitNull();
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_data->head);
}
FORCE_INLINE iterator end() const {
return iterator();
}
// Gets the value associated with the specified key.
//
// TValue get<TValue>(TKey) const;
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArrayConst, JsonObjectConst
template <typename TKey>
FORCE_INLINE JsonVariantConst get(const TKey& key) const {
return get_impl(makeString(key));
}
//
// TValue get<TValue>(TKey) const;
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArrayConst, JsonObjectConst
template <typename TKey>
FORCE_INLINE JsonVariantConst get(TKey* key) const {
return get_impl(makeString(key));
}
//
// JsonVariantConst operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey>::value, JsonVariantConst>::type
operator[](const TKey& key) const {
return get_impl(makeString(key));
}
//
// JsonVariantConst operator[](TKey) const;
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TKey>
FORCE_INLINE
typename enable_if<IsString<TKey*>::value, JsonVariantConst>::type
operator[](TKey* key) const {
return get_impl(makeString(key));
}
FORCE_INLINE bool operator==(JsonObjectConst rhs) const {
return objectEquals(_data, rhs._data);
}
private:
template <typename TKey>
FORCE_INLINE JsonVariantConst get_impl(TKey key) const {
return JsonVariantConst(objectGet(_data, key));
}
};
class JsonObject : public JsonObjectProxy<JsonObjectData>, public Visitable {
typedef JsonObjectProxy<JsonObjectData> proxy_type;
public:
typedef JsonObjectIterator iterator;
FORCE_INLINE JsonObject() : proxy_type(0), _memoryPool(0) {}
FORCE_INLINE JsonObject(MemoryPool* buf, JsonObjectData* data)
: proxy_type(data), _memoryPool(buf) {}
operator JsonVariant() const {
return JsonVariant(_memoryPool, getVariantData(_data));
}
operator JsonObjectConst() const {
return JsonObjectConst(_data);
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_memoryPool, _data->head);
}
FORCE_INLINE iterator end() const {
return iterator();
}
void clear() const {
objectClear(_data);
}
FORCE_INLINE bool copyFrom(JsonObjectConst src) {
return objectCopy(_data, src._data, _memoryPool);
}
// Creates and adds a JsonArray.
//
// JsonArray createNestedArray(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE JsonArray createNestedArray(const TKey& key) const;
// JsonArray createNestedArray(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TKey>
FORCE_INLINE JsonArray createNestedArray(TKey* key) const;
// Creates and adds a JsonObject.
//
// JsonObject createNestedObject(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE JsonObject createNestedObject(const TKey& key) const {
return set(key).template to<JsonObject>();
}
//
// JsonObject createNestedObject(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TKey>
FORCE_INLINE JsonObject createNestedObject(TKey* key) const {
return set(key).template to<JsonObject>();
}
// Gets the value associated with the specified key.
//
// TValue get<TValue>(TKey) const;
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TKey>
FORCE_INLINE JsonVariant get(const TKey& key) const {
return get_impl(makeString(key));
}
//
// TValue get<TValue>(TKey) const;
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TKey>
FORCE_INLINE JsonVariant get(TKey* key) const {
return get_impl(makeString(key));
}
// Gets or sets the value associated with the specified key.
//
// JsonObjectSubscript operator[](TKey)
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE JsonObjectSubscript<const TKey&> operator[](
const TKey& key) const {
return JsonObjectSubscript<const TKey&>(*this, key);
}
//
// JsonObjectSubscript operator[](TKey)
// TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
template <typename TKey>
FORCE_INLINE JsonObjectSubscript<TKey*> operator[](TKey* key) const {
return JsonObjectSubscript<TKey*>(*this, key);
}
FORCE_INLINE bool operator==(JsonObject rhs) const {
return objectEquals(_data, rhs._data);
}
FORCE_INLINE void remove(iterator it) const {
objectRemove(_data, it.internal(), _memoryPool);
}
// Removes the specified key and the associated value.
//
// void remove(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE void remove(const TKey& key) const {
remove_impl(makeString(key));
}
//
// void remove(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TKey>
FORCE_INLINE void remove(TKey* key) const {
remove_impl(makeString(key));
}
template <typename TKey>
FORCE_INLINE JsonVariant set(TKey* key) const {
return set_impl(makeString(key));
}
template <typename TKey>
FORCE_INLINE JsonVariant set(const TKey& key) const {
return set_impl(makeString(key));
}
FORCE_INLINE JsonVariant set(StringInMemoryPool key) const {
return set_impl(key);
}
FORCE_INLINE JsonVariant set(ZeroTerminatedRamStringConst key) const {
return set_impl(key);
}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
JsonObjectConst(_data).accept(visitor);
}
private:
template <typename TStringRef>
FORCE_INLINE JsonVariant get_impl(TStringRef key) const {
return JsonVariant(_memoryPool, objectGet(_data, key));
}
template <typename TKey>
FORCE_INLINE JsonVariant set_impl(TKey key) const {
return JsonVariant(_memoryPool, objectSet(_data, key, _memoryPool));
}
template <typename TStringRef>
FORCE_INLINE void remove_impl(TStringRef key) const {
objectRemove(_data, objectFindSlot(_data, key), _memoryPool);
}
MemoryPool* _memoryPool;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,21 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "JsonObject.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TString>
inline JsonArray JsonObject::createNestedArray(const TString& key) const {
return set(key).template to<JsonArray>();
}
template <typename TString>
inline JsonArray JsonObject::createNestedArray(TString* key) const {
return set(key).template to<JsonArray>();
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,124 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/SlotFunctions.hpp"
#include "JsonPair.hpp"
namespace ARDUINOJSON_NAMESPACE {
class JsonPairPtr {
public:
JsonPairPtr(MemoryPool *memoryPool, VariantSlot *slot)
: _pair(memoryPool, slot) {}
const JsonPair *operator->() const {
return &_pair;
}
const JsonPair &operator*() const {
return _pair;
}
private:
JsonPair _pair;
};
class JsonObjectIterator {
public:
JsonObjectIterator() : _slot(0) {}
explicit JsonObjectIterator(MemoryPool *memoryPool, VariantSlot *slot)
: _memoryPool(memoryPool), _slot(slot) {}
JsonPair operator*() const {
return JsonPair(_memoryPool, _slot);
}
JsonPairPtr operator->() {
return JsonPairPtr(_memoryPool, _slot);
}
bool operator==(const JsonObjectIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonObjectIterator &other) const {
return _slot != other._slot;
}
JsonObjectIterator &operator++() {
if (_slot) _slot = _slot->next;
return *this;
}
JsonObjectIterator &operator+=(size_t distance) {
_slot = slotAdvance(_slot, distance);
return *this;
}
VariantSlot *internal() {
return _slot;
}
private:
MemoryPool *_memoryPool;
VariantSlot *_slot;
};
class JsonPairConstPtr {
public:
JsonPairConstPtr(const VariantSlot *slot) : _pair(slot) {}
const JsonPairConst *operator->() const {
return &_pair;
}
const JsonPairConst &operator*() const {
return _pair;
}
private:
JsonPairConst _pair;
};
class JsonObjectConstIterator {
public:
JsonObjectConstIterator() : _slot(0) {}
explicit JsonObjectConstIterator(const VariantSlot *slot) : _slot(slot) {}
JsonPairConst operator*() const {
return JsonPairConst(_slot);
}
JsonPairConstPtr operator->() {
return JsonPairConstPtr(_slot);
}
bool operator==(const JsonObjectConstIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonObjectConstIterator &other) const {
return _slot != other._slot;
}
JsonObjectConstIterator &operator++() {
if (_slot) _slot = _slot->next;
return *this;
}
JsonObjectConstIterator &operator+=(size_t distance) {
_slot = slotAdvance(_slot, distance);
return *this;
}
const VariantSlot *internal() {
return _slot;
}
private:
const VariantSlot *_slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,133 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Configuration.hpp"
#include "JsonVariantBase.hpp"
#include "Polyfills/type_traits.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE {
template <typename TStringRef>
class JsonObjectSubscript
: public JsonVariantBase<JsonObjectSubscript<TStringRef> >,
public Visitable {
typedef JsonObjectSubscript<TStringRef> this_type;
public:
FORCE_INLINE JsonObjectSubscript(JsonObject object, TStringRef key)
: _object(object), _key(key) {}
operator JsonVariantConst() const {
return get_impl();
}
FORCE_INLINE this_type &operator=(const this_type &src) {
set_impl().set(src);
return *this;
}
// Set the specified value
//
// operator=(const TValue&);
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
operator=(const TValue &src) {
set_impl().set(src);
return *this;
}
//
// operator=(TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE this_type &operator=(TValue *src) {
set_impl().set(src);
return *this;
}
FORCE_INLINE bool isNull() const {
return get_impl().isNull();
}
template <typename TValue>
FORCE_INLINE typename JsonVariantAs<TValue>::type as() const {
return get_impl().template as<TValue>();
}
template <typename TValue>
FORCE_INLINE bool is() const {
return get_impl().template is<TValue>();
}
template <typename TValue>
FORCE_INLINE typename JsonVariantTo<TValue>::type to() {
return set_impl().template to<TValue>();
}
// Sets the specified value.
//
// bool set(const TValue&);
// TValue = bool, char, long, int, short, float, double, serialized,
// JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
const TValue &value) {
return set_impl().set(value);
}
//
// bool set(TValue);
// TValue = char*, const char, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(const TValue *value) {
return set_impl().set(value);
}
template <typename Visitor>
void accept(Visitor &visitor) const {
return get_impl().accept(visitor);
}
private:
FORCE_INLINE JsonVariant get_impl() const {
return _object.get(_key);
}
FORCE_INLINE JsonVariant set_impl() const {
return _object.set(_key);
}
JsonObject _object;
TStringRef _key;
};
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
JsonObjectSubscript<const TString &> >::type
JsonVariantSubscripts<TImpl>::operator[](const TString &key) const {
return impl()->template as<JsonObject>()[key];
}
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString *>::value,
JsonObjectSubscript<TString *> >::type
JsonVariantSubscripts<TImpl>::operator[](TString *key) const {
return impl()->template as<JsonObject>()[key];
}
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)
#endif

View File

@ -1,53 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonKey.hpp"
#include "JsonVariant.hpp"
namespace ARDUINOJSON_NAMESPACE {
// A key value pair for JsonObjectData.
class JsonPair {
public:
JsonPair(MemoryPool* memoryPool, VariantSlot* slot) : _key(slot) {
if (slot) {
_value = JsonVariant(memoryPool, &slot->value);
}
}
JsonKey key() const {
return _key;
}
JsonVariant value() const {
return _value;
}
private:
JsonKey _key;
JsonVariant _value;
};
class JsonPairConst {
public:
JsonPairConst(const VariantSlot* slot) : _key(slot) {
if (slot) {
_value = JsonVariantConst(&slot->value);
}
}
JsonKey key() const {
return _key;
}
JsonVariantConst value() const {
return _value;
}
private:
JsonKey _key;
JsonVariantConst _value;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,330 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include "Data/JsonVariantData.hpp"
#include "Data/VariantAs.hpp"
#include "Data/VariantFunctions.hpp"
#include "JsonVariant.hpp"
#include "JsonVariantBase.hpp"
#include "Memory/MemoryPool.hpp"
#include "Numbers/parseFloat.hpp"
#include "Numbers/parseInteger.hpp"
#include "Polyfills/type_traits.hpp"
#include "Visitable.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Forward declarations.
class JsonArray;
class JsonObject;
// Contains the methods shared by JsonVariant and JsonVariantConst
template <typename TData>
class JsonVariantProxy {
public:
// Tells wether the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
//
// bool is<char>() const;
// bool is<signed char>() const;
// bool is<signed short>() const;
// bool is<signed int>() const;
// bool is<signed long>() const;
// bool is<unsigned char>() const;
// bool is<unsigned short>() const;
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_integral<T>::value, bool>::type is()
const {
return variantIsInteger(_data);
}
//
// bool is<double>() const;
// bool is<float>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
const {
return variantIsFloat(_data);
}
//
// bool is<bool>() const
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, bool>::value, bool>::type is()
const {
return _data && _data->type == JSON_BOOLEAN;
}
//
// bool is<const char*>() const;
// bool is<char*>() const;
// bool is<std::string>() const;
// bool is<String>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, const char *>::value ||
is_same<T, char *>::value ||
IsWriteableString<T>::value,
bool>::type
is() const {
return variantIsString(_data);
}
//
// bool is<JsonArray> const;
// bool is<const JsonArray> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, JsonArray>::value, bool>::type
is() const {
return variantIsArray(_data);
}
//
// bool is<JsonObject> const;
// bool is<const JsonObject> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, JsonObject>::value, bool>::type
is() const {
return variantIsObject(_data);
}
FORCE_INLINE bool isNull() const {
return variantIsNull(_data);
}
FORCE_INLINE bool isInvalid() const {
return _data == 0;
}
size_t size() const {
return objectSize(variantAsObject(_data)) +
arraySize(variantAsArray(_data));
}
protected:
JsonVariantProxy(TData *data) : _data(data) {}
TData *_data;
};
// A variant that can be a any value serializable to a JSON value.
//
// It can be set to:
// - a boolean
// - a char, short, int or a long (signed or unsigned)
// - a string (const char*)
// - a reference to a JsonArray or JsonObject
class JsonVariant : public JsonVariantProxy<JsonVariantData>,
public JsonVariantBase<JsonVariant>,
public Visitable {
typedef JsonVariantProxy<JsonVariantData> proxy_type;
friend class JsonVariantConst;
public:
// Intenal use only
FORCE_INLINE JsonVariant(MemoryPool *memoryPool, JsonVariantData *data)
: proxy_type(data), _memoryPool(memoryPool) {}
// Creates an uninitialized JsonVariant
FORCE_INLINE JsonVariant() : proxy_type(0), _memoryPool(0) {}
// set(bool value)
FORCE_INLINE bool set(bool value) const {
return variantSetBoolean(_data, value, _memoryPool);
}
// set(double value);
// set(float value);
template <typename T>
FORCE_INLINE bool set(
T value,
typename enable_if<is_floating_point<T>::value>::type * = 0) const {
return variantSetFloat(_data, static_cast<JsonFloat>(value), _memoryPool);
}
// set(char)
// set(signed short)
// set(signed int)
// set(signed long)
// set(signed char)
template <typename T>
FORCE_INLINE bool set(
T value,
typename enable_if<is_integral<T>::value && is_signed<T>::value>::type * =
0) const {
return variantSetSignedInteger(_data, value, _memoryPool);
}
// set(unsigned short)
// set(unsigned int)
// set(unsigned long)
template <typename T>
FORCE_INLINE bool set(
T value, typename enable_if<is_integral<T>::value &&
is_unsigned<T>::value>::type * = 0) const {
return variantSetUnsignedInteger(_data, static_cast<JsonUInt>(value),
_memoryPool);
}
// set(SerializedValue<const char *>)
FORCE_INLINE bool set(SerializedValue<const char *> value) const {
return variantSetLinkedRaw(_data, value, _memoryPool);
}
// set(SerializedValue<std::string>)
// set(SerializedValue<String>)
// set(SerializedValue<const __FlashStringHelper*>)
template <typename T>
FORCE_INLINE bool set(
SerializedValue<T> value,
typename enable_if<!is_same<const char *, T>::value>::type * = 0) const {
return variantSetOwnedRaw(_data, value, _memoryPool);
}
// set(const std::string&)
// set(const String&)
template <typename T>
FORCE_INLINE bool set(
const T &value,
typename enable_if<IsString<T>::value>::type * = 0) const {
return variantSetString(_data, makeString(value), _memoryPool);
}
// set(char*)
template <typename T>
FORCE_INLINE bool set(
T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
return variantSetString(_data, makeString(value), _memoryPool);
}
// set(const char*);
FORCE_INLINE bool set(const char *value) const {
return variantSetString(_data, value, _memoryPool);
}
// for internal use only
FORCE_INLINE bool set(StringInMemoryPool value) const {
return variantSetOwnedString(_data, value.slot(), _memoryPool);
}
FORCE_INLINE bool set(ZeroTerminatedRamStringConst value) const {
return variantSetString(_data, value.c_str(), _memoryPool);
}
bool set(JsonVariantConst value) const;
bool set(JsonVariant value) const;
FORCE_INLINE bool set(JsonArray array) const;
FORCE_INLINE bool set(const JsonArraySubscript &) const;
FORCE_INLINE bool set(JsonObject object) const;
template <typename TString>
FORCE_INLINE bool set(const JsonObjectSubscript<TString> &) const;
// Get the variant as the specified type.
//
// std::string as<std::string>() const;
// String as<String>() const;
template <typename T>
FORCE_INLINE typename enable_if<!is_same<T, JsonArray>::value &&
!is_same<T, JsonObject>::value &&
!is_same<T, JsonVariant>::value,
typename JsonVariantAs<T>::type>::type
as() const {
return variantAs<T>(_data);
}
//
// JsonArray as<JsonArray>() const;
// const JsonArray as<const JsonArray>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, JsonArray>::value, T>::type as()
const;
//
// JsonObject as<JsonObject>() const;
// const JsonObject as<const JsonObject>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, JsonObject>::value, T>::type as()
const;
//
// JsonVariant as<JsonVariant> const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, JsonVariant>::value, T>::type as()
const {
return *this;
}
template <typename Visitor>
void accept(Visitor &visitor) const;
FORCE_INLINE bool operator==(JsonVariant lhs) const {
return variantEquals(_data, lhs._data);
}
FORCE_INLINE bool operator!=(JsonVariant lhs) const {
return !variantEquals(_data, lhs._data);
}
// Change the type of the variant
//
// JsonArray to<JsonArray>()
template <typename T>
typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type to() const;
//
// JsonObject to<JsonObject>()
template <typename T>
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type to()
const;
//
// JsonObject to<JsonVariant>()
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type to()
const;
private:
MemoryPool *_memoryPool;
};
class JsonVariantConst : public JsonVariantProxy<const JsonVariantData>,
public JsonVariantBase<JsonVariantConst>,
public Visitable {
typedef JsonVariantProxy<const JsonVariantData> proxy_type;
friend class JsonVariant;
public:
JsonVariantConst() : proxy_type(0) {}
JsonVariantConst(const JsonVariantData *data) : proxy_type(data) {}
JsonVariantConst(JsonVariant var) : proxy_type(var._data) {}
template <typename Visitor>
void accept(Visitor &visitor) const;
// Get the variant as the specified type.
//
template <typename T>
FORCE_INLINE typename JsonVariantConstAs<T>::type as() const {
return variantAs<typename JsonVariantConstAs<T>::type>(_data);
}
FORCE_INLINE JsonVariantConst operator[](size_t index) const;
//
// const JsonVariantConst operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, JsonVariantConst>::type
operator[](const TString &key) const {
return JsonVariantConst(objectGet(variantAsObject(_data), makeString(key)));
}
//
// JsonVariantConst operator[](TKey);
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString *>::value, JsonVariantConst>::type
operator[](TString *key) const {
return JsonVariantConst(objectGet(variantAsObject(_data), makeString(key)));
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,19 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariantCasts.hpp"
#include "JsonVariantComparisons.hpp"
#include "JsonVariantOr.hpp"
#include "JsonVariantSubscripts.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TImpl>
class JsonVariantBase : public JsonVariantCasts<TImpl>,
public JsonVariantComparisons<TImpl>,
public JsonVariantOr<TImpl>,
public JsonVariantSubscripts<TImpl> {};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,161 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariant.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
struct is_simple_value {
static const bool value = is_integral<T>::value ||
is_floating_point<T>::value ||
is_same<T, bool>::value;
};
template <typename TVariant>
class JsonVariantComparisons {
public:
// const char* == TVariant
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator==(
T *lhs, TVariant rhs) {
return makeString(lhs).equals(rhs.template as<const char *>());
}
// std::string == TVariant
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator==(
const T &lhs, TVariant rhs) {
return makeString(lhs).equals(rhs.template as<const char *>());
}
// TVariant == const char*
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator==(
TVariant lhs, T *rhs) {
return makeString(rhs).equals(lhs.template as<const char *>());
}
// TVariant == std::string
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator==(
TVariant lhs, const T &rhs) {
return makeString(rhs).equals(lhs.template as<const char *>());
}
// bool/int/float == TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator==(
const T &lhs, TVariant rhs) {
return lhs == rhs.template as<T>();
}
// TVariant == bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator==(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() == rhs;
}
// const char* != TVariant
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
T *lhs, TVariant rhs) {
return !makeString(lhs).equals(rhs.template as<const char *>());
}
// std::string != TVariant
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator!=(
const T &lhs, TVariant rhs) {
return !makeString(lhs).equals(rhs.template as<const char *>());
}
// TVariant != const char*
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
TVariant lhs, T *rhs) {
return !makeString(rhs).equals(lhs.template as<const char *>());
}
// TVariant != std::string
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator!=(
TVariant lhs, const T &rhs) {
return !makeString(rhs).equals(lhs.template as<const char *>());
}
// bool/int/float != TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator!=(
const T &lhs, TVariant rhs) {
return lhs != rhs.template as<T>();
}
// TVariant != bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator!=(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() != rhs;
}
// bool/int/float < TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator<(
const T &lhs, TVariant rhs) {
return lhs < rhs.template as<T>();
}
// TVariant < bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator<(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() < rhs;
}
// bool/int/float <= TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator<=(
const T &lhs, TVariant rhs) {
return lhs <= rhs.template as<T>();
}
// TVariant <= bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator<=(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() <= rhs;
}
// bool/int/float > TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator>(
const T &lhs, TVariant rhs) {
return lhs > rhs.template as<T>();
}
// TVariant > bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator>(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() > rhs;
}
// bool/int/float >= TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator>=(
const T &lhs, TVariant rhs) {
return lhs >= rhs.template as<T>();
}
// TVariant >= bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator>=(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() >= rhs;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,123 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Configuration.hpp"
#include "JsonVariant.hpp"
#include "Numbers/parseFloat.hpp"
#include "Numbers/parseInteger.hpp"
#include <string.h> // for strcmp
namespace ARDUINOJSON_NAMESPACE {
inline bool JsonVariant::set(JsonArray array) const {
return to<JsonArray>().copyFrom(array);
}
inline bool JsonVariant::set(const JsonArraySubscript& value) const {
return set(value.as<JsonVariant>());
}
inline bool JsonVariant::set(JsonObject object) const {
return to<JsonObject>().copyFrom(object);
}
template <typename TString>
inline bool JsonVariant::set(const JsonObjectSubscript<TString>& value) const {
return set(value.template as<JsonVariant>());
}
inline bool JsonVariant::set(JsonVariantConst value) const {
return variantCopy(_data, value._data, _memoryPool);
}
inline bool JsonVariant::set(JsonVariant value) const {
return variantCopy(_data, value._data, _memoryPool);
}
template <typename T>
inline typename enable_if<is_same<T, JsonArray>::value, T>::type
JsonVariant::as() const {
return JsonArray(_memoryPool, variantAsArray(_data));
}
template <typename T>
inline typename enable_if<is_same<T, JsonObject>::value, T>::type
JsonVariant::as() const {
return JsonObject(_memoryPool, variantAsObject(_data));
}
template <typename T>
inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type
JsonVariant::to() const {
return JsonArray(_memoryPool, variantToArray(_data, _memoryPool));
}
template <typename T>
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type
JsonVariant::to() const {
return JsonObject(_memoryPool, variantToObject(_data, _memoryPool));
}
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type
JsonVariant::to() const {
variantSetNull(_data, _memoryPool);
return *this;
}
template <typename Visitor>
inline void JsonVariant::accept(Visitor& visitor) const {
return JsonVariantConst(_data).accept(visitor);
}
template <typename Visitor>
inline void JsonVariantConst::accept(Visitor& visitor) const {
if (!_data) return visitor.visitNull();
switch (_data->type) {
case JSON_FLOAT:
return visitor.visitFloat(_data->content.asFloat);
case JSON_ARRAY:
return visitor.visitArray(JsonArrayConst(&_data->content.asArray));
case JSON_OBJECT:
return visitor.visitObject(JsonObjectConst(&_data->content.asObject));
case JSON_LINKED_STRING:
return visitor.visitString(_data->content.asString);
case JSON_OWNED_STRING:
return visitor.visitString(_data->content.asOwnedString->value);
case JSON_OWNED_RAW:
return visitor.visitRawJson(_data->content.asOwnedRaw->value,
_data->content.asOwnedRaw->size);
case JSON_LINKED_RAW:
return visitor.visitRawJson(_data->content.asRaw.data,
_data->content.asRaw.size);
case JSON_NEGATIVE_INTEGER:
return visitor.visitNegativeInteger(_data->content.asInteger);
case JSON_POSITIVE_INTEGER:
return visitor.visitPositiveInteger(_data->content.asInteger);
case JSON_BOOLEAN:
return visitor.visitBoolean(_data->content.asInteger != 0);
default:
return visitor.visitNull();
}
}
inline JsonVariantConst JsonVariantConst::operator[](size_t index) const {
return JsonArrayConst(variantAsArray(_data))[index];
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,49 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/JsonVariantAs.hpp"
#include "Polyfills/attributes.hpp"
#include "Polyfills/type_traits.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TImpl>
class JsonVariantOr {
public:
// Returns the default value if the JsonVariant is undefined of incompatible
template <typename T>
typename enable_if<!is_integral<T>::value, T>::type operator|(
const T &defaultValue) const {
if (impl()->template is<T>())
return impl()->template as<T>();
else
return defaultValue;
}
// Returns the default value if the JsonVariant is undefined of incompatible
// Special case for string: null is treated as undefined
const char *operator|(const char *defaultValue) const {
const char *value = impl()->template as<const char *>();
return value ? value : defaultValue;
}
// Returns the default value if the JsonVariant is undefined of incompatible
// Special case for integers: we also accept double
template <typename Integer>
typename enable_if<is_integral<Integer>::value, Integer>::type operator|(
const Integer &defaultValue) const {
if (impl()->template is<double>())
return impl()->template as<Integer>();
else
return defaultValue;
}
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,51 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/JsonVariantAs.hpp"
#include "Polyfills/attributes.hpp"
#include "Polyfills/type_traits.hpp"
#include "Strings/StringTypes.hpp"
namespace ARDUINOJSON_NAMESPACE {
class JsonArray;
class JsonObject;
// Forward declarations.
class JsonArraySubscript;
template <typename TKey>
class JsonObjectSubscript;
template <typename TImpl>
class JsonVariantSubscripts {
public:
// Mimics an array.
// Returns the element at specified index if the variant is an array.
FORCE_INLINE JsonArraySubscript operator[](size_t index) const;
// Mimics an object.
// Returns the value associated with the specified key if the variant is
// an object.
//
// JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
JsonObjectSubscript<const TString &> >::type
operator[](const TString &key) const;
//
// JsonObjectSubscript operator[](TKey) const;
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString *>::value,
JsonObjectSubscript<TString *> >::type
operator[](TString *key) const;
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once

View File

@ -1,187 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Strings/StringInMemoryPool.hpp"
#include "Alignment.hpp"
#include "MemoryPool.hpp"
#include "StaticMemoryPool.hpp"
#include <stdlib.h> // malloc, free
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ARDUINOJSON_NAMESPACE {
class DefaultAllocator {
public:
void* allocate(size_t size) {
return malloc(size);
}
void deallocate(void* pointer) {
free(pointer);
}
};
template <typename TAllocator>
class DynamicMemoryPoolBase : public MemoryPool {
class Block : public StaticMemoryPoolBase {
public:
Block(char* buf, size_t sz, Block* nxt)
: StaticMemoryPoolBase(buf, sz), next(nxt) {}
Block* next;
};
public:
enum { EmptyBlockSize = sizeof(Block) };
DynamicMemoryPoolBase(size_t initialSize = ARDUINOJSON_DEFAULT_POOL_SIZE)
: _head(NULL), _nextBlockCapacity(initialSize) {}
~DynamicMemoryPoolBase() {
clear();
}
void reserve(size_t capacity) {
_nextBlockCapacity = capacity;
}
virtual size_t size() const {
size_t sum = 0;
for (Block* b = _head; b; b = b->next) {
sum += b->size();
}
return sum;
}
virtual VariantSlot* allocVariant() {
for (Block* b = _head; b; b = b->next) {
VariantSlot* s = b->allocVariant();
if (s) return s;
}
if (!addNewBlock(sizeof(VariantSlot))) return 0;
return _head->allocVariant();
}
virtual void freeVariant(VariantSlot* slot) {
for (Block* b = _head; b; b = b->next) {
if (b->owns(slot)) {
b->freeVariant(slot);
break;
}
}
}
virtual void freeString(StringSlot* slot) {
for (Block* b = _head; b; b = b->next) {
if (b->owns(slot)) {
b->freeString(slot);
break;
}
}
}
virtual StringSlot* allocFrozenString(size_t n) {
for (Block* b = _head; b; b = b->next) {
StringSlot* s = b->allocFrozenString(n);
if (s) return s;
}
if (!addNewBlock(sizeof(StringSlot) + n)) return 0;
return _head->allocFrozenString(n);
}
virtual StringSlot* allocExpandableString() {
for (Block* b = _head; b; b = b->next) {
StringSlot* s = b->allocExpandableString();
if (s) return s;
}
if (!addNewBlock(sizeof(StringSlot))) return 0;
return _head->allocExpandableString();
}
virtual StringSlot* expandString(StringSlot* oldSlot) {
if (!addNewBlock(sizeof(StringSlot) + oldSlot->size)) return 0;
StringSlot* newSlot = _head->allocExpandableString();
ARDUINOJSON_ASSERT(newSlot->size > oldSlot->size);
memcpy(newSlot->value, oldSlot->value, oldSlot->size);
freeString(oldSlot);
return newSlot;
}
virtual void freezeString(StringSlot* slot, size_t newSize) {
for (Block* b = _head; b; b = b->next) {
if (b->owns(slot)) {
b->freezeString(slot, newSize);
}
}
}
// Resets the memoryPool.
// USE WITH CAUTION: this invalidates all previously allocated data
void clear() {
Block* currentBlock = _head;
while (currentBlock != NULL) {
_nextBlockCapacity = currentBlock->capacity();
Block* nextBlock = currentBlock->next;
_allocator.deallocate(currentBlock);
currentBlock = nextBlock;
}
_head = 0;
}
size_t blockCount() const {
size_t sum = 0;
for (Block* b = _head; b; b = b->next) sum++;
return sum;
}
private:
bool addNewBlock(size_t minCapacity) {
size_t capacity = _nextBlockCapacity;
if (minCapacity > capacity) capacity = minCapacity;
capacity = addPadding(capacity);
size_t bytes = sizeof(Block) + capacity;
char* p = reinterpret_cast<char*>(_allocator.allocate(bytes));
if (!p) return false;
Block* block = new (p) Block(p + sizeof(Block), capacity, _head);
_nextBlockCapacity = capacity * 2;
_head = block;
return true;
}
TAllocator _allocator;
Block* _head;
size_t _nextBlockCapacity;
};
// Implements a MemoryPool with dynamic memory allocation.
// You are strongly encouraged to consider using StaticMemoryPool which is much
// more suitable for embedded systems.
typedef DynamicMemoryPoolBase<DefaultAllocator> DynamicMemoryPool;
} // namespace ARDUINOJSON_NAMESPACE
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif

View File

@ -1,34 +1,120 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <stddef.h> // for size_t
#include "../Polyfills/attributes.hpp"
#include "../Polyfills/assert.hpp"
#include "../Polyfills/mpl/max.hpp"
#include "../Variant/VariantSlot.hpp"
#include "Alignment.hpp"
#include "MemoryPool.hpp"
#include "StringSlot.hpp"
#include "VariantSlot.hpp"
namespace ARDUINOJSON_NAMESPACE {
// _begin _end
// v v
// +-------------+--------------+-----------+
// | strings... | (free) | ...slots |
// +-------------+--------------+-----------+
// ^ ^
// _left _right
class MemoryPool {
public:
virtual StringSlot *allocExpandableString() = 0;
virtual StringSlot *allocFrozenString(size_t) = 0;
virtual StringSlot *expandString(StringSlot *) = 0;
virtual void freezeString(StringSlot *, size_t) = 0;
virtual void freeString(StringSlot *) = 0;
MemoryPool(char* buf, size_t capa)
: _begin(buf),
_left(buf),
_right(buf ? buf + capa : 0),
_end(buf ? buf + capa : 0) {
ARDUINOJSON_ASSERT(isAligned(_begin));
ARDUINOJSON_ASSERT(isAligned(_right));
ARDUINOJSON_ASSERT(isAligned(_end));
}
virtual VariantSlot *allocVariant() = 0;
virtual void freeVariant(VariantSlot *) = 0;
void* buffer() {
return _begin;
}
virtual size_t size() const = 0;
// Gets the capacity of the memoryPool in bytes
size_t capacity() const {
return size_t(_end - _begin);
}
protected:
// CAUTION: NO VIRTUAL DESTRUCTOR!
// If we add a virtual constructor the Arduino compiler will add malloc()
// and free() to the binary, adding 706 useless bytes.
~MemoryPool() {}
size_t size() const {
return size_t(_left - _begin + _end - _right);
}
VariantSlot* allocVariant() {
return allocRight<VariantSlot>();
}
char* allocFrozenString(size_t n) {
if (!canAlloc(n)) return 0;
char* s = _left;
_left += n;
checkInvariants();
return s;
}
StringSlot allocExpandableString() {
StringSlot s;
s.value = _left;
s.size = size_t(_right - _left);
_left = _right;
checkInvariants();
return s;
}
void freezeString(StringSlot& s, size_t newSize) {
_left -= (s.size - newSize);
s.size = newSize;
checkInvariants();
}
void clear() {
_left = _begin;
_right = _end;
}
bool canAlloc(size_t bytes) const {
return _left + bytes <= _right;
}
bool owns(void* p) const {
return _begin <= p && p < _end;
}
template <typename T>
T* allocRight() {
return reinterpret_cast<T*>(allocRight(sizeof(T)));
}
void* allocRight(size_t bytes) {
if (!canAlloc(bytes)) return 0;
_right -= bytes;
return _right;
}
// Workaround for missing placement new
void* operator new(size_t, void* p) {
return p;
}
private:
StringSlot* allocStringSlot() {
return allocRight<StringSlot>();
}
void checkInvariants() {
ARDUINOJSON_ASSERT(_begin <= _left);
ARDUINOJSON_ASSERT(_left <= _right);
ARDUINOJSON_ASSERT(_right <= _end);
ARDUINOJSON_ASSERT(isAligned(_right));
}
char *_begin, *_left, *_right, *_end;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,67 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h> // for size_t
namespace ARDUINOJSON_NAMESPACE {
template <typename TSlot>
class SlotList {
public:
SlotList() : _head(0) {}
TSlot *pop() {
TSlot *slot = _head;
if (slot) _head = slot->next;
return slot;
}
void push(TSlot *slot) {
slot->next = _head;
_head = slot;
}
bool remove(const TSlot *slot) {
if (_head == slot) {
_head = slot->next;
return true;
}
for (TSlot *s = _head; s; s = s->next) {
if (s->next == slot) {
s->next = slot->next;
return true;
}
}
return false;
}
bool remove(const void *slot) {
return remove(reinterpret_cast<const TSlot *>(slot));
}
template <typename Functor>
void forEach(const Functor &f) {
for (TSlot *s = _head; s; s = s->next) {
f(s);
}
}
size_t size() const {
size_t sum = 0;
for (TSlot *s = _head; s; s = s->next) sum += sizeof(TSlot);
return sum;
}
void clear() {
_head = 0;
}
private:
TSlot *_head;
};
} // namespace ARDUINOJSON_NAMESPACE

Some files were not shown because too many files have changed in this diff Show More