forked from bblanchon/ArduinoJson
Compare commits
301 Commits
Author | SHA1 | Date | |
---|---|---|---|
46bd98fd10 | |||
63c89f166d | |||
8340b36170 | |||
ad4b13c8f0 | |||
f20f8e3171 | |||
5c297ba4a2 | |||
f483b06735 | |||
a0011ba7f8 | |||
ae2bfee0b1 | |||
b171872b58 | |||
0d01e84336 | |||
0685a36f0e | |||
ef12c74771 | |||
0bc03e8071 | |||
04286f3228 | |||
0d4a93018b | |||
3ca40db9f8 | |||
ce607196d1 | |||
0b3af166ae | |||
fa1a40ac6e | |||
954428e341 | |||
7b229e4c38 | |||
9ac9b533b6 | |||
011aac43d2 | |||
eb20ae6a3f | |||
7c0af91844 | |||
3523296e3d | |||
689ae5c08d | |||
d9b1e7e810 | |||
b4eece01f8 | |||
cf5396aaed | |||
e390587e91 | |||
bae179ed67 | |||
7e4fcb0868 | |||
fbfdca1de9 | |||
0612eef69b | |||
ae0b7a3ebd | |||
e92612b511 | |||
5c33fd4b94 | |||
c3f51e2980 | |||
de47c0af9e | |||
e53e4e3dd9 | |||
36fe6535c4 | |||
b55e57a7cf | |||
7626db624e | |||
6d8329b255 | |||
461e30148c | |||
57d98e48f7 | |||
cf2babc598 | |||
d10277df31 | |||
d3a1203782 | |||
126f7ab819 | |||
221c2861fc | |||
66667382e1 | |||
a7e928d126 | |||
591fe7e92b | |||
d6e61cbcda | |||
5825366fe4 | |||
6df204cf40 | |||
3f7e1db549 | |||
a6091136b0 | |||
353bbd0e8c | |||
a428e125fa | |||
2e262b2689 | |||
a2d055e408 | |||
57defe00ee | |||
ac5a2676e7 | |||
ed98ea4e43 | |||
729bf0afd2 | |||
2ea7ea153c | |||
2772e66064 | |||
d41f7a8165 | |||
abfd3997eb | |||
788c9be016 | |||
c3d7a79a83 | |||
1782348275 | |||
edfe5c6622 | |||
2b9492317b | |||
5da41edf6a | |||
476e5aaa86 | |||
789fa507b5 | |||
508f936317 | |||
e9d88dda8e | |||
ecceb71a1e | |||
bff77abe6a | |||
98413089f6 | |||
a2446f6c68 | |||
c955049207 | |||
574c00c096 | |||
7415f206ea | |||
f76017a015 | |||
cda05aec04 | |||
639286f8b6 | |||
cc66618e70 | |||
9efc0ec40d | |||
34674fc282 | |||
01c3166043 | |||
bf2e3d5669 | |||
4e9f0b2e2e | |||
223f14710d | |||
f7ae91b85d | |||
445dff499b | |||
9afa05e2f4 | |||
c3e1677b7d | |||
024976cda2 | |||
df541a2a22 | |||
f2ef338cb8 | |||
8c6f64c111 | |||
5a16b2117b | |||
71edcaf20f | |||
ac89d91db5 | |||
e664c1ab05 | |||
adba668109 | |||
ad972725de | |||
185eccf6f5 | |||
c4567bac18 | |||
13409c433a | |||
20431debe0 | |||
797ea356ef | |||
2321473c34 | |||
0d5f65c5f3 | |||
c30241775a | |||
31827d03f9 | |||
7bcdf3e722 | |||
db9a76f7c6 | |||
3fd87e8e82 | |||
22a2786610 | |||
2b5a6df1e1 | |||
5fefeae404 | |||
d4f725d1fa | |||
a096098c1f | |||
cc8c0472ca | |||
fb554071dc | |||
17a17c8957 | |||
2e7d498865 | |||
567157b005 | |||
ec6cbc5135 | |||
8499f0b960 | |||
11432253a1 | |||
f17e1c4a80 | |||
6b2f6a4f87 | |||
671329a3e9 | |||
7e7074502f | |||
aa306d5573 | |||
55669e306e | |||
3f96e070ce | |||
8032a4b564 | |||
b923e8f4df | |||
c5388cf8e7 | |||
cb908a2373 | |||
cecbcd1929 | |||
90e0cc6091 | |||
45bbf6db86 | |||
432476c98a | |||
1f3e227a8b | |||
66c28020c5 | |||
6cfe2a58eb | |||
fc6ad51e68 | |||
d3bc52951a | |||
2f7232859e | |||
4a7232ac99 | |||
72d78432c9 | |||
f6cd42d916 | |||
542dff2a08 | |||
e75e843c88 | |||
146a76247c | |||
f28157cab7 | |||
1ce16ce449 | |||
c310e7e8b7 | |||
aa2ef79e55 | |||
7ad57f1c33 | |||
cbfd331e50 | |||
e6f55b1f6f | |||
bb805e93cb | |||
deb57b960b | |||
8a9b918bf4 | |||
2f6f3d0629 | |||
a60b35f41c | |||
6757f35a3a | |||
ffb9b6d1ba | |||
e401498e4a | |||
d30e940b3b | |||
05ea5e04c8 | |||
a7ef99d0fe | |||
f2a8b52c2c | |||
409ca7ee4e | |||
387b565705 | |||
96f486001d | |||
a498abc14a | |||
c64340a9bb | |||
79d80a5dbf | |||
7ebff5949f | |||
434080572c | |||
c87a0e97ab | |||
2dbd94951c | |||
1e044f50c7 | |||
a7aa98510c | |||
729ab56878 | |||
907b627e16 | |||
10fcca20f8 | |||
59cd1f1433 | |||
4a2c570270 | |||
8c7edbd9c3 | |||
0801e16327 | |||
0df2a365f5 | |||
c7d6d33e6c | |||
c705f3cfeb | |||
7fecb36aee | |||
657a2ea8d9 | |||
dd064f4c96 | |||
3bc05b97ea | |||
bbd515f6f6 | |||
9b3e3a3d9c | |||
a3a2ca4796 | |||
eab13dc565 | |||
bebd1c400c | |||
36d1bb2f52 | |||
ae32695c3e | |||
c5d19a4dbd | |||
78728c6547 | |||
a8032f81d9 | |||
a138791964 | |||
f9f002c8f7 | |||
f192d5c12e | |||
a6724bd03f | |||
c77c3f33ef | |||
623aeee9bf | |||
a241d53d28 | |||
11500d2ff5 | |||
85708bc94f | |||
ba6e8856f2 | |||
c8448b0abf | |||
e35248ffc4 | |||
b47a3b566a | |||
6ab23bd523 | |||
987afff0e9 | |||
564c62f3b3 | |||
8733f95e51 | |||
ce63e9c3c3 | |||
77b7124cf1 | |||
6a608d4b49 | |||
01924618bd | |||
666e2fd0ce | |||
0cfc25d751 | |||
b6d8e6c989 | |||
ab2502f7b8 | |||
c57e6f3bd8 | |||
b54f1ffc1d | |||
bd0ea42277 | |||
7ae43bc4f8 | |||
056682327b | |||
8b66a25f66 | |||
96245dd3b4 | |||
9cc49da68a | |||
224918b463 | |||
cbeefa2503 | |||
6d68806633 | |||
ba3617c22f | |||
b7d9bb2765 | |||
74b42e2251 | |||
c0cf9c3fcc | |||
9f3ce18f06 | |||
b9e3255c9e | |||
e657396f65 | |||
929f608f2f | |||
c6a4bfa886 | |||
d5e25b12b8 | |||
7cf6fe6d62 | |||
155dd653e7 | |||
b5c8cd1766 | |||
4967e389c5 | |||
ffbaebd198 | |||
04b8781c8d | |||
5a4d993f7d | |||
823a172681 | |||
a1943e21ed | |||
01c287bc89 | |||
0cf8249b14 | |||
a8265a799d | |||
18bb653f10 | |||
a003a31952 | |||
0a1c27f873 | |||
75f8e25aed | |||
39c506b419 | |||
ef2641b49b | |||
bce101578d | |||
10e466426a | |||
9b90aeffa5 | |||
601b51890f | |||
2524a00a96 | |||
e31d667bec | |||
c161f698fc | |||
92e687303d | |||
f5b83f9314 | |||
5e7b9ec688 | |||
78ae0b8aee | |||
283dffc035 | |||
0aded2a798 | |||
1b5be892b9 | |||
756c279cdc | |||
08d05df00e |
5
.clang-format
Normal file
5
.clang-format
Normal file
@ -0,0 +1,5 @@
|
||||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
|
||||
BasedOnStyle: Google
|
||||
Standard: Cpp03
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.sh text eol=lf
|
14
.github/ISSUE_TEMPLATE.md
vendored
Normal file
14
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<!--
|
||||
Before opening an issue, please read the FAQ:
|
||||
https://arduinojson.org/faq/
|
||||
|
||||
Please provide all the relevant information:
|
||||
* good title
|
||||
* short description of the problem
|
||||
* target platform
|
||||
* compiler model and version
|
||||
* MVCE (https://stackoverflow.com/help/mcve)
|
||||
* compiler output
|
||||
|
||||
Good questions get fast answers!
|
||||
-->
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -3,3 +3,9 @@
|
||||
/build
|
||||
/bin
|
||||
/lib
|
||||
/sftp-config.json
|
||||
.tags
|
||||
.tags_sorted_by_file
|
||||
/fuzzing/*_fuzzer
|
||||
/fuzzing/*_fuzzer.options
|
||||
/fuzzing/*_fuzzer_seed_corpus.zip
|
||||
|
6
.mbedignore
Normal file
6
.mbedignore
Normal file
@ -0,0 +1,6 @@
|
||||
.github/
|
||||
examples/
|
||||
fuzzing/
|
||||
scripts/
|
||||
test/
|
||||
third-party/
|
146
.travis.yml
146
.travis.yml
@ -1,12 +1,134 @@
|
||||
language: c++
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
before_install:
|
||||
- sudo pip install cpp-coveralls
|
||||
before_script:
|
||||
- cmake -DCOVERAGE=true .
|
||||
script:
|
||||
- make && make test
|
||||
after_success:
|
||||
- coveralls --exclude test --exclude third-party --gcov-options '\-lp'
|
||||
sudo: false
|
||||
language: cpp
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.4']
|
||||
env: SCRIPT=cmake GCC=4.4
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.6']
|
||||
env: SCRIPT=cmake GCC=4.6
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.7']
|
||||
env: SCRIPT=cmake GCC=4.7
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.8']
|
||||
env: SCRIPT=cmake GCC=4.8 SANITIZE=address
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.9']
|
||||
env: SCRIPT=cmake GCC=4.9 SANITIZE=leak
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5']
|
||||
env: SCRIPT=cmake GCC=5
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-6']
|
||||
env: SCRIPT=cmake GCC=6
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-7']
|
||||
env: SCRIPT=cmake GCC=7
|
||||
- compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- compiler: 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:
|
||||
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:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.7']
|
||||
packages: ['clang-3.7']
|
||||
env: SCRIPT=cmake CLANG=3.7
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
|
||||
packages: ['clang-3.8']
|
||||
env: SCRIPT=cmake CLANG=3.8 SANITIZE=undefined
|
||||
- compiler: clang
|
||||
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:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-4.0']
|
||||
packages: ['clang-4.0']
|
||||
env: SCRIPT=cmake CLANG=4.0
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-5.0']
|
||||
packages: ['clang-5.0']
|
||||
env: SCRIPT=cmake CLANG=5.0
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
|
||||
packages: ['clang-6.0']
|
||||
env: SCRIPT=cmake CLANG=6.0
|
||||
- compiler: gcc
|
||||
env: SCRIPT=coverage
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode10
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake SANITIZE=address
|
||||
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=platformio BOARD=uno
|
||||
- env: SCRIPT=platformio BOARD=esp01
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
|
||||
packages: ['clang-6.0','llvm-6.0']
|
||||
env: SCRIPT=fuzz CLANG=6.0
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
script: scripts/travis/$SCRIPT.sh
|
||||
|
@ -1,24 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
// This file is here to help the Arduino IDE find the other files.
|
||||
|
||||
#include "src/Arduino/Print.cpp"
|
||||
#include "src/DynamicJsonBuffer.cpp"
|
||||
#include "src/Internals/IndentedPrint.cpp"
|
||||
#include "src/Internals/JsonParser.cpp"
|
||||
#include "src/Internals/List.cpp"
|
||||
#include "src/Internals/Prettyfier.cpp"
|
||||
#include "src/Internals/QuotedString.cpp"
|
||||
#include "src/Internals/StringBuilder.cpp"
|
||||
#include "src/JsonArray.cpp"
|
||||
#include "src/JsonBuffer.cpp"
|
||||
#include "src/JsonObject.cpp"
|
||||
#include "src/JsonVariant.cpp"
|
||||
|
||||
#endif
|
@ -1,13 +1,5 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
// This file is here to help the Arduino IDE find the other files.
|
||||
|
||||
#include "include/ArduinoJson.h"
|
||||
|
||||
#endif
|
||||
#include "src/ArduinoJson.h"
|
||||
|
574
CHANGELOG.md
574
CHANGELOG.md
@ -1,5 +1,469 @@
|
||||
Arduino JSON: change log
|
||||
========================
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
HEAD
|
||||
----
|
||||
|
||||
* `JsonObject::createNestedObject()` returns `JsonObject::invalid()` if key is null (issue #1891)
|
||||
* `JsonObject::createNestedArray()` returns `JsonArray::invalid()` if key is null
|
||||
|
||||
v5.13.5
|
||||
-------
|
||||
|
||||
* Fixed warning "unused variable" with GCC 4.4 (issue #912)
|
||||
* Fixed warning "maybe uninitialized" (issue #909)
|
||||
* Added an clear message for `StaticJsonDocument`, `DynamicJsonDocument`...
|
||||
|
||||
v5.13.4
|
||||
-------
|
||||
|
||||
* Removed spurious files in the Particle library
|
||||
|
||||
v5.13.3
|
||||
-------
|
||||
|
||||
* Improved float serialization when `-fsingle-precision-constant` is used
|
||||
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
|
||||
* Fixed `JsonVariant::is<String>()` (closes #763)
|
||||
|
||||
v5.13.2
|
||||
-------
|
||||
|
||||
* Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693)
|
||||
* Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu)
|
||||
* Fixed null values that could be pass to `strcmp()` (PR #745 from Mike Karlesky)
|
||||
* Added macros `ARDUINOJSON_VERSION`, `ARDUINOJSON_VERSION_MAJOR`...
|
||||
|
||||
v5.13.1
|
||||
-------
|
||||
|
||||
* Fixed `JsonVariant::operator|(int)` that returned the default value if the variant contained a double (issue #675)
|
||||
* Allowed non-quoted key to contain underscores (issue #665)
|
||||
|
||||
v5.13.0
|
||||
-------
|
||||
|
||||
* Changed the rules of string duplication (issue #658)
|
||||
* `RawJson()` accepts any kind of string and obeys to the same rules for duplication
|
||||
* Changed the return type of `strdup()` to `const char*` to prevent double duplication
|
||||
* Marked `strdup()` as deprecated
|
||||
|
||||
> ### New rules for string duplication
|
||||
>
|
||||
> | type | duplication |
|
||||
> |:---------------------------|:------------|
|
||||
> | const char* | no |
|
||||
> | char* | ~~no~~ yes |
|
||||
> | String | yes |
|
||||
> | std::string | yes |
|
||||
> | const __FlashStringHelper* | yes |
|
||||
>
|
||||
> These new rules make `JsonBuffer::strdup()` useless.
|
||||
|
||||
v5.12.0
|
||||
-------
|
||||
|
||||
* Added `JsonVariant::operator|` to return a default value (see below)
|
||||
* Added a clear error message when compiled as C instead of C++ (issue #629)
|
||||
* Added detection of MPLAB XC compiler (issue #629)
|
||||
* Added detection of Keil ARM Compiler (issue #629)
|
||||
* Added an example that shows how to save and load a configuration file
|
||||
* Reworked all other examples
|
||||
|
||||
> ### How to use the new feature?
|
||||
>
|
||||
> If you have a block like this:
|
||||
>
|
||||
> ```c++
|
||||
> const char* ssid = root["ssid"];
|
||||
> if (!ssid)
|
||||
> ssid = "default ssid";
|
||||
> ```
|
||||
>
|
||||
> You can simplify like that:
|
||||
>
|
||||
> ```c++
|
||||
> const char* ssid = root["ssid"] | "default ssid";
|
||||
> ```
|
||||
|
||||
v5.11.2
|
||||
-------
|
||||
|
||||
* Fixed `DynamicJsonBuffer::clear()` not resetting allocation size (issue #561)
|
||||
* Fixed incorrect rounding for float values (issue #588)
|
||||
|
||||
v5.11.1
|
||||
-------
|
||||
|
||||
* Removed dependency on `PGM_P` as Particle 0.6.2 doesn't define it (issue #546)
|
||||
* Fixed warning "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]"
|
||||
* Fixed warning "floating constant exceeds range of 'float' [-Woverflow]" (issue #544)
|
||||
* Fixed warning "this statement may fall through" [-Wimplicit-fallthrough=] (issue #539)
|
||||
* Removed `ARDUINOJSON_DOUBLE_IS_64BITS` as it became useless.
|
||||
* Fixed too many decimals places in float serialization (issue #543)
|
||||
|
||||
v5.11.0
|
||||
-------
|
||||
|
||||
* Made `JsonBuffer` non-copyable (PR #524 by @luisrayas3)
|
||||
* Added `StaticJsonBuffer::clear()`
|
||||
* Added `DynamicJsonBuffer::clear()`
|
||||
|
||||
v5.10.1
|
||||
-------
|
||||
|
||||
* Fixed IntelliSense errors in Visual Micro (issue #483)
|
||||
* Fixed compilation in IAR Embedded Workbench (issue #515)
|
||||
* Fixed reading "true" as a float (issue #516)
|
||||
* Added `ARDUINOJSON_DOUBLE_IS_64BITS`
|
||||
* Added `ARDUINOJSON_EMBEDDED_MODE`
|
||||
|
||||
v5.10.0
|
||||
-------
|
||||
|
||||
* Removed configurable number of decimal places (issues #288, #427 and #506)
|
||||
* Changed exponentiation thresholds to `1e7` and `1e-5` (issues #288, #427 and #506)
|
||||
* `JsonVariant::is<double>()` now returns `true` for integers
|
||||
* Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495)
|
||||
* Fixed error `forming reference to reference` (issue #495)
|
||||
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> | Old syntax | New syntax |
|
||||
> |:--------------------------------|:--------------------|
|
||||
> | `double_with_n_digits(3.14, 2)` | `3.14` |
|
||||
> | `float_with_n_digits(3.14, 2)` | `3.14f` |
|
||||
> | `obj.set("key", 3.14, 2)` | `obj["key"] = 3.14` |
|
||||
> | `arr.add(3.14, 2)` | `arr.add(3.14)` |
|
||||
>
|
||||
> | Input | Old output | New output |
|
||||
> |:----------|:-----------|:-----------|
|
||||
> | `3.14159` | `3.14` | `3.14159` |
|
||||
> | `42.0` | `42.00` | `42` |
|
||||
> | `0.0` | `0.00` | `0` |
|
||||
>
|
||||
> | Expression | Old result | New result |
|
||||
> |:-------------------------------|:-----------|:-----------|
|
||||
> | `JsonVariant(42).is<int>()` | `true` | `true` |
|
||||
> | `JsonVariant(42).is<float>()` | `false` | `true` |
|
||||
> | `JsonVariant(42).is<double>()` | `false` | `true` |
|
||||
|
||||
v5.9.0
|
||||
------
|
||||
|
||||
* Added `JsonArray::remove(iterator)` (issue #479)
|
||||
* Added `JsonObject::remove(iterator)`
|
||||
* Renamed `JsonArray::removeAt(size_t)` into `remove(size_t)`
|
||||
* Renamed folder `include/` to `src/`
|
||||
* Fixed warnings `floating constant exceeds range of float`and `floating constant truncated to zero` (issue #483)
|
||||
* Removed `Print` class and converted `printTo()` to a template method (issue #276)
|
||||
* Removed example `IndentedPrintExample.ino`
|
||||
* Now compatible with Particle 0.6.1, thanks to Jacob Nite (issue #294 and PR #461 by @foodbag)
|
||||
|
||||
v5.8.4
|
||||
------
|
||||
|
||||
* Added custom implementation of `strtod()` (issue #453)
|
||||
* Added custom implementation of `strtol()` (issue #465)
|
||||
* `char` is now treated as an integral type (issue #337, #370)
|
||||
|
||||
v5.8.3
|
||||
------
|
||||
|
||||
* Fixed an access violation in `DynamicJsonBuffer` when memory allocation fails (issue #433)
|
||||
* Added operators `==` and `!=` for two `JsonVariant`s (issue #436)
|
||||
* Fixed `JsonVariant::operator[const FlashStringHelper*]` (issue #441)
|
||||
|
||||
v5.8.2
|
||||
------
|
||||
|
||||
* Fixed parsing of comments (issue #421)
|
||||
* Fixed ignored `Stream` timeout (issue #422)
|
||||
* Made sure we don't read more that necessary (issue #422)
|
||||
* Fixed error when the key of a `JsonObject` is a `char[]` (issue #423)
|
||||
* Reduced code size when using `const` references
|
||||
* Fixed error with string of type `unsigned char*` (issue #428)
|
||||
* Added `deprecated` attribute on `asArray()`, `asObject()` and `asString()` (issue #420)
|
||||
|
||||
v5.8.1
|
||||
------
|
||||
|
||||
* Fixed error when assigning a `volatile int` to a `JsonVariant` (issue #415)
|
||||
* Fixed errors with Variable Length Arrays (issue #416)
|
||||
* Fixed error when both `ARDUINOJSON_ENABLE_STD_STREAM` and `ARDUINOJSON_ENABLE_ARDUINO_STREAM` are set to `1`
|
||||
* Fixed error "Stream does not name a type" (issue #412)
|
||||
|
||||
v5.8.0
|
||||
------
|
||||
|
||||
* Added operator `==` to compare `JsonVariant` and strings (issue #402)
|
||||
* Added support for `Stream` (issue #300)
|
||||
* Reduced memory consumption by not duplicating spaces and comments
|
||||
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> `JsonBuffer::parseObject()` and `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`.
|
||||
>
|
||||
> This means that if you have code like:
|
||||
>
|
||||
> ```c++
|
||||
> void myFunction(JsonBuffer& jsonBuffer);
|
||||
> ```
|
||||
>
|
||||
> you need to replace it with one of the following:
|
||||
>
|
||||
> ```c++
|
||||
> void myFunction(DynamicJsonBuffer& jsonBuffer);
|
||||
> void myFunction(StaticJsonBufferBase& jsonBuffer);
|
||||
> template<typename TJsonBuffer> void myFunction(TJsonBuffer& jsonBuffer);
|
||||
> ```
|
||||
|
||||
v5.7.3
|
||||
------
|
||||
|
||||
* Added an `printTo(char[N])` and `prettyPrintTo(char[N])` (issue #292)
|
||||
* Added ability to set a nested value like this: `root["A"]["B"] = "C"` (issue #352)
|
||||
* Renamed `*.ipp` to `*Impl.hpp` because they were ignored by Arduino IDE (issue #396)
|
||||
|
||||
v5.7.2
|
||||
------
|
||||
|
||||
* Made PROGMEM available on more platforms (issue #381)
|
||||
* Fixed PROGMEM causing an exception on ESP8266 (issue #383)
|
||||
|
||||
v5.7.1
|
||||
------
|
||||
|
||||
* Added support for PROGMEM (issue #76)
|
||||
* Fixed compilation error when index is not an `int` (issue #381)
|
||||
|
||||
v5.7.0
|
||||
------
|
||||
|
||||
* Templatized all functions using `String` or `std::string`
|
||||
* Removed `ArduinoJson::String`
|
||||
* Removed `JsonVariant::defaultValue<T>()`
|
||||
* Removed non-template `JsonObject::get()` and `JsonArray.get()`
|
||||
* Fixed support for `StringSumHelper` (issue #184)
|
||||
* Replaced `ARDUINOJSON_USE_ARDUINO_STRING` by `ARDUINOJSON_ENABLE_STD_STRING` and `ARDUINOJSON_ENABLE_ARDUINO_STRING` (issue #378)
|
||||
* Added example `StringExample.ino` to show where `String` can be used
|
||||
* Increased default nesting limit to 50 when compiled for a computer (issue #349)
|
||||
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return.
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> #define ARDUINOJSON_USE_ARDUINO_STRING 0
|
||||
> JsonVariant value1 = myObject.get("myKey");
|
||||
> JsonVariant value2 = myArray.get(0);
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||
> #define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||
> JsonVariant value1 = myObject.get<JsonVariant>("myKey");
|
||||
> JsonVariant value2 = myArray.get<JsonVariant>(0);
|
||||
> ```
|
||||
|
||||
v5.6.7
|
||||
------
|
||||
|
||||
* Fixed `array[idx].as<JsonVariant>()` and `object[key].as<JsonVariant>()`
|
||||
* Fixed return value of `JsonObject::set()` (issue #350)
|
||||
* Fixed undefined behavior in `Prettyfier` and `Print` (issue #354)
|
||||
* Fixed parser that incorrectly rejected floats containing a `+` (issue #349)
|
||||
|
||||
v5.6.6
|
||||
------
|
||||
|
||||
* Fixed `-Wparentheses` warning introduced in v5.6.5 (PR #335 by @nuket)
|
||||
* Added `.mbedignore` for ARM mbdeb (PR #334 by @nuket)
|
||||
* Fixed `JsonVariant::success()` which didn't propagate `JsonArray::success()` nor `JsonObject::success()` (issue #342).
|
||||
|
||||
v5.6.5
|
||||
------
|
||||
|
||||
* `as<char*>()` now returns `true` when input is `null` (issue #330)
|
||||
|
||||
v5.6.4
|
||||
------
|
||||
|
||||
* Fixed error in float serialization (issue #324)
|
||||
|
||||
v5.6.3
|
||||
------
|
||||
|
||||
* Improved speed of float serialization (about twice faster)
|
||||
* Added `as<JsonArray>()` as a synonym for `as<JsonArray&>()`... (issue #291)
|
||||
* Fixed `call of overloaded isinf(double&) is ambiguous` (issue #284)
|
||||
|
||||
v5.6.2
|
||||
------
|
||||
|
||||
* Fixed build when another lib does `#undef isnan` (issue #284)
|
||||
|
||||
v5.6.1
|
||||
------
|
||||
|
||||
* Added missing `#pragma once` (issue #310)
|
||||
|
||||
v5.6.0
|
||||
------
|
||||
|
||||
* ArduinoJson is now a header-only library (issue #199)
|
||||
|
||||
v5.5.1
|
||||
------
|
||||
|
||||
* Fixed compilation error with Intel Galileo (issue #299)
|
||||
|
||||
v5.5.0
|
||||
------
|
||||
|
||||
* Added `JsonVariant::success()` (issue #279)
|
||||
* Renamed `JsonVariant::invalid<T>()` to `JsonVariant::defaultValue<T>()`
|
||||
|
||||
v5.4.0
|
||||
------
|
||||
|
||||
* Changed `::String` to `ArduinoJson::String` (issue #275)
|
||||
* Changed `::Print` to `ArduinoJson::Print` too
|
||||
|
||||
v5.3.0
|
||||
------
|
||||
|
||||
* Added custom implementation of `ftoa` (issues #266, #267, #269 and #270)
|
||||
* Added `JsonVariant JsonBuffer::parse()` (issue #265)
|
||||
* Fixed `unsigned long` printed as `signed long` (issue #170)
|
||||
|
||||
v5.2.0
|
||||
------
|
||||
|
||||
* Added `JsonVariant::as<char*>()` as a synonym for `JsonVariant::as<const char*>()` (issue #257)
|
||||
* Added example `JsonHttpClient` (issue #256)
|
||||
* Added `JsonArray::copyTo()` and `JsonArray::copyFrom()` (issue #254)
|
||||
* Added `RawJson()` to insert pregenerated JSON portions (issue #259)
|
||||
|
||||
v5.1.1
|
||||
------
|
||||
|
||||
* Removed `String` duplication when one replaces a value in a `JsonObject` (PR #232 by @ulion)
|
||||
|
||||
v5.1.0
|
||||
------
|
||||
|
||||
* Added support of `long long` (issue #171)
|
||||
* Moved all build settings to `ArduinoJson/Configuration.hpp`
|
||||
|
||||
> ### BREAKING CHANGE :warning:
|
||||
>
|
||||
> If you defined `ARDUINOJSON_ENABLE_STD_STREAM`, you now need to define it to `1`.
|
||||
|
||||
v5.0.8
|
||||
------
|
||||
|
||||
* Made the library compatible with [PlatformIO](http://platformio.org/) (issue #181)
|
||||
* Fixed `JsonVariant::is<bool>()` that was incorrectly returning false (issue #214)
|
||||
|
||||
v5.0.7
|
||||
------
|
||||
|
||||
* Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)`
|
||||
* Changed `String` to be a `typedef` of `std::string` (issues #142 and #161)
|
||||
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> - `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"`
|
||||
> - `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"`
|
||||
|
||||
v5.0.6
|
||||
------
|
||||
|
||||
* Added parameter to `DynamicJsonBuffer` constructor to set initial size (issue #152)
|
||||
* Fixed warning about library category in Arduino 1.6.6 (issue #147)
|
||||
* Examples: Added a loop to wait for serial port to be ready (issue #156)
|
||||
|
||||
v5.0.5
|
||||
------
|
||||
|
||||
* Added overload `JsonObjectSuscript::set(value, decimals)` (issue #143)
|
||||
* Use `float` instead of `double` to reduce the size of `JsonVariant` (issue #134)
|
||||
|
||||
v5.0.4
|
||||
------
|
||||
|
||||
* Fixed ambiguous overload with `JsonArraySubscript` and `JsonObjectSubscript` (issue #122)
|
||||
|
||||
v5.0.3
|
||||
------
|
||||
|
||||
* Fixed `printTo(String)` which wrote numbers instead of strings (issue #120)
|
||||
* Fixed return type of `JsonArray::is<T>()` and some others (issue #121)
|
||||
|
||||
v5.0.2
|
||||
------
|
||||
|
||||
* Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the
|
||||
`StaticJsonBuffer` is too small to hold a copy of the string
|
||||
* Fixed Clang warning "register specifier is deprecated" (issue #102)
|
||||
* Fixed GCC warning "declaration shadows a member" (issue #103)
|
||||
* Fixed memory alignment, which made ESP8266 crash (issue #104)
|
||||
* Fixed compilation on Visual Studio 2010 and 2012 (issue #107)
|
||||
|
||||
v5.0.1
|
||||
------
|
||||
|
||||
* Fixed compilation with Arduino 1.0.6 (issue #99)
|
||||
|
||||
v5.0.0
|
||||
------
|
||||
|
||||
* Added support of `String` class (issues #55, #56, #70, #77)
|
||||
* Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57)
|
||||
* Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87)
|
||||
* Added support of non standard JSON input (issue #44)
|
||||
* Added support of comments in JSON input (issue #88)
|
||||
* Added implicit cast between numerical types (issues #64, #69, #93)
|
||||
* Added ability to read number values as string (issue #90)
|
||||
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66)
|
||||
* Switched to new the library layout (requires Arduino 1.0.6 or above)
|
||||
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> - `JsonObject::add()` was renamed to `set()`
|
||||
> - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
|
||||
> - Number of digits of floating point value are now set with `double_with_n_digits()`
|
||||
|
||||
**Personal note about the `String` class**:
|
||||
Support of the `String` class has been added to the library because many people use it in their programs.
|
||||
However, you should not see this as an invitation to use the `String` class.
|
||||
The `String` class is **bad** because it uses dynamic memory allocation.
|
||||
Compared to static allocation, it compiles to a bigger, slower program, and is less predictable.
|
||||
You certainly don't want that in an embedded environment!
|
||||
|
||||
v4.6
|
||||
----
|
||||
|
||||
* Fixed segmentation fault in `DynamicJsonBuffer` when memory allocation fails (issue #92)
|
||||
|
||||
v4.5
|
||||
----
|
||||
|
||||
* Fixed buffer overflow when input contains a backslash followed by a terminator (issue #81)
|
||||
|
||||
**Upgrading is recommended** since previous versions contain a potential security risk.
|
||||
|
||||
Special thanks to [Giancarlo Canales Barreto](https://github.com/gcanalesb) for finding this nasty bug.
|
||||
|
||||
v4.4
|
||||
----
|
||||
|
||||
* Added `JsonArray::measureLength()` and `JsonObject::measureLength()` (issue #75)
|
||||
|
||||
v4.3
|
||||
----
|
||||
@ -26,106 +490,6 @@ v4.0
|
||||
* Unified parser and generator API (issue #23)
|
||||
* Updated library layout, now requires Arduino 1.0.6 or newer
|
||||
|
||||
**BREAKING CHANGE**: API changed significantly, see [Migrating code to the new API](https://github.com/bblanchon/ArduinoJson/wiki/Migrating-code-to-the-new-API).
|
||||
|
||||
|
||||
v3.4
|
||||
----
|
||||
|
||||
* Fixed escaped char parsing (issue #16)
|
||||
|
||||
|
||||
v3.3
|
||||
----
|
||||
|
||||
* Added indented output for the JSON generator (issue #11), see example bellow.
|
||||
* Added `IndentedPrint`, a decorator for `Print` to allow indented output
|
||||
|
||||
Example:
|
||||
|
||||
JsonOject<2> json;
|
||||
json["key"] = "value";
|
||||
json.prettyPrintTo(Serial);
|
||||
|
||||
v3.2
|
||||
----
|
||||
|
||||
* Fixed a bug when adding nested object in `JsonArray` (bug introduced in v3.1).
|
||||
|
||||
v3.1
|
||||
----
|
||||
|
||||
* Calling `Generator::JsonObject::add()` twice with the same `key` now replaces the `value`
|
||||
* Added `Generator::JsonObject::operator[]`, see bellow the new API
|
||||
* Added `Generator::JsonObject::remove()` (issue #9)
|
||||
|
||||
Old generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
root.add("sensor", "gps");
|
||||
root.add("time", 1351824120);
|
||||
root.add("data", array);
|
||||
|
||||
New generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
root["data"] = array;
|
||||
|
||||
v3.0
|
||||
----
|
||||
|
||||
* New parser API, see bellow
|
||||
* Renamed `JsonHashTable` into `JsonObject`
|
||||
* Added iterators for `JsonArray` and `JsonObject` (issue #4)
|
||||
|
||||
Old parser API:
|
||||
|
||||
JsonHashTable root = parser.parseHashTable(json);
|
||||
|
||||
char* sensor = root.getString("sensor");
|
||||
long time = root.getLong("time");
|
||||
double latitude = root.getArray("data").getDouble(0);
|
||||
double longitude = root.getArray("data").getDouble(1);
|
||||
|
||||
New parser API:
|
||||
|
||||
JsonObject root = parser.parse(json);
|
||||
|
||||
char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
v2.1
|
||||
----
|
||||
|
||||
* Fixed case `#include "jsmn.cpp"` which caused an error in Linux (issue #6)
|
||||
* Fixed a buffer overrun in JSON Parser (issue #5)
|
||||
|
||||
v2.0
|
||||
----
|
||||
|
||||
* Added JSON encoding (issue #2)
|
||||
* Renamed the library `ArduinoJsonParser` becomes `ArduinoJson`
|
||||
|
||||
**Breaking change**: you need to add the following line at the top of your program.
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
v1.2
|
||||
----
|
||||
|
||||
* Fixed error in JSON parser example (issue #1)
|
||||
|
||||
v1.1
|
||||
----
|
||||
|
||||
* Example: changed `char* json` into `char[] json` so that the bytes are not write protected
|
||||
* Fixed parsing bug when the JSON contains multi-dimensional arrays
|
||||
|
||||
v1.0
|
||||
----
|
||||
|
||||
Initial release
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> API changed significantly since v3, see [Migrating code to the new API](https://arduinojson.org/doc/migration/).
|
||||
|
@ -1,20 +1,16 @@
|
||||
cmake_minimum_required(VERSION 2.8.4)
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(ArduinoJson)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -W4)
|
||||
endif()
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -coverage")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage")
|
||||
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
add_subdirectory(third-party/catch)
|
||||
add_subdirectory(test)
|
||||
|
11
CONTRIBUTING.md
Normal file
11
CONTRIBUTING.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Contribution to ArduinoJson
|
||||
|
||||
First, thank you for taking the time to contribute to this project.
|
||||
|
||||
You can submit changes via GitHub Pull Requests.
|
||||
|
||||
Please:
|
||||
|
||||
1. Unit test every change in behavior
|
||||
2. Use clang-format in "file" mode to format the code
|
||||
3. Consider using the Continuous Integration (Travis and AppVeyor)
|
@ -1,10 +1,10 @@
|
||||
The MIT License (MIT)
|
||||
---------------------
|
||||
|
||||
Copyright © 2014 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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
189
README.md
189
README.md
@ -1,81 +1,114 @@
|
||||
Arduino JSON library
|
||||
====================
|
||||
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
|
||||
|
||||
*An elegant and efficient JSON library for embedded systems.*
|
||||
|
||||
It's design to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
|
||||
|
||||
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* JSON decoding
|
||||
* JSON encoding (with optional indentation)
|
||||
* Elegant API, very easy to use
|
||||
* Fixed memory allocation (no malloc)
|
||||
* Small footprint
|
||||
* MIT License
|
||||
|
||||
Quick start
|
||||
-----------
|
||||
|
||||
#### Decoding / Parsing
|
||||
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
#### Encoding / Generating
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080, 6); // 6 is the number of decimals to print
|
||||
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The documentation is available online in the [Arduino JSON wiki](https://github.com/bblanchon/ArduinoJson/wiki)
|
||||
|
||||
Testimonials
|
||||
------------
|
||||
|
||||
From Arduino's Forum user `jflaplante`:
|
||||
> I tried aJson json-arduino before trying your library. I always ran into memory problem after a while.
|
||||
> I have no such problem so far with your library. It is working perfectly with my web services.
|
||||
|
||||
From Arduino's Forum user `gbathree`:
|
||||
> Thanks so much - this is an awesome library! If you want to see what we're doing with it - the project is located at www.photosynq.org.
|
||||
|
||||
From StackOverflow user `thegreendroid`:
|
||||
> It has a really elegant, simple API and it works like a charm on embedded and Windows/Linux platforms. We recently started using this on an embedded project and I can vouch for its quality.
|
||||
|
||||
From GitHub user `zacsketches`:
|
||||
|
||||
> Thanks for a great library!!!
|
||||
> I've been watching you consistently develop this library over the past six months, and I used it today for a publish and subscribe architecture designed to help hobbyists move into more advanced robotics. Your library allowed me to implement remote subscription in order to facilitate multi-processor robots.
|
||||
> ArduinoJson saved me a week's worth of time!!
|
||||

|
||||
|
||||
---
|
||||
|
||||
Found this library useful? [Help me back with a donation!](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile:
|
||||
[](https://www.ardu-badge.com/ArduinoJson/5.13.5)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master)
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
[](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
|
||||
[](https://github.com/bblanchon/ArduinoJson)
|
||||
|
||||
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
|
||||
## Features
|
||||
|
||||
* JSON decoding (comments are supported)
|
||||
* JSON encoding (with optional indentation)
|
||||
* Elegant API, easy to use
|
||||
* Fixed memory allocation (zero malloc)
|
||||
* No data duplication (zero copy)
|
||||
* Portable (written in C++98, can be used in any C++ project)
|
||||
* Self-contained (no external dependency)
|
||||
* Small footprint
|
||||
* Input and output streams
|
||||
* [100% code coverage](https://coveralls.io/github/bblanchon/ArduinoJson)
|
||||
* [Header-only library](https://en.wikipedia.org/wiki/Header-only)
|
||||
* [MIT License](https://en.wikipedia.org/wiki/MIT_License)
|
||||
* [Comprehensive documentation](https://arduinojson.org?utm_source=github&utm_medium=readme)
|
||||
|
||||
## Compatibility
|
||||
|
||||
ArduinoJson works on the following hardware:
|
||||
|
||||
* <img src="https://www.arduino.cc/favicon.ico" height="16" width="16"> Arduino boards: [Uno](https://www.arduino.cc/en/Main/ArduinoBoardUno), [Due](https://www.arduino.cc/en/Main/ArduinoBoardDue), [Mini](https://www.arduino.cc/en/Main/ArduinoBoardMini), [Micro](https://www.arduino.cc/en/Main/ArduinoBoardMicro), [Yun](https://www.arduino.cc/en/Main/ArduinoBoardYun)...
|
||||
* <img src="http://espressif.com/sites/all/themes/espressif/favicon.ico" height="16" width="16"> Espressif chips: [ESP8266](https://en.wikipedia.org/wiki/ESP8266), [ESP32](https://en.wikipedia.org/wiki/ESP32)
|
||||
* <img src="https://www.wemos.cc/themes/martin-materialize-parallax/assets/favicon.ico" height="16" width="16"> WeMos boards: [D1](https://wiki.wemos.cc/products:d1:d1), [D1 mini](https://wiki.wemos.cc/products:d1:d1_mini), ...
|
||||
* <img src="http://redbearlab.com/favicon.ico" height="16" width="16"> RedBearLab boards: [BLE Nano](http://redbearlab.com/blenano/), [BLE Mini](http://redbearlab.com/blemini/), [WiFi Micro](https://redbear.cc/product/wifi/wifi-micro.html), [LOLIN32](https://wiki.wemos.cc/products:lolin32:lolin32)...
|
||||
* <img src="https://www.pjrc.com/favicon.ico" height="16" width="16"> [Teensy](https://www.pjrc.com/teensy/) boards
|
||||
* <img src="https://software.intel.com/sites/all/themes/zero/favicon.ico" height="16" width="16"> Intel boards: Edison, Galileo...
|
||||
* <img src="https://www-assets.particle.io/images/favicon.png" height="16" width="16"> Particle boards: [Photon](https://www.particle.io/products/hardware/photon-wifi-dev-kit), [Electron](https://www.particle.io/products/hardware/electron-cellular-dev-kit)...
|
||||
* <img src="http://www.ti.com/favicon.ico" height="16" width="16"> Texas Instruments boards: [MSP430](http://www.ti.com/microcontrollers/msp430-ultra-low-power-mcus/overview/overview.html)...
|
||||
|
||||
ArduinoJson compiles with zero warning on the following compilers, IDEs, and platforms:
|
||||
|
||||
* <img src="https://www.arduino.cc/favicon.ico" height="16" width="16"> [Arduino IDE](https://www.arduino.cc/en/Main/Software)
|
||||
* <img src="http://cdn.platformio.org/favicon.ico" height="16" width="16"> [PlatformIO](http://platformio.org/)
|
||||
* <img src="http://energia.nu/img/favicon.ico" height="16" width="16"> [Energia](http://energia.nu/)
|
||||
* <img src="http://www.visualmicro.com/pics/arduino-visual-studio-ld.png" height="16" width="16"> [Visual Micro](http://www.visualmicro.com/)
|
||||
* <img src="http://www.atmel.com/Images/favicon.ico" height="16" width="16"> [Atmel Studio](http://www.atmel.com/microsite/atmel-studio/)
|
||||
* <img src="https://www.iar.com/favicon.ico" height="16" width="16"> [IAR Embedded Workbench](https://www.iar.com/iar-embedded-workbench/)
|
||||
* <img src="http://www.st.com/etc/clientlibs/st-site/media/app/images/favicon.png" height="16" width="16"> [Atollic TrueSTUDIO](https://atollic.com/truestudio/)
|
||||
* <img src="http://www.keil.com/favicon.ico" height="16" width="16"> [Keil uVision](http://www.keil.com/)
|
||||
* <img src="http://www.microchip.com/favicon.ico" height="16" width="16"> [MPLAB X IDE](http://www.microchip.com/mplab/mplab-x-ide)
|
||||
* <img src="https://gcc.gnu.org/favicon.ico" height="16" width="16"> [GCC](https://gcc.gnu.org/)
|
||||
* <img src="https://clang.llvm.org/favicon.ico" height="16" width="16"> [Clang](https://clang.llvm.org/)
|
||||
* <img src="https://www.visualstudio.com/favicon.ico" height="16" width="16"> [Visual Studio](https://www.visualstudio.com/)
|
||||
|
||||
## Quickstart
|
||||
|
||||
### Deserialization
|
||||
|
||||
Here is a program that parses a JSON document with ArduinoJson.
|
||||
|
||||
```c++
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
```
|
||||
|
||||
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme)
|
||||
|
||||
### Serialization
|
||||
|
||||
Here is a program that generates a JSON document with ArduinoJson:
|
||||
|
||||
```c++
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
```
|
||||
|
||||
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme)
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation is available on [arduinojson.org](https://arduinojson.org/?utm_source=github&utm_medium=readme), here are some shortcuts:
|
||||
|
||||
* The [Examples](https://arduinojson.org/example/?utm_source=github&utm_medium=readme) show how to use the library in various situations.
|
||||
* The [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=readme) contains the description of each class and function.
|
||||
* The [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=readme) has the answer to virtually every question.
|
||||
* The [ArduinoJson Assistant](https://arduinojson.org/assistant/?utm_source=github&utm_medium=readme) writes programs for you!
|
||||
|
||||
---
|
||||
|
||||
Do you like this library? Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)!
|
||||
|
||||
What? You don't like it but you *love* it?
|
||||
We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time!
|
||||
|
27
SUPPORT.md
Normal file
27
SUPPORT.md
Normal file
@ -0,0 +1,27 @@
|
||||
# ArduinoJson Support
|
||||
|
||||
First off, thank you very much for using ArduinoJson.
|
||||
|
||||
We'll be very happy to help you, but first please read the following.
|
||||
|
||||
## Before asking for help
|
||||
|
||||
1. Read the [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=support)
|
||||
2. Search in the [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=support)
|
||||
|
||||
If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new).
|
||||
|
||||
It is OK to add a comment to a currently opened issue, but please avoid adding comments to a closed issue.
|
||||
|
||||
## Before hitting the Submit button
|
||||
|
||||
Please provide all the relevant information:
|
||||
|
||||
* Good title
|
||||
* Short description of the problem
|
||||
* Target platform
|
||||
* Compiler model and version
|
||||
* [MVCE](https://stackoverflow.com/help/mcve)
|
||||
* Compiler output
|
||||
|
||||
Good questions get fast answers!
|
20
appveyor.yml
Normal file
20
appveyor.yml
Normal file
@ -0,0 +1,20 @@
|
||||
version: 5.13.5.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
CMAKE_GENERATOR: Visual Studio 12 2013
|
||||
- CMAKE_GENERATOR: Visual Studio 11 2012
|
||||
- CMAKE_GENERATOR: Visual Studio 10 2010
|
||||
- CMAKE_GENERATOR: MinGW Makefiles
|
||||
configuration: Debug
|
||||
before_build:
|
||||
- set PATH=C:\MinGW\bin;%PATH:C:\Program Files\Git\usr\bin;=% # Workaround for CMake not wanting sh.exe on PATH for MinGW
|
||||
- cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -G "%CMAKE_GENERATOR%" .
|
||||
build_script:
|
||||
- cmake --build . --config %CONFIGURATION%
|
||||
test_script:
|
||||
- ctest --output-on-failure .
|
367
banner.svg
Normal file
367
banner.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 32 KiB |
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library - IndentedPrint example
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
IndentedPrint serial(Serial);
|
||||
serial.setTabSize(4);
|
||||
|
||||
serial.println("This is at indentation 0");
|
||||
serial.indent();
|
||||
serial.println("This is at indentation 1");
|
||||
serial.println("This is also at indentation 1");
|
||||
serial.indent();
|
||||
serial.println("This is at indentation 2");
|
||||
|
||||
serial.unindent();
|
||||
serial.unindent();
|
||||
serial.println("This is back at indentation 0");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
144
examples/JsonConfigFile/JsonConfigFile.ino
Normal file
144
examples/JsonConfigFile/JsonConfigFile.ino
Normal file
@ -0,0 +1,144 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to store your project configuration in a file.
|
||||
// It uses the SD library but can be easily modified for any other file-system.
|
||||
//
|
||||
// The file contains a JSON document with the following content:
|
||||
// {
|
||||
// "hostname": "examples.com",
|
||||
// "port": 2731
|
||||
// }
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <SD.h>
|
||||
#include <SPI.h>
|
||||
|
||||
// Configuration that we'll store on disk
|
||||
struct Config {
|
||||
char hostname[64];
|
||||
int port;
|
||||
};
|
||||
|
||||
const char *filename = "/config.txt"; // <- SD library uses 8.3 filenames
|
||||
Config config; // <- global configuration object
|
||||
|
||||
// Loads the configuration from a file
|
||||
void loadConfiguration(const char *filename, Config &config) {
|
||||
// Open file for reading
|
||||
File file = SD.open(filename);
|
||||
|
||||
// Allocate the memory pool on the stack.
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<512> jsonBuffer;
|
||||
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.parseObject(file);
|
||||
|
||||
if (!root.success())
|
||||
Serial.println(F("Failed to read file, using default configuration"));
|
||||
|
||||
// Copy values from the JsonObject to the Config
|
||||
config.port = root["port"] | 2731;
|
||||
strlcpy(config.hostname, // <- destination
|
||||
root["hostname"] | "example.com", // <- source
|
||||
sizeof(config.hostname)); // <- destination's capacity
|
||||
|
||||
// Close the file (File's destructor doesn't close the file)
|
||||
file.close();
|
||||
}
|
||||
|
||||
// Saves the configuration to a file
|
||||
void saveConfiguration(const char *filename, const Config &config) {
|
||||
// Delete existing file, otherwise the configuration is appended to the file
|
||||
SD.remove(filename);
|
||||
|
||||
// Open file for writing
|
||||
File file = SD.open(filename, FILE_WRITE);
|
||||
if (!file) {
|
||||
Serial.println(F("Failed to create file"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the memory pool on the stack
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Use https://arduinojson.org/assistant/ to compute the capacity.
|
||||
StaticJsonBuffer<256> jsonBuffer;
|
||||
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.createObject();
|
||||
|
||||
// Set the values
|
||||
root["hostname"] = config.hostname;
|
||||
root["port"] = config.port;
|
||||
|
||||
// Serialize JSON to file
|
||||
if (root.printTo(file) == 0) {
|
||||
Serial.println(F("Failed to write to file"));
|
||||
}
|
||||
|
||||
// Close the file (File's destructor doesn't close the file)
|
||||
file.close();
|
||||
}
|
||||
|
||||
// Prints the content of a file to the Serial
|
||||
void printFile(const char *filename) {
|
||||
// Open file for reading
|
||||
File file = SD.open(filename);
|
||||
if (!file) {
|
||||
Serial.println(F("Failed to read file"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract each characters by one by one
|
||||
while (file.available()) {
|
||||
Serial.print((char)file.read());
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// Close the file (File's destructor doesn't close the file)
|
||||
file.close();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Initialize SD library
|
||||
while (!SD.begin()) {
|
||||
Serial.println(F("Failed to initialize SD library"));
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// Should load default config if run for the first time
|
||||
Serial.println(F("Loading configuration..."));
|
||||
loadConfiguration(filename, config);
|
||||
|
||||
// Create configuration file
|
||||
Serial.println(F("Saving configuration..."));
|
||||
saveConfiguration(filename, config);
|
||||
|
||||
// Dump config file
|
||||
Serial.println(F("Print config file..."));
|
||||
printFile(filename);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization or deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a case study of a project that has
|
||||
// a complex configuration with nested members.
|
||||
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
@ -1,23 +1,49 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize Serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer(200);
|
||||
|
||||
// Create the root of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
// Add values in the object
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do root.set<long>("time", 1351824120);
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
// Add a nested array.
|
||||
//
|
||||
// It's also possible to create the array separately and add it to the
|
||||
// JsonObject but it's less efficient.
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080, 6); // 6 is the number of decimals to print
|
||||
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
@ -39,4 +65,17 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like serializing directly to a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
112
examples/JsonHttpClient/JsonHttpClient.ino
Normal file
112
examples/JsonHttpClient/JsonHttpClient.ino
Normal file
@ -0,0 +1,112 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to parse a JSON document in an HTTP response.
|
||||
// It uses the Ethernet library, but can be easily adapted for Wifi.
|
||||
//
|
||||
// It performs a GET resquest on arduinojson.org/example.json
|
||||
// Here is the expected response:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [
|
||||
// 48.756080,
|
||||
// 2.302038
|
||||
// ]
|
||||
// }
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
#include <SPI.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize Serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Initialize Ethernet library
|
||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||
if (!Ethernet.begin(mac)) {
|
||||
Serial.println(F("Failed to configure Ethernet"));
|
||||
return;
|
||||
}
|
||||
delay(1000);
|
||||
|
||||
Serial.println(F("Connecting..."));
|
||||
|
||||
// Connect to HTTP server
|
||||
EthernetClient client;
|
||||
client.setTimeout(10000);
|
||||
if (!client.connect("arduinojson.org", 80)) {
|
||||
Serial.println(F("Connection failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println(F("Connected!"));
|
||||
|
||||
// Send HTTP request
|
||||
client.println(F("GET /example.json HTTP/1.0"));
|
||||
client.println(F("Host: arduinojson.org"));
|
||||
client.println(F("Connection: close"));
|
||||
if (client.println() == 0) {
|
||||
Serial.println(F("Failed to send request"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check HTTP status
|
||||
char status[32] = {0};
|
||||
client.readBytesUntil('\r', status, sizeof(status));
|
||||
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
|
||||
Serial.print(F("Unexpected response: "));
|
||||
Serial.println(status);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip HTTP headers
|
||||
char endOfHeaders[] = "\r\n\r\n";
|
||||
if (!client.find(endOfHeaders)) {
|
||||
Serial.println(F("Invalid response"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
|
||||
DynamicJsonBuffer jsonBuffer(capacity);
|
||||
|
||||
// Parse JSON object
|
||||
JsonObject& root = jsonBuffer.parseObject(client);
|
||||
if (!root.success()) {
|
||||
Serial.println(F("Parsing failed!"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract values
|
||||
Serial.println(F("Response:"));
|
||||
Serial.println(root["sensor"].as<char*>());
|
||||
Serial.println(root["time"].as<char*>());
|
||||
Serial.println(root["data"][0].as<char*>());
|
||||
Serial.println(root["data"][1].as<char*>());
|
||||
|
||||
// Disconnect
|
||||
client.stop();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization
|
||||
// showing how to parse the response from Yahoo Weather. In the last chapter,
|
||||
// it shows how to parse the huge documents from OpenWeatherMap
|
||||
// and Weather Underground.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
@ -1,31 +1,59 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer(200);
|
||||
|
||||
// JSON input string.
|
||||
//
|
||||
// It's better to use a char[] as shown here.
|
||||
// If you use a const char* or a String, ArduinoJson will
|
||||
// have to make a copy of the input in the JsonBuffer.
|
||||
char json[] =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
// Root of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (!root.success()) {
|
||||
Serial.println("parseObject() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do root["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
// Print values.
|
||||
Serial.println(sensor);
|
||||
Serial.println(time);
|
||||
Serial.println(latitude, 6);
|
||||
@ -34,4 +62,17 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like deserializing directly from a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,74 +1,109 @@
|
||||
// Sample Arduino Json Web Server
|
||||
// Created by Benoit Blanchon.
|
||||
// Heavily inspired by "Web Server" from David A. Mellis and Tom Igoe
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to implement an HTTP server that sends JSON document
|
||||
// in the responses.
|
||||
// It uses the Ethernet library but can be easily adapted for Wifi.
|
||||
//
|
||||
// It sends the value of the analog and digital pins.
|
||||
// The JSON document looks like the following:
|
||||
// {
|
||||
// "analog": [ 0, 1, 2, 3, 4, 5 ],
|
||||
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
|
||||
// }
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Ethernet.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
#include <SPI.h>
|
||||
|
||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||
IPAddress ip(192, 168, 0, 177);
|
||||
EthernetServer server(80);
|
||||
|
||||
bool readRequest(EthernetClient& client) {
|
||||
bool currentLineIsBlank = true;
|
||||
while (client.connected()) {
|
||||
if (client.available()) {
|
||||
char c = client.read();
|
||||
if (c == '\n' && currentLineIsBlank) {
|
||||
return true;
|
||||
} else if (c == '\n') {
|
||||
currentLineIsBlank = true;
|
||||
} else if (c != '\r') {
|
||||
currentLineIsBlank = false;
|
||||
}
|
||||
}
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Initialize Ethernet libary
|
||||
if (!Ethernet.begin(mac)) {
|
||||
Serial.println(F("Failed to initialize Ethernet library"));
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
|
||||
// Start to listen
|
||||
server.begin();
|
||||
|
||||
Serial.println(F("Server is ready."));
|
||||
Serial.print(F("Please connect to http://"));
|
||||
Serial.println(Ethernet.localIP());
|
||||
}
|
||||
|
||||
JsonObject& prepareResponse(JsonBuffer& jsonBuffer) {
|
||||
void loop() {
|
||||
// Wait for an incomming connection
|
||||
EthernetClient client = server.available();
|
||||
|
||||
// Do we have a client?
|
||||
if (!client) return;
|
||||
|
||||
Serial.println(F("New client"));
|
||||
|
||||
// Read the request (we ignore the content in this example)
|
||||
while (client.available()) client.read();
|
||||
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
// Read the analog input
|
||||
int value = analogRead(pin);
|
||||
|
||||
// Add the value at the end of the array
|
||||
analogValues.add(value);
|
||||
}
|
||||
|
||||
// Create the "digital" array
|
||||
JsonArray& digitalValues = root.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
// Read the digital input
|
||||
int value = digitalRead(pin);
|
||||
|
||||
// Add the value at the end of the array
|
||||
digitalValues.add(value);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
Serial.print(F("Sending: "));
|
||||
root.printTo(Serial);
|
||||
Serial.println();
|
||||
|
||||
void writeResponse(EthernetClient& client, JsonObject& json) {
|
||||
client.println("HTTP/1.1 200 OK");
|
||||
// Write response headers
|
||||
client.println("HTTP/1.0 200 OK");
|
||||
client.println("Content-Type: application/json");
|
||||
client.println("Connection: close");
|
||||
client.println();
|
||||
|
||||
json.prettyPrintTo(client);
|
||||
// Write JSON document
|
||||
root.prettyPrintTo(client);
|
||||
|
||||
// Disconnect
|
||||
client.stop();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Ethernet.begin(mac, ip);
|
||||
server.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
EthernetClient client = server.available();
|
||||
if (client) {
|
||||
bool success = readRequest(client);
|
||||
if (success) {
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
JsonObject& json = prepareResponse(jsonBuffer);
|
||||
writeResponse(client, json);
|
||||
}
|
||||
delay(1);
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or an HTTP client.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,55 +1,101 @@
|
||||
// Send a JSON object on UDP at regular interval
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// You can easily test this program with netcat:
|
||||
// $ nc -ulp 8888
|
||||
// This example shows how to send a JSON document to a UDP socket.
|
||||
// At regular interval, it sends a UDP packet that contains the status of
|
||||
// analog and digital pins.
|
||||
// The JSON document looks like the following:
|
||||
// {
|
||||
// "analog": [ 0, 1, 2, 3, 4, 5 ],
|
||||
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
|
||||
// }
|
||||
//
|
||||
// by Benoit Blanchon, MIT License 2015
|
||||
// If you want to test this program, you need to be able to receive the UDP
|
||||
// packets.
|
||||
// For example, you can run netcat on your computer
|
||||
// $ ncat -ulp 8888
|
||||
// See https://nmap.org/ncat/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Ethernet.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
#include <SPI.h>
|
||||
|
||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||
IPAddress localIp(192, 168, 0, 177);
|
||||
IPAddress remoteIp(192, 168, 0, 109);
|
||||
unsigned int remotePort = 8888;
|
||||
unsigned localPort = 8888;
|
||||
IPAddress remoteIp(192, 168, 0, 108); // <- EDIT!!!!
|
||||
unsigned short remotePort = 8888;
|
||||
unsigned short localPort = 8888;
|
||||
EthernetUDP udp;
|
||||
|
||||
JsonObject& buildJson(JsonBuffer& jsonBuffer) {
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
int value = analogRead(pin);
|
||||
analogValues.add(value);
|
||||
}
|
||||
|
||||
JsonArray& digitalValues = root.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
int value = digitalRead(pin);
|
||||
digitalValues.add(value);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void sendJson(JsonObject& json) {
|
||||
udp.beginPacket(remoteIp, remotePort);
|
||||
json.printTo(udp);
|
||||
udp.println();
|
||||
udp.endPacket();
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Ethernet.begin(mac, localIp);
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Initialize Ethernet libary
|
||||
if (!Ethernet.begin(mac)) {
|
||||
Serial.println(F("Failed to initialize Ethernet library"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable UDP
|
||||
udp.begin(localPort);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(1000);
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
|
||||
StaticJsonBuffer<300> jsonBuffer;
|
||||
JsonObject& json = buildJson(jsonBuffer);
|
||||
sendJson(json);
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
// Read the analog input
|
||||
int value = analogRead(pin);
|
||||
|
||||
// Add the value at the end of the array
|
||||
analogValues.add(value);
|
||||
}
|
||||
|
||||
// Create the "digital" array
|
||||
JsonArray& digitalValues = root.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
// Read the digital input
|
||||
int value = digitalRead(pin);
|
||||
|
||||
// Add the value at the end of the array
|
||||
digitalValues.add(value);
|
||||
}
|
||||
|
||||
// Log
|
||||
Serial.print(F("Sending to "));
|
||||
Serial.print(remoteIp);
|
||||
Serial.print(F(" on port "));
|
||||
Serial.println(remotePort);
|
||||
root.printTo(Serial);
|
||||
|
||||
// Send UDP packet
|
||||
udp.beginPacket(remoteIp, remotePort);
|
||||
root.printTo(udp);
|
||||
udp.println();
|
||||
udp.endPacket();
|
||||
|
||||
// Wait
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or any stream.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
70
examples/ProgmemExample/ProgmemExample.ino
Normal file
70
examples/ProgmemExample/ProgmemExample.ino
Normal file
@ -0,0 +1,70 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
// code size, speed, and memory usage.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
#ifdef PROGMEM // <- check that Flash strings are supported
|
||||
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
// You can use a Flash String as your JSON input.
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
JsonObject& root =
|
||||
jsonBuffer.parseObject(F("{\"sensor\":\"gps\",\"time\":1351824120,"
|
||||
"\"data\":[48.756080,2.302038]}"));
|
||||
|
||||
// You can use a Flash String to get an element of a JsonObject
|
||||
// No duplication is done.
|
||||
long time = root[F("time")];
|
||||
|
||||
// You can use a Flash String to set an element of a JsonObject
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
root[F("time")] = time;
|
||||
|
||||
// You can set a Flash String to a JsonObject or JsonArray:
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
root["sensor"] = F("gps");
|
||||
|
||||
// It works with RawJson too:
|
||||
root["sensor"] = RawJson(F("\"gps\""));
|
||||
|
||||
// You can compare the content of a JsonVariant to a Flash String
|
||||
if (root["sensor"] == F("gps")) {
|
||||
// ...
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#warning PROGMEM is not supported on this platform
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any memory
|
||||
// problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. It also tells why you
|
||||
// should not abuse Flash strings with ArduinoJson.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
74
examples/StringExample/StringExample.ino
Normal file
74
examples/StringExample/StringExample.ino
Normal file
@ -0,0 +1,74 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// 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
|
||||
// code size, speed, and memory usage.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
// You can use a String as your JSON input.
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
String input =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
JsonObject& root = jsonBuffer.parseObject(input);
|
||||
|
||||
// You can use a String to get an element of a JsonObject
|
||||
// No duplication is done.
|
||||
long time = root[String("time")];
|
||||
|
||||
// You can use a String to set an element of a JsonObject
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
root[String("time")] = time;
|
||||
|
||||
// You can get a String from a JsonObject or JsonArray:
|
||||
// No duplication is done, at least not in the JsonBuffer.
|
||||
String sensor = root["sensor"];
|
||||
|
||||
// Unfortunately, the following doesn't work (issue #118):
|
||||
// sensor = root["sensor"]; // <- error "ambiguous overload for 'operator='"
|
||||
// As a workaround, you need to replace by:
|
||||
sensor = root["sensor"].as<String>();
|
||||
|
||||
// You can set a String to a JsonObject or JsonArray:
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
root["sensor"] = sensor;
|
||||
|
||||
// It works with RawJson too:
|
||||
root["sensor"] = RawJson(sensor);
|
||||
|
||||
// You can also concatenate strings
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
root[String("sen") + "sor"] = String("gp") + "s";
|
||||
|
||||
// You can compare the content of a JsonObject with a String
|
||||
if (root["sensor"] == sensor) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// Lastly, you can print the resulting JSON to a String
|
||||
String output;
|
||||
root.printTo(output);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. On several occasions, it
|
||||
// shows how you can avoid String in your program.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
19
fuzzing/Makefile
Normal file
19
fuzzing/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
|
||||
|
||||
CXXFLAGS += -I../src
|
||||
|
||||
all: \
|
||||
$(OUT)/json_fuzzer \
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/json_fuzzer.options
|
||||
|
||||
$(OUT)/json_fuzzer: fuzzer.cpp $(shell find ../src -type f)
|
||||
$(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE)
|
||||
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip: seed_corpus/*
|
||||
zip -j $@ $?
|
||||
|
||||
$(OUT)/json_fuzzer.options:
|
||||
@echo "[libfuzzer]" > $@
|
||||
@echo "max_len = 256" >> $@
|
||||
@echo "timeout = 10" >> $@
|
26
fuzzing/fuzzer.cpp
Normal file
26
fuzzing/fuzzer.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class memstream : public std::istream {
|
||||
struct membuf : std::streambuf {
|
||||
membuf(const uint8_t *p, size_t l) {
|
||||
setg((char *)p, (char *)p, (char *)p + l);
|
||||
}
|
||||
};
|
||||
membuf _buffer;
|
||||
|
||||
public:
|
||||
memstream(const uint8_t *p, size_t l)
|
||||
: std::istream(&_buffer), _buffer(p, l) {
|
||||
rdbuf(&_buffer);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
memstream json(data, size);
|
||||
JsonVariant variant = jsonBuffer.parse(json);
|
||||
if (variant.success()) {
|
||||
variant.as<std::string>(); // <- serialize to JSON
|
||||
}
|
||||
return 0;
|
||||
}
|
2
fuzzing/my_corpus/.gitignore
vendored
Normal file
2
fuzzing/my_corpus/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
10
fuzzing/seed_corpus/Comments.json
Normal file
10
fuzzing/seed_corpus/Comments.json
Normal file
@ -0,0 +1,10 @@
|
||||
//comment
|
||||
/*comment*/
|
||||
[ //comment
|
||||
/*comment*/"comment"/*comment*/,//comment
|
||||
/*comment*/{//comment
|
||||
/* comment*/"key"//comment
|
||||
: //comment
|
||||
"value"//comment
|
||||
}/*comment*/
|
||||
]//comment
|
1
fuzzing/seed_corpus/EmptyArray.json
Normal file
1
fuzzing/seed_corpus/EmptyArray.json
Normal file
@ -0,0 +1 @@
|
||||
[]
|
1
fuzzing/seed_corpus/EmptyObject.json
Normal file
1
fuzzing/seed_corpus/EmptyObject.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
1
fuzzing/seed_corpus/ExcessiveNesting.json
Normal file
1
fuzzing/seed_corpus/ExcessiveNesting.json
Normal file
@ -0,0 +1 @@
|
||||
[1,[2,[3,[4,[5,[6,[7,[8,[9,[10,[11,[12,[13,[14,[15,[16,[17,[18,[19,[20,[21,[22,[23,[24,[25,[26,[27,[28,[29,[30,[31,[32,[33,[34,[35,[36,[37,[38,[39,[40,[41,[42,[43,[44,[45,[46,[47,[48,[49,[50,[51,[52,[53,[54,[55,[56,[57,[58,[59,[60,[61,[62,[63,[64,[65,[66,[67,[68,[69,[70,[71,[72,[73,[74,[75,[76,[77,[78,[79,[80,[81,[82,[83,[84,[85,[86,[87,[88,[89,[90,[91,[92,[93,[94,[95,[96,[97,[98,[99,[100,[101,[102,[103,[104,[105,[106,[107,[108,[109,[110,[111,[112,[113,[114,[115,[116,[117,[118,[119,[120]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
|
24
fuzzing/seed_corpus/Numbers.json
Normal file
24
fuzzing/seed_corpus/Numbers.json
Normal file
@ -0,0 +1,24 @@
|
||||
[
|
||||
123,
|
||||
-123,
|
||||
123.456,
|
||||
-123.456,
|
||||
12e34,
|
||||
12e-34,
|
||||
12e+34,
|
||||
12E34,
|
||||
12E-34,
|
||||
12E+34,
|
||||
12.34e56,
|
||||
12.34e-56,
|
||||
12.34e+56,
|
||||
12.34E56,
|
||||
12.34E-56,
|
||||
12.34E+56,
|
||||
NaN,
|
||||
-NaN,
|
||||
+NaN,
|
||||
Infinity,
|
||||
+Infinity,
|
||||
-Infinity
|
||||
]
|
53
fuzzing/seed_corpus/OpenWeatherMap.json
Normal file
53
fuzzing/seed_corpus/OpenWeatherMap.json
Normal file
@ -0,0 +1,53 @@
|
||||
{
|
||||
"coord": {
|
||||
"lon": -0.13,
|
||||
"lat": 51.51
|
||||
},
|
||||
"weather": [
|
||||
{
|
||||
"id": 301,
|
||||
"main": "Drizzle",
|
||||
"description": "drizzle",
|
||||
"icon": "09n"
|
||||
},
|
||||
{
|
||||
"id": 701,
|
||||
"main": "Mist",
|
||||
"description": "mist",
|
||||
"icon": "50n"
|
||||
},
|
||||
{
|
||||
"id": 741,
|
||||
"main": "Fog",
|
||||
"description": "fog",
|
||||
"icon": "50n"
|
||||
}
|
||||
],
|
||||
"base": "stations",
|
||||
"main": {
|
||||
"temp": 281.87,
|
||||
"pressure": 1032,
|
||||
"humidity": 100,
|
||||
"temp_min": 281.15,
|
||||
"temp_max": 283.15
|
||||
},
|
||||
"visibility": 2900,
|
||||
"wind": {
|
||||
"speed": 1.5
|
||||
},
|
||||
"clouds": {
|
||||
"all": 90
|
||||
},
|
||||
"dt": 1483820400,
|
||||
"sys": {
|
||||
"type": 1,
|
||||
"id": 5091,
|
||||
"message": 0.0226,
|
||||
"country": "GB",
|
||||
"sunrise": 1483776245,
|
||||
"sunset": 1483805443
|
||||
},
|
||||
"id": 2643743,
|
||||
"name": "London",
|
||||
"cod": 200
|
||||
}
|
8
fuzzing/seed_corpus/Strings.json
Normal file
8
fuzzing/seed_corpus/Strings.json
Normal file
@ -0,0 +1,8 @@
|
||||
[
|
||||
"hello",
|
||||
'hello',
|
||||
hello,
|
||||
{"hello":"world"},
|
||||
{'hello':'world'},
|
||||
{hello:world}
|
||||
]
|
90
fuzzing/seed_corpus/WeatherUnderground.json
Normal file
90
fuzzing/seed_corpus/WeatherUnderground.json
Normal file
@ -0,0 +1,90 @@
|
||||
{
|
||||
"response": {
|
||||
"version": "0.1",
|
||||
"termsofService": "http://www.wunderground.com/weather/api/d/terms.html",
|
||||
"features": {
|
||||
"conditions": 1
|
||||
}
|
||||
},
|
||||
"current_observation": {
|
||||
"image": {
|
||||
"url": "http://icons-ak.wxug.com/graphics/wu2/logo_130x80.png",
|
||||
"title": "Weather Underground",
|
||||
"link": "http://www.wunderground.com"
|
||||
},
|
||||
"display_location": {
|
||||
"full": "San Francisco, CA",
|
||||
"city": "San Francisco",
|
||||
"state": "CA",
|
||||
"state_name": "California",
|
||||
"country": "US",
|
||||
"country_iso3166": "US",
|
||||
"zip": "94101",
|
||||
"latitude": "37.77500916",
|
||||
"longitude": "-122.41825867",
|
||||
"elevation": "47.00000000"
|
||||
},
|
||||
"observation_location": {
|
||||
"full": "SOMA - Near Van Ness, San Francisco, California",
|
||||
"city": "SOMA - Near Van Ness, San Francisco",
|
||||
"state": "California",
|
||||
"country": "US",
|
||||
"country_iso3166": "US",
|
||||
"latitude": "37.773285",
|
||||
"longitude": "-122.417725",
|
||||
"elevation": "49 ft"
|
||||
},
|
||||
"estimated": {},
|
||||
"station_id": "KCASANFR58",
|
||||
"observation_time": "Last Updated on June 27, 5:27 PM PDT",
|
||||
"observation_time_rfc822": "Wed, 27 Jun 2012 17:27:13 -0700",
|
||||
"observation_epoch": "1340843233",
|
||||
"local_time_rfc822": "Wed, 27 Jun 2012 17:27:14 -0700",
|
||||
"local_epoch": "1340843234",
|
||||
"local_tz_short": "PDT",
|
||||
"local_tz_long": "America/Los_Angeles",
|
||||
"local_tz_offset": "-0700",
|
||||
"weather": "Partly Cloudy",
|
||||
"temperature_string": "66.3 F (19.1 C)",
|
||||
"temp_f": 66.3,
|
||||
"temp_c": 19.1,
|
||||
"relative_humidity": "65%",
|
||||
"wind_string": "From the NNW at 22.0 MPH Gusting to 28.0 MPH",
|
||||
"wind_dir": "NNW",
|
||||
"wind_degrees": 346,
|
||||
"wind_mph": 22,
|
||||
"wind_gust_mph": "28.0",
|
||||
"wind_kph": 35.4,
|
||||
"wind_gust_kph": "45.1",
|
||||
"pressure_mb": "1013",
|
||||
"pressure_in": "29.93",
|
||||
"pressure_trend": "+",
|
||||
"dewpoint_string": "54 F (12 C)",
|
||||
"dewpoint_f": 54,
|
||||
"dewpoint_c": 12,
|
||||
"heat_index_string": "NA",
|
||||
"heat_index_f": "NA",
|
||||
"heat_index_c": "NA",
|
||||
"windchill_string": "NA",
|
||||
"windchill_f": "NA",
|
||||
"windchill_c": "NA",
|
||||
"feelslike_string": "66.3 F (19.1 C)",
|
||||
"feelslike_f": "66.3",
|
||||
"feelslike_c": "19.1",
|
||||
"visibility_mi": "10.0",
|
||||
"visibility_km": "16.1",
|
||||
"solarradiation": "",
|
||||
"UV": "5",
|
||||
"precip_1hr_string": "0.00 in ( 0 mm)",
|
||||
"precip_1hr_in": "0.00",
|
||||
"precip_1hr_metric": " 0",
|
||||
"precip_today_string": "0.00 in (0 mm)",
|
||||
"precip_today_in": "0.00",
|
||||
"precip_today_metric": "0",
|
||||
"icon": "partlycloudy",
|
||||
"icon_url": "http://icons-ak.wxug.com/i/c/k/partlycloudy.gif",
|
||||
"forecast_url": "http://www.wunderground.com/US/CA/San_Francisco.html",
|
||||
"history_url": "http://www.wunderground.com/history/airport/KCASANFR58/2012/6/27/DailyHistory.html",
|
||||
"ob_url": "http://www.wunderground.com/cgi-bin/findweather/getForecast?query=37.773285,-122.417725"
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../include/ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
||||
#include "../include/ArduinoJson/JsonObject.hpp"
|
||||
#include "../include/ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
@ -1,31 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// This class reproduces Arduino's Print
|
||||
class Print {
|
||||
public:
|
||||
virtual ~Print() {}
|
||||
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
|
||||
size_t print(const char[]);
|
||||
size_t print(double, int = 2);
|
||||
size_t print(long);
|
||||
size_t println();
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <Print.h>
|
||||
|
||||
#endif
|
@ -1,46 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonBuffer.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declaration
|
||||
namespace Internals {
|
||||
struct DynamicJsonBufferBlock;
|
||||
}
|
||||
|
||||
// Implements a JsonBuffer with dynamic memory allocation.
|
||||
// You are strongly encouraged to consider using StaticJsonBuffer which is much
|
||||
// more suitable for embedded systems.
|
||||
class DynamicJsonBuffer : public JsonBuffer {
|
||||
public:
|
||||
DynamicJsonBuffer();
|
||||
~DynamicJsonBuffer();
|
||||
|
||||
size_t size() const;
|
||||
|
||||
protected:
|
||||
virtual void* alloc(size_t bytes);
|
||||
|
||||
private:
|
||||
typedef Internals::DynamicJsonBufferBlock Block;
|
||||
|
||||
static const size_t FIRST_BLOCK_CAPACITY = 32;
|
||||
|
||||
static Block* createBlock(size_t capacity);
|
||||
|
||||
inline bool canAllocInHead(size_t bytes) const;
|
||||
inline void* allocInHead(size_t bytes);
|
||||
inline void addNewBlock();
|
||||
|
||||
Block* _head;
|
||||
};
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Parse JSON string to create JsonArrays and JsonObjects
|
||||
// This internal class is not indended to be used directly.
|
||||
// Instead, use JsonBuffer.parseArray() or .parseObject()
|
||||
class JsonParser {
|
||||
public:
|
||||
JsonParser(JsonBuffer *buffer, char *json, uint8_t nestingLimit)
|
||||
: _buffer(buffer), _ptr(json), _nestingLimit(nestingLimit) {}
|
||||
|
||||
JsonArray &parseArray();
|
||||
JsonObject &parseObject();
|
||||
|
||||
private:
|
||||
bool skip(char charToSkip);
|
||||
bool skip(const char *wordToSkip);
|
||||
void skipSpaces();
|
||||
|
||||
void parseAnythingTo(JsonVariant &destination);
|
||||
inline void parseBooleanTo(JsonVariant &destination);
|
||||
inline void parseNullTo(JsonVariant &destination);
|
||||
inline void parseNumberTo(JsonVariant &destination);
|
||||
inline const char *parseString();
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
char *_ptr;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IndentedPrint.hpp"
|
||||
#include "JsonWriter.hpp"
|
||||
#include "Prettyfier.hpp"
|
||||
#include "StringBuilder.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Implements all the overloads of printTo() and prettyPrintTo()
|
||||
// Caution: this class use a template parameter to avoid virtual methods.
|
||||
// This is a bit curious but allows to reduce the size of JsonVariant, JsonArray
|
||||
// and JsonObject.
|
||||
template <typename T>
|
||||
class JsonPrintable {
|
||||
public:
|
||||
size_t printTo(Print &print) const {
|
||||
JsonWriter writer(print);
|
||||
downcast().writeTo(writer);
|
||||
return writer.bytesWritten();
|
||||
}
|
||||
|
||||
size_t printTo(char *buffer, size_t bufferSize) const {
|
||||
StringBuilder sb(buffer, bufferSize);
|
||||
return printTo(sb);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(IndentedPrint &print) const {
|
||||
Prettyfier p(print);
|
||||
return printTo(p);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(char *buffer, size_t bufferSize) const {
|
||||
StringBuilder sb(buffer, bufferSize);
|
||||
return prettyPrintTo(sb);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(Print &print) const {
|
||||
IndentedPrint indentedPrint = IndentedPrint(print);
|
||||
return prettyPrintTo(indentedPrint);
|
||||
}
|
||||
|
||||
private:
|
||||
const T &downcast() const { return *static_cast<const T *>(this); }
|
||||
};
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_INVALID, // a special state for JsonVariant::invalid()
|
||||
JSON_UNDEFINED, // the JsonVariant has not been initialized
|
||||
JSON_ARRAY, // the JsonVariant stores a pointer to a JsonArray
|
||||
JSON_OBJECT, // the JsonVariant stores a pointer to a JsonObject
|
||||
JSON_BOOLEAN, // the JsonVariant stores a bool
|
||||
JSON_STRING, // the JsonVariant stores a const char*
|
||||
JSON_LONG, // the JsonVariant stores a long
|
||||
|
||||
// The following values are reserved for double values
|
||||
// Multiple values are used for double, depending on the number of decimal
|
||||
// digits that must be printed in the JSON output.
|
||||
// This little trick allow to save one extra member in JsonVariant
|
||||
JSON_DOUBLE_0_DECIMALS
|
||||
// JSON_DOUBLE_1_DECIMAL
|
||||
// JSON_DOUBLE_2_DECIMALS
|
||||
// ...
|
||||
};
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
#include "QuotedString.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Writes the JSON tokens to a Print implementation
|
||||
// This class is used by:
|
||||
// - JsonArray::writeTo()
|
||||
// - JsonObject::writeTo()
|
||||
// - JsonVariant::writeTo()
|
||||
// Its derived by PrettyJsonWriter that overrides some members to add
|
||||
// indentation.
|
||||
class JsonWriter {
|
||||
public:
|
||||
explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {}
|
||||
|
||||
// Returns the number of bytes sent to the Print implementation.
|
||||
// This is very handy for implementations of printTo() that must return the
|
||||
// number of bytes written.
|
||||
size_t bytesWritten() { return _length; }
|
||||
|
||||
void beginArray() { write('['); }
|
||||
void endArray() { write(']'); }
|
||||
|
||||
void beginObject() { write('{'); }
|
||||
void endObject() { write('}'); }
|
||||
|
||||
void writeColon() { write(':'); }
|
||||
void writeComma() { write(','); }
|
||||
|
||||
void writeString(const char *value) {
|
||||
_length += QuotedString::printTo(value, _sink);
|
||||
}
|
||||
|
||||
void writeLong(long value) { _length += _sink.print(value); }
|
||||
|
||||
void writeBoolean(bool value) {
|
||||
_length += _sink.print(value ? "true" : "false");
|
||||
}
|
||||
void writeDouble(double value, uint8_t decimals) {
|
||||
_length += _sink.print(value, decimals);
|
||||
}
|
||||
|
||||
protected:
|
||||
void write(char c) { _length += _sink.write(c); }
|
||||
void write(const char *s) { _length += _sink.print(s); }
|
||||
|
||||
Print &_sink;
|
||||
size_t _length;
|
||||
|
||||
private:
|
||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||
};
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IndentedPrint.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Converts a compact JSON string into an indented one.
|
||||
class Prettyfier : public Print {
|
||||
public:
|
||||
explicit Prettyfier(IndentedPrint& p) : _sink(p) {
|
||||
_previousChar = 0;
|
||||
_inString = false;
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t);
|
||||
|
||||
private:
|
||||
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
|
||||
|
||||
bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; }
|
||||
|
||||
size_t handleStringChar(uint8_t);
|
||||
size_t handleMarkupChar(uint8_t);
|
||||
|
||||
size_t handleBlockClose(uint8_t);
|
||||
size_t handleBlockOpen(uint8_t);
|
||||
size_t handleColumn();
|
||||
size_t handleComma();
|
||||
size_t handleQuoteOpen();
|
||||
size_t handleNormalChar(uint8_t);
|
||||
size_t indentIfNeeded();
|
||||
size_t unindentIfNeeded();
|
||||
|
||||
uint8_t _previousChar;
|
||||
IndentedPrint& _sink;
|
||||
bool _inString;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// An helper class to print and extract doubly-quoted strings
|
||||
class QuotedString {
|
||||
public:
|
||||
// Writes a doubly-quote string to a Print implementation.
|
||||
// It adds the double quotes (") at the beginning and the end of the string.
|
||||
// It escapes the special characters as required by the JSON specifications.
|
||||
static size_t printTo(const char *, Print &);
|
||||
|
||||
// Reads a doubly-quoted string from a buffer.
|
||||
// It removes the double quotes (").
|
||||
// It unescapes the special character as required by the JSON specification,
|
||||
// with the exception of the Unicode characters (\u0000).
|
||||
static char *extractFrom(char *input, char **end);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A type that is meant to be used by reference only (JsonArray and JsonObject)
|
||||
class ReferenceType {
|
||||
public:
|
||||
bool operator==(const ReferenceType& other) const {
|
||||
// two JsonArray are equal if they are the same instance
|
||||
// (we don't compare the content)
|
||||
return this == &other;
|
||||
}
|
||||
|
||||
bool operator!=(const ReferenceType& other) const { return this != &other; }
|
||||
|
||||
protected:
|
||||
ReferenceType() {}
|
||||
|
||||
private:
|
||||
// copy constructor is private
|
||||
ReferenceType(const ReferenceType&);
|
||||
|
||||
// copy operator is private
|
||||
ReferenceType& operator=(const ReferenceType&);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A Print implementation that allows to write in a char[]
|
||||
class StringBuilder : public Print {
|
||||
public:
|
||||
StringBuilder(char *buf, int size)
|
||||
: buffer(buf), capacity(size - 1), length(0) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t c);
|
||||
|
||||
private:
|
||||
char *buffer;
|
||||
int capacity;
|
||||
int length;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Internals/JsonBufferAllocated.hpp"
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/List.hpp"
|
||||
#include "Internals/ReferenceType.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(JsonArray) + (NUMBER_OF_ELEMENTS) * sizeof(JsonArray::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonObject;
|
||||
class JsonBuffer;
|
||||
|
||||
// An array of JsonVariant.
|
||||
//
|
||||
// The constructor is private, instances must be created via
|
||||
// JsonBuffer::createArray() or JsonBuffer::parseArray().
|
||||
// A JsonArray can be serialized to a JSON string via JsonArray::printTo().
|
||||
// It can also be deserialized from a JSON string via JsonBuffer::parseArray().
|
||||
class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
public Internals::ReferenceType,
|
||||
public Internals::List<JsonVariant>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
// JsonBuffer is a friend because it needs to call the private constructor.
|
||||
friend class JsonBuffer;
|
||||
|
||||
public:
|
||||
// Returns the JsonVariant at the specified index (synonym for operator[])
|
||||
JsonVariant &at(int index) const;
|
||||
|
||||
// Returns the JsonVariant at the specified index (synonym for at())
|
||||
JsonVariant &operator[](int index) const { return at(index); }
|
||||
|
||||
// Adds an uninitialized JsonVariant at the end of the array.
|
||||
// Return a reference or JsonVariant::invalid() if allocation fails.
|
||||
JsonVariant &add();
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
template <typename T>
|
||||
void add(T value) {
|
||||
add().set(value);
|
||||
}
|
||||
|
||||
// Adds the specified double value at the end of the array.
|
||||
// The value will be printed with the specified number of decimal digits.
|
||||
void add(double value, uint8_t decimals) { add().set(value, decimals); }
|
||||
|
||||
// Adds a reference to the specified JsonArray at the end of the array.
|
||||
void add(JsonArray &array) { add().set(array); }
|
||||
|
||||
// Adds a reference to the specified JsonObject at the end of the array.
|
||||
void add(JsonObject &obejct) { add().set(obejct); }
|
||||
|
||||
// Creates a JsonArray and adds a reference at the end of the array.
|
||||
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
|
||||
JsonArray &createNestedArray();
|
||||
|
||||
// Creates a JsonObject and adds a reference at the end of the array.
|
||||
// It's a shortcut for JsonBuffer::createObject() and JsonArray::add()
|
||||
JsonObject &createNestedObject();
|
||||
|
||||
// Removes element at specified index.
|
||||
void removeAt(int index);
|
||||
|
||||
// Returns a reference an invalid JsonArray.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
// This is used when memory allocation or JSON parsing fail.
|
||||
static JsonArray &invalid() { return _invalid; }
|
||||
|
||||
// Serialize the array to the specified JsonWriter.
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
private:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
explicit JsonArray(JsonBuffer *buffer)
|
||||
: Internals::List<JsonVariant>(buffer) {}
|
||||
|
||||
node_type *getNodeAt(int index) const;
|
||||
|
||||
// The instance returned by JsonArray::invalid()
|
||||
static JsonArray _invalid;
|
||||
};
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // for uint8_t
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
// Entry point for using the library.
|
||||
//
|
||||
// Handle the memory management (done in derived classes) and calls the parser.
|
||||
// This abstract class is implemented by StaticJsonBuffer which implements a
|
||||
// fixed memory allocation.
|
||||
class JsonBuffer {
|
||||
public:
|
||||
// CAUTION: NO VIRTUAL DESTRUCTOR!
|
||||
// If we add a virtual constructor the Arduino compiler will add malloc() and
|
||||
// free() to the binary, adding 706 useless bytes.
|
||||
// virtual ~JsonBuffer() {}
|
||||
|
||||
// Allocates an empty JsonArray.
|
||||
//
|
||||
// Returns a reference to the new JsonArray or JsonArray::invalid() if the
|
||||
// allocation fails.
|
||||
JsonArray &createArray();
|
||||
|
||||
// Allocates an empty JsonObject.
|
||||
//
|
||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||
// allocation fails.
|
||||
JsonObject &createObject();
|
||||
|
||||
// Allocates and populate a JsonArray from a JSON string.
|
||||
//
|
||||
// The First argument is a pointer to the JSON string, the memory must be
|
||||
// writable
|
||||
// because the parser will insert null-terminators and replace escaped chars.
|
||||
//
|
||||
// The second argument set the nesting limit (see comment on DEFAULT_LIMIT)
|
||||
//
|
||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||
// allocation fails.
|
||||
JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
||||
|
||||
// Allocates and populate a JsonObject from a JSON string.
|
||||
//
|
||||
// The First argument is a pointer to the JSON string, the memory must be
|
||||
// writable
|
||||
// because the parser will insert null-terminators and replace escaped chars.
|
||||
//
|
||||
// The second argument set the nesting limit (see comment on DEFAULT_LIMIT)
|
||||
//
|
||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||
// allocation fails.
|
||||
JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
||||
|
||||
// Allocates n bytes in the JsonBuffer.
|
||||
// Return a pointer to the allocated memory or NULL if allocation fails.
|
||||
virtual void *alloc(size_t size) = 0;
|
||||
|
||||
// Default value of nesting limit of parseArray() and parseObject().
|
||||
//
|
||||
// The nesting limit is a contain on the level of nesting allowed in the JSON
|
||||
// string.
|
||||
// If set to 0, only a flat array or objects can be parsed.
|
||||
// If set to 1, the object can contain nested arrays or objects but only 1
|
||||
// level deep.
|
||||
// And bigger values will allow more level of nesting.
|
||||
//
|
||||
// The purpose of this feature is to prevent stack overflow that could lead to
|
||||
// a security risk.
|
||||
static const uint8_t DEFAULT_LIMIT = 10;
|
||||
};
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Internals/JsonBufferAllocated.hpp"
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/List.hpp"
|
||||
#include "Internals/ReferenceType.hpp"
|
||||
#include "JsonPair.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonArray;
|
||||
class JsonBuffer;
|
||||
|
||||
// A dictionary of JsonVariant indexed by string (char*)
|
||||
//
|
||||
// The constructor is private, instances must be created via
|
||||
// JsonBuffer::createObject() or JsonBuffer::parseObject().
|
||||
// A JsonObject can be serialized to a JSON string via JsonObject::printTo().
|
||||
// It can also be deserialized from a JSON string via JsonBuffer::parseObject().
|
||||
class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
public Internals::ReferenceType,
|
||||
public Internals::List<JsonPair>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
// JsonBuffer is a friend because it needs to call the private constructor.
|
||||
friend class JsonBuffer;
|
||||
|
||||
public:
|
||||
typedef const char *key_type;
|
||||
typedef JsonPair value_type;
|
||||
|
||||
// Gets the JsonVariant associated with the specified key.
|
||||
// Returns a reference or JsonVariant::invalid() if not found.
|
||||
JsonVariant &at(key_type key);
|
||||
|
||||
// Gets the JsonVariant associated with the specified key.
|
||||
// Returns a constant reference or JsonVariant::invalid() if not found.
|
||||
const JsonVariant &at(key_type key) const;
|
||||
|
||||
// Gets or create the JsonVariant associated with the specified key.
|
||||
// Returns a reference or JsonVariant::invalid() if allocation failed.
|
||||
JsonVariant &operator[](key_type key);
|
||||
|
||||
// Gets the JsonVariant associated with the specified key.
|
||||
// Returns a constant reference or JsonVariant::invalid() if not found.
|
||||
const JsonVariant &operator[](key_type key) const { return at(key); }
|
||||
|
||||
// Adds an uninitialized JsonVariant associated with the specified key.
|
||||
// Return a reference or JsonVariant::invalid() if allocation fails.
|
||||
JsonVariant &add(key_type key) { return (*this)[key]; }
|
||||
|
||||
// Adds the specified key with the specified value.
|
||||
template <typename T>
|
||||
void add(key_type key, T value) {
|
||||
add(key).set(value);
|
||||
}
|
||||
|
||||
// Adds the specified key with a reference to the specified JsonArray.
|
||||
void add(key_type key, JsonArray &array) { add(key).set(array); }
|
||||
|
||||
// Adds the specified key with a reference to the specified JsonObject.
|
||||
void add(key_type key, JsonObject &object) { add(key).set(object); }
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
||||
JsonArray &createNestedArray(key_type key);
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
||||
JsonObject &createNestedObject(key_type key);
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
bool containsKey(key_type key) const { return at(key).success(); }
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
void remove(key_type key);
|
||||
|
||||
// Returns a reference an invalid JsonObject.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
// This is used when memory allocation or JSON parsing fail.
|
||||
static JsonObject &invalid() { return _invalid; }
|
||||
|
||||
// Serialize the object to the specified JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
private:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
explicit JsonObject(JsonBuffer *buffer) : Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Returns the list node that matches the specified key.
|
||||
node_type *getNodeAt(key_type key) const;
|
||||
|
||||
// The instance returned by JsonObject::invalid()
|
||||
static JsonObject _invalid;
|
||||
};
|
||||
}
|
@ -1,286 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h> // for uint8_t
|
||||
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/JsonVariantContent.hpp"
|
||||
#include "Internals/JsonVariantType.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
// A variant that can be a any value serializable to a JSON value.
|
||||
//
|
||||
// It can be set to:
|
||||
// - a boolean
|
||||
// - a char, short, int or a long (signed or unsigned)
|
||||
// - a string (const char*)
|
||||
// - a reference to a JsonArray or JsonObject
|
||||
class JsonVariant : public Internals::JsonPrintable<JsonVariant> {
|
||||
public:
|
||||
// Creates an uninitialized JsonVariant
|
||||
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||
|
||||
// Initializes a JsonVariant with the specified value.
|
||||
template <typename T>
|
||||
explicit JsonVariant(T value) {
|
||||
set(value);
|
||||
}
|
||||
|
||||
// Tells weither the variant is valid.
|
||||
bool success() const {
|
||||
return _type != Internals::JSON_INVALID &&
|
||||
_type != Internals::JSON_UNDEFINED;
|
||||
}
|
||||
|
||||
// Sets the variant to a boolean value.
|
||||
// It will be serialized as "true" or "false" in JSON.
|
||||
void set(bool value);
|
||||
|
||||
// Sets the variant to a floating point value.
|
||||
// The second argument specifies the number of decimal digits to write in
|
||||
// the JSON string.
|
||||
void set(double value, uint8_t decimals = 2);
|
||||
|
||||
// Sets the variant to be an integer value.
|
||||
void set(signed long value);
|
||||
void set(signed char value) { set(static_cast<long>(value)); }
|
||||
void set(signed int value) { set(static_cast<long>(value)); }
|
||||
void set(signed short value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned char value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned int value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned long value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned short value) { set(static_cast<long>(value)); }
|
||||
|
||||
// Sets the variant to be a string.
|
||||
void set(const char *value);
|
||||
|
||||
// Sets the variant to be a reference to an array.
|
||||
void set(JsonArray &array);
|
||||
|
||||
// Sets the variant to be a reference to an object.
|
||||
void set(JsonObject &object);
|
||||
|
||||
// Sets the variant to the specified value.
|
||||
template <typename T>
|
||||
JsonVariant &operator=(T value) {
|
||||
set(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the variant to be a reference to an array.
|
||||
JsonVariant &operator=(JsonArray &array) {
|
||||
set(array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the variant to be a reference to an object.
|
||||
JsonVariant &operator=(JsonObject &object) {
|
||||
set(object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Gets the variant as a boolean value.
|
||||
// Returns false if the variant is not a boolean value.
|
||||
operator bool() const;
|
||||
|
||||
// Gets the variant as a floating-point value.
|
||||
// Returns 0.0 if the variant is not a floating-point value
|
||||
operator double() const;
|
||||
operator float() const { return static_cast<float>(as<double>()); }
|
||||
|
||||
// Gets the variant as an integer value.
|
||||
// Returns 0 if the variant is not an integer value.
|
||||
operator signed long() const;
|
||||
operator signed char() const { return cast_long_to<signed char>(); }
|
||||
operator signed int() const { return cast_long_to<signed int>(); }
|
||||
operator signed short() const { return cast_long_to<signed short>(); }
|
||||
operator unsigned char() const { return cast_long_to<unsigned char>(); }
|
||||
operator unsigned int() const { return cast_long_to<unsigned int>(); }
|
||||
operator unsigned long() const { return cast_long_to<unsigned long>(); }
|
||||
operator unsigned short() const { return cast_long_to<unsigned short>(); }
|
||||
|
||||
// Gets the variant as a string.
|
||||
// Returns NULL if variant is not a string.
|
||||
operator const char *() const;
|
||||
const char *asString() const { return as<const char *>(); }
|
||||
|
||||
// Gets the variant as an array.
|
||||
// Returns a reference to the JsonArray or JsonArray::invalid() if the variant
|
||||
// is not an array.
|
||||
operator JsonArray &() const;
|
||||
JsonArray &asArray() const { return as<JsonArray &>(); }
|
||||
|
||||
// Gets the variant as an object.
|
||||
// Returns a reference to the JsonObject or JsonObject::invalid() if the
|
||||
// variant is not an object.
|
||||
operator JsonObject &() const;
|
||||
JsonObject &asObject() const { return as<JsonObject &>(); }
|
||||
|
||||
// Get the variant as the specified type.
|
||||
// See cast operators for details.
|
||||
template <typename T>
|
||||
T as() const {
|
||||
return static_cast<T>(*this);
|
||||
}
|
||||
|
||||
// Tells weither the variant has the specified type.
|
||||
// Returns true if the variant has type type T, false otherwise.
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns an invalid variant.
|
||||
// This is meant to replace a NULL pointer.
|
||||
static JsonVariant &invalid() { return _invalid; }
|
||||
|
||||
// Serialize the variant to a JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
// Mimics an array or an object.
|
||||
// Returns the size of the array or object if the variant has that type.
|
||||
// Returns 0 if the variant is neither an array nor an object
|
||||
size_t size() const;
|
||||
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
// Returns JsonVariant::invalid() if the variant is not an array.
|
||||
JsonVariant &operator[](int index);
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is an
|
||||
// object.
|
||||
// Return JsonVariant::invalid() if the variant is not an object.
|
||||
JsonVariant &operator[](const char *key);
|
||||
|
||||
private:
|
||||
// Special constructor used only to create _invalid.
|
||||
explicit JsonVariant(Internals::JsonVariantType type) : _type(type) {}
|
||||
|
||||
// Helper for interger cast operators
|
||||
template <typename T>
|
||||
T cast_long_to() const {
|
||||
return static_cast<T>(as<long>());
|
||||
}
|
||||
|
||||
// The current type of the variant
|
||||
Internals::JsonVariantType _type;
|
||||
|
||||
// The various alternatives for the value of the variant.
|
||||
Internals::JsonVariantContent _content;
|
||||
|
||||
// The instance returned by JsonVariant::invalid()
|
||||
static JsonVariant _invalid;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<long>() const {
|
||||
return _type == Internals::JSON_LONG;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<double>() const {
|
||||
return _type >= Internals::JSON_DOUBLE_0_DECIMALS;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<bool>() const {
|
||||
return _type == Internals::JSON_BOOLEAN;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<const char *>() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonArray &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<const JsonArray &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonObject &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<const JsonObject &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(const JsonVariant &left, T right) {
|
||||
return left.as<T>() == right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(T left, const JsonVariant &right) {
|
||||
return left == right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator!=(const JsonVariant &left, T right) {
|
||||
return left.as<T>() != right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator!=(T left, const JsonVariant &right) {
|
||||
return left != right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<=(const JsonVariant &left, T right) {
|
||||
return left.as<T>() <= right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<=(T left, const JsonVariant &right) {
|
||||
return left <= right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>=(const JsonVariant &left, T right) {
|
||||
return left.as<T>() >= right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>=(T left, const JsonVariant &right) {
|
||||
return left >= right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<(const JsonVariant &left, T right) {
|
||||
return left.as<T>() < right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<(T left, const JsonVariant &right) {
|
||||
return left < right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>(const JsonVariant &left, T right) {
|
||||
return left.as<T>() > right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>(T left, const JsonVariant &right) {
|
||||
return left > right.as<T>();
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Implements a JsonBuffer with fixed memory allocation.
|
||||
// The template paramenter CAPACITY specifies the capacity of the buffer in
|
||||
// bytes.
|
||||
template <size_t CAPACITY>
|
||||
class StaticJsonBuffer : public JsonBuffer {
|
||||
public:
|
||||
explicit StaticJsonBuffer() : _size(0) {}
|
||||
|
||||
size_t capacity() const { return CAPACITY; }
|
||||
size_t size() const { return _size; }
|
||||
|
||||
protected:
|
||||
virtual void* alloc(size_t bytes) {
|
||||
if (_size + bytes > CAPACITY) return NULL;
|
||||
void* p = &_buffer[_size];
|
||||
_size += bytes;
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _buffer[CAPACITY];
|
||||
size_t _size;
|
||||
};
|
||||
}
|
@ -2,6 +2,7 @@ JsonArray KEYWORD1
|
||||
JsonObject KEYWORD1
|
||||
JsonVariant KEYWORD1
|
||||
StaticJsonBuffer KEYWORD1
|
||||
DynamicJsonBuffer KEYWORD1
|
||||
add KEYWORD2
|
||||
createArray KEYWORD2
|
||||
createNestedArray KEYWORD2
|
||||
|
22
library.json
22
library.json
@ -1,17 +1,23 @@
|
||||
{
|
||||
"name": "Json",
|
||||
"name": "ArduinoJson",
|
||||
"keywords": "json, rest, http, web",
|
||||
"description": "An elegant and efficient JSON library for embedded systems",
|
||||
"repository":
|
||||
{
|
||||
"homepage": "https://arduinojson.org/?utm_source=meta&utm_medium=library.json",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"authors":
|
||||
{
|
||||
"version": "5.13.5",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "http://blog.benoitblanchon.fr"
|
||||
"url": "https://blog.benoitblanchon.fr"
|
||||
},
|
||||
"exclude": [
|
||||
"fuzzing",
|
||||
"scripts",
|
||||
"test",
|
||||
"third-party"
|
||||
],
|
||||
"frameworks": "arduino",
|
||||
"platforms": "atmelavr"
|
||||
}
|
||||
"platforms": "*"
|
||||
}
|
||||
|
11
library.properties
Normal file
11
library.properties
Normal file
@ -0,0 +1,11 @@
|
||||
name=ArduinoJson
|
||||
version=5.13.5
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ fixed allocation, ✔ zero-copy, ✔ streams, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
||||
category=Data Processing
|
||||
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
|
||||
architectures=*
|
||||
repository=https://github.com/bblanchon/ArduinoJson.git
|
||||
license=MIT
|
@ -1,23 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
ZIP="C:\Program Files\7-Zip\7z.exe"
|
||||
TAG=$(git describe)
|
||||
OUTPUT="ArduinoJson-$TAG.zip"
|
||||
|
||||
cd ../..
|
||||
|
||||
# remove existing file
|
||||
rm -f $OUTPUT
|
||||
|
||||
# create zip
|
||||
"$ZIP" a $OUTPUT \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/include \
|
||||
ArduinoJson/keywords.txt \
|
||||
ArduinoJson/LICENSE.md \
|
||||
ArduinoJson/README.md \
|
||||
ArduinoJson/src \
|
||||
ArduinoJson/ArduinoJson.h \
|
||||
ArduinoJson/ArduinoJson.cpp \
|
||||
-x!ArduinoJson/src/CMakeLists.txt
|
||||
#!/bin/bash
|
||||
|
||||
TAG=$(git describe)
|
||||
OUTPUT="ArduinoJson-$TAG.zip"
|
||||
|
||||
cd $(dirname $0)/../..
|
||||
|
||||
# remove existing file
|
||||
rm -f $OUTPUT
|
||||
|
||||
# create zip
|
||||
7z a $OUTPUT \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/src \
|
||||
ArduinoJson/keywords.txt \
|
||||
ArduinoJson/library.properties \
|
||||
ArduinoJson/LICENSE.md \
|
||||
ArduinoJson/README.md \
|
||||
ArduinoJson/ArduinoJson.h
|
||||
|
53
scripts/build-single-header.sh
Normal file
53
scripts/build-single-header.sh
Normal file
@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
|
||||
TAG=$(git describe)
|
||||
RE_INCLUDE='^#include[[:space:]]*["<](.*)[">]'
|
||||
RE_EMPTY='^(#pragma[[:space:]]+once)?[[:space:]]*(//.*)?$'
|
||||
|
||||
declare -A INCLUDED
|
||||
|
||||
process()
|
||||
{
|
||||
local PARENT=$1
|
||||
local FOLDER=$(dirname $1)
|
||||
local SHOW_COMMENT=$2
|
||||
while IFS= read -r LINE; do
|
||||
if [[ $LINE =~ $RE_INCLUDE ]]; then
|
||||
local CHILD=${BASH_REMATCH[1]}
|
||||
pushd "$FOLDER" > /dev/null
|
||||
if [[ -e $CHILD ]]; then
|
||||
local CHILD_PATH=$(realpath $CHILD)
|
||||
if [[ ! ${INCLUDED[$CHILD_PATH]} ]]; then
|
||||
#echo "// $PARENT -> $CHILD"
|
||||
INCLUDED[$CHILD_PATH]=true
|
||||
process "$CHILD" false
|
||||
fi
|
||||
else
|
||||
if [[ ! ${INCLUDED[$CHILD]} ]]; then
|
||||
echo "$LINE"
|
||||
INCLUDED[$CHILD]=true
|
||||
fi
|
||||
fi
|
||||
popd > /dev/null
|
||||
elif [[ "${SHOW_COMMENT}" = "true" ]] ; then
|
||||
echo "$LINE"
|
||||
elif [[ ! $LINE =~ $RE_EMPTY ]]; then
|
||||
echo "$LINE"
|
||||
fi
|
||||
done < $PARENT
|
||||
}
|
||||
|
||||
cd $(dirname $0)/../
|
||||
INCLUDED=()
|
||||
process src/ArduinoJson.h true > ../ArduinoJson-$TAG.h
|
||||
g++ -x c++ -c -o ../smoketest.o - <<END
|
||||
#include "../ArduinoJson-$TAG.h"
|
||||
int main() {}
|
||||
END
|
||||
|
||||
INCLUDED=()
|
||||
process src/ArduinoJson.hpp true > ../ArduinoJson-$TAG.hpp
|
||||
g++ -x c++ -c -o ../smoketest.o - <<END
|
||||
#include "../ArduinoJson-$TAG.hpp"
|
||||
int main() {}
|
||||
END
|
@ -1,5 +0,0 @@
|
||||
CPPLINT="python third-party/cpplint/cpplint.py"
|
||||
FLAGS="--filter=-runtime/printf,-runtime/int,-readability/todo,-build/namespace,-runtime/references,-readability/streams"
|
||||
|
||||
cd ..
|
||||
$CPPLINT $FLAGS $(find include src test -regex ".*\.[hc]pp$")
|
@ -20,10 +20,10 @@ build-env()
|
||||
if [[ $(uname) == MINGW* ]]
|
||||
then
|
||||
build-env "Make" "MinGW Makefiles"
|
||||
build-env "SublimeText" "Sublime Text 2 - MinGW Makefiles"
|
||||
build-env "VisualStudio" "Visual Studio 12 2013"
|
||||
build-env "SublimeText" "Sublime Text 2 - Ninja"
|
||||
build-env "VisualStudio" "Visual Studio 14 2015"
|
||||
else
|
||||
build-env "SublimeText" "Sublime Text 2 - Unix Makefiles"
|
||||
build-env "SublimeText" "Sublime Text 2 - Ninja"
|
||||
build-env "Make" "Unix Makefiles"
|
||||
build-env "Xcode" "Xcode"
|
||||
fi
|
||||
fi
|
||||
|
@ -1,7 +0,0 @@
|
||||
cd ..
|
||||
FILES=$(find include src test -regex ".*\.[ch]pp$")
|
||||
|
||||
clang-format -style=Google -i $FILES
|
||||
|
||||
# insert newline at end of file
|
||||
sed -i -e '$a\' $FILES
|
2
scripts/oss-fuzz/.gitignore
vendored
Normal file
2
scripts/oss-fuzz/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/.vagrant/
|
||||
*.log
|
33
scripts/oss-fuzz/Vagrantfile
vendored
Normal file
33
scripts/oss-fuzz/Vagrantfile
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
# A virtual machine to run https://github.com/google/oss-fuzz
|
||||
Vagrant.configure(2) do |config|
|
||||
config.vm.box = "ubuntu/xenial64"
|
||||
|
||||
config.vm.synced_folder "E:\\Git\\Arduino\\libraries\\ArduinoJson", "/host/ArduinoJson"
|
||||
config.vm.synced_folder "E:\\Git\\oss-fuzz", "/host/oss-fuzz"
|
||||
|
||||
config.vm.network "forwarded_port", guest: 8001, host: 8001
|
||||
|
||||
config.vm.provision "shell", privileged: false, inline: <<-SHELL
|
||||
set -x
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y make git docker.io zip
|
||||
sudo groupadd docker
|
||||
sudo usermod -aG docker $USER
|
||||
|
||||
git clone https://github.com/google/fuzzer-test-suite.git FTS
|
||||
./FTS/tutorial/install-deps.sh # Get deps
|
||||
./FTS/tutorial/install-clang.sh # Get fresh clang binaries
|
||||
# Get libFuzzer sources and build it
|
||||
svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
|
||||
Fuzzer/build.sh
|
||||
sudo mv libFuzzer.a /usr/local/lib/
|
||||
|
||||
echo "export PROJECT_NAME='arduinojson'" >> $HOME/.profile
|
||||
echo "export CC='clang'" >> $HOME/.profile
|
||||
echo "export CXX='clang++'" >> $HOME/.profile
|
||||
echo "export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/" >> $HOME/.profile
|
||||
|
||||
echo "Run /host/ArduinoJson/fuzzing/fuzz.sh" | sudo tee /etc/motd
|
||||
SHELL
|
||||
end
|
18
scripts/publish-particle-library.sh
Normal file
18
scripts/publish-particle-library.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
SOURCE_DIR="$(dirname "$0")/.."
|
||||
WORK_DIR=$(mktemp -d)
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
cp "$SOURCE_DIR/README.md" "$WORK_DIR/README.md"
|
||||
cp "$SOURCE_DIR/CHANGELOG.md" "$WORK_DIR/CHANGELOG.md"
|
||||
cp "$SOURCE_DIR/library.properties" "$WORK_DIR/library.properties"
|
||||
cp "$SOURCE_DIR/LICENSE.md" "$WORK_DIR/LICENSE.txt"
|
||||
cp -r "$SOURCE_DIR/src" "$WORK_DIR/"
|
||||
cp -r "$SOURCE_DIR/examples" "$WORK_DIR/"
|
||||
|
||||
cd "$WORK_DIR"
|
||||
particle library upload
|
||||
particle library publish
|
@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
FILE=../bin/ArduinoJsonTests.exe
|
||||
MD5=""
|
||||
|
||||
file_changed() {
|
||||
[[ ! -f "$FILE" ]] && return 1
|
||||
NEW_MD5=$(md5sum $FILE)
|
||||
[[ "$MD5" == "$NEW_MD5" ]] && return 1
|
||||
MD5=$NEW_MD5
|
||||
return 0
|
||||
}
|
||||
|
||||
test_succeed() {
|
||||
echo -en "\007"{,}
|
||||
}
|
||||
|
||||
test_failed() {
|
||||
echo -en "\007"{,,,,,,,,,,,}
|
||||
}
|
||||
|
||||
run_tests() {
|
||||
$FILE
|
||||
case $? in
|
||||
0)
|
||||
test_succeed
|
||||
;;
|
||||
1)
|
||||
test_failed
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
while true
|
||||
do
|
||||
if file_changed
|
||||
then
|
||||
run_tests
|
||||
else
|
||||
sleep 2
|
||||
fi
|
||||
done
|
||||
|
||||
|
16
scripts/travis/arduino.sh
Executable file
16
scripts/travis/arduino.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
|
||||
sleep 3
|
||||
export DISPLAY=:1.0
|
||||
|
||||
mkdir -p /tmp/arduino
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tar.xz | tar xJ -C /tmp/arduino --strip 1 ||
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tgz | tar xz -C /tmp/arduino --strip 1
|
||||
export PATH=$PATH:/tmp/arduino/
|
||||
|
||||
ln -s $PWD /tmp/arduino/libraries/ArduinoJson
|
||||
|
||||
for EXAMPLE in $PWD/examples/*/*.ino; do
|
||||
arduino --verify --board $BOARD $EXAMPLE
|
||||
done
|
33
scripts/travis/cmake.sh
Executable file
33
scripts/travis/cmake.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/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"
|
||||
BUILD_TYPE="Debug"
|
||||
else
|
||||
BUILD_TYPE="Release"
|
||||
fi
|
||||
|
||||
$CMAKE -DCMAKE_BUILD_TYPE=$BUILD_TYPE .
|
||||
$CMAKE --build .
|
||||
$CTEST --output-on-failure .
|
10
scripts/travis/coverage.sh
Executable file
10
scripts/travis/coverage.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/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 .
|
||||
make
|
||||
make test
|
||||
|
||||
pip install --user cpp-coveralls 'requests[security]'
|
||||
coveralls --exclude third-party --gcov-options '\-lp'; fi
|
20
scripts/travis/fuzz.sh
Executable file
20
scripts/travis/fuzz.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash -eux
|
||||
|
||||
ROOT_DIR=$(dirname $0)/../../
|
||||
INCLUDE_DIR=$ROOT_DIR/src/
|
||||
FUZZING_DIR=$ROOT_DIR/fuzzing/
|
||||
JSON_CORPUS_DIR=$FUZZING_DIR/my_corpus
|
||||
JSON_SEED_CORPUS_DIR=$FUZZING_DIR/seed_corpus
|
||||
|
||||
CXX="clang++-$CLANG"
|
||||
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,fuzzer"
|
||||
|
||||
$CXX $CXXFLAGS -o json_fuzzer -I$INCLUDE_DIR $FUZZING_DIR/fuzzer.cpp
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="json_fuzzer.profraw"
|
||||
./json_fuzzer "$JSON_CORPUS_DIR" "$JSON_SEED_CORPUS_DIR" -max_total_time=60
|
||||
|
||||
llvm-profdata-$CLANG merge -sparse json_fuzzer.profraw -o json_fuzzer.profdata
|
||||
|
||||
llvm-cov-$CLANG report ./json_fuzzer -instr-profile=json_fuzzer.profdata
|
10
scripts/travis/platformio.sh
Executable file
10
scripts/travis/platformio.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh -eux
|
||||
|
||||
pip install --user platformio
|
||||
|
||||
rm -r test
|
||||
|
||||
for EXAMPLE in $PWD/examples/*/*.ino;
|
||||
do
|
||||
platformio ci $EXAMPLE -l '.' -b $BOARD
|
||||
done
|
@ -1,52 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include "../../include/ArduinoJson/Arduino/Print.hpp"
|
||||
|
||||
#include <math.h> // for isnan() and isinf()
|
||||
#include <stdio.h> // for sprintf()
|
||||
|
||||
size_t Print::print(const char s[]) {
|
||||
size_t n = 0;
|
||||
while (*s) {
|
||||
n += write(*s++);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(double value, int digits) {
|
||||
// https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L218
|
||||
if (isnan(value)) return print("nan");
|
||||
if (isinf(value)) return print("inf");
|
||||
|
||||
char tmp[32];
|
||||
|
||||
// https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L220
|
||||
bool isBigDouble = value > 4294967040.0 || value < -4294967040.0;
|
||||
|
||||
if (isBigDouble) {
|
||||
// Arduino's implementation prints "ovf"
|
||||
// We prefer trying to use scientific notation, since we have sprintf
|
||||
sprintf(tmp, "%g", value);
|
||||
} else {
|
||||
// Here we have the exact same output as Arduino's implementation
|
||||
sprintf(tmp, "%.*f", digits, value);
|
||||
}
|
||||
|
||||
return print(tmp);
|
||||
}
|
||||
|
||||
size_t Print::print(long value) {
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%ld", value);
|
||||
return print(tmp);
|
||||
}
|
||||
|
||||
size_t Print::println() { return write('\r') + write('\n'); }
|
||||
|
||||
#endif
|
17
src/ArduinoJson.h
Normal file
17
src/ArduinoJson.h
Normal file
@ -0,0 +1,17 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "ArduinoJson.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
|
||||
#else
|
||||
|
||||
#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp
|
||||
|
||||
#endif
|
21
src/ArduinoJson.hpp
Normal file
21
src/ArduinoJson.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/version.hpp"
|
||||
|
||||
#include "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonBufferImpl.hpp"
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
|
||||
|
||||
#include "ArduinoJson/compatibility.hpp"
|
151
src/ArduinoJson/Configuration.hpp
Normal file
151
src/ArduinoJson/Configuration.hpp
Normal file
@ -0,0 +1,151 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
// Small or big machine?
|
||||
#ifndef ARDUINOJSON_EMBEDDED_MODE
|
||||
#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
|
||||
defined(__ARMCC_VERSION)
|
||||
#define ARDUINOJSON_EMBEDDED_MODE 1
|
||||
#else
|
||||
#define ARDUINOJSON_EMBEDDED_MODE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
// Store floats by default to reduce the memory usage (issue #134)
|
||||
#ifndef ARDUINOJSON_USE_DOUBLE
|
||||
#define ARDUINOJSON_USE_DOUBLE 0
|
||||
#endif
|
||||
|
||||
// Store longs by default, because they usually match the size of a float.
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
|
||||
// Embedded systems usually don't have std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
#define ARDUINOJSON_ENABLE_STD_STRING 0
|
||||
#endif
|
||||
|
||||
// Embedded systems usually don't have std::stream
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM 0
|
||||
#endif
|
||||
|
||||
// Limit nesting as the stack is likely to be small
|
||||
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
|
||||
#endif
|
||||
|
||||
#else // ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
// On a computer we have plenty of memory so we can use doubles
|
||||
#ifndef ARDUINOJSON_USE_DOUBLE
|
||||
#define ARDUINOJSON_USE_DOUBLE 1
|
||||
#endif
|
||||
|
||||
// Use long long when available
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#define ARDUINOJSON_USE_LONG_LONG 1
|
||||
#else
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Use _int64 on old versions of Visual Studio
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
#define ARDUINOJSON_USE_INT64 1
|
||||
#else
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// On a computer, we can use std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
#define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||
#endif
|
||||
|
||||
// On a computer, we can assume std::stream
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM 1
|
||||
#endif
|
||||
|
||||
// On a computer, the stack is large so we can increase nesting limit
|
||||
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
|
||||
#endif
|
||||
|
||||
#endif // ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
// Enable support for Arduino String
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||
#endif
|
||||
|
||||
// Enable support for Arduino Stream
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
|
||||
#endif
|
||||
|
||||
#else // ARDUINO
|
||||
|
||||
// Disable support for Arduino String
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||
#endif
|
||||
|
||||
// Disable support for Arduino Stream
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
|
||||
#endif
|
||||
|
||||
#endif // ARDUINO
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||
#ifdef PROGMEM
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 1
|
||||
#else
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
// alignment isn't needed for 8-bit AVR
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
|
||||
#else
|
||||
// but most processors need pointers to be align on word size
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Enable deprecated functions by default
|
||||
#ifndef ARDUINOJSON_ENABLE_DEPRECATED
|
||||
#define ARDUINOJSON_ENABLE_DEPRECATED 1
|
||||
#endif
|
||||
|
||||
// Control the exponentiation threshold for big numbers
|
||||
// CAUTION: cannot be more that 1e9 !!!!
|
||||
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
|
||||
#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
|
||||
#endif
|
||||
|
||||
// Control the exponentiation threshold for small numbers
|
||||
#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
|
||||
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
|
||||
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
|
||||
#endif
|
37
src/ArduinoJson/Data/Encoding.hpp
Normal file
37
src/ArduinoJson/Data/Encoding.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class Encoding {
|
||||
public:
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char escapeChar(char c) {
|
||||
const char *p = escapeTable(false);
|
||||
while (p[0] && p[1] != c) {
|
||||
p += 2;
|
||||
}
|
||||
return p[0];
|
||||
}
|
||||
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char unescapeChar(char c) {
|
||||
const char *p = escapeTable(true);
|
||||
for (;;) {
|
||||
if (p[0] == '\0') return c;
|
||||
if (p[0] == c) return p[1];
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static const char *escapeTable(bool excludeIdenticals) {
|
||||
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,8 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -14,10 +12,11 @@ namespace Internals {
|
||||
class JsonBufferAllocated {
|
||||
public:
|
||||
void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() {
|
||||
if (!jsonBuffer) return NULL;
|
||||
return jsonBuffer->alloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *, JsonBuffer *) throw() {}
|
||||
void operator delete(void *, JsonBuffer *)throw();
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
18
src/ArduinoJson/Data/JsonFloat.hpp
Normal file
18
src/ArduinoJson/Data/JsonFloat.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
typedef double JsonFloat;
|
||||
#else
|
||||
typedef float JsonFloat;
|
||||
#endif
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
23
src/ArduinoJson/Data/JsonInteger.hpp
Normal file
23
src/ArduinoJson/Data/JsonInteger.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
typedef long long JsonInteger;
|
||||
typedef unsigned long long JsonUInt;
|
||||
#elif ARDUINOJSON_USE_INT64
|
||||
typedef __int64 JsonInteger;
|
||||
typedef unsigned _int64 JsonUInt;
|
||||
#else
|
||||
typedef long JsonInteger;
|
||||
typedef unsigned long JsonUInt;
|
||||
#endif
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
42
src/ArduinoJson/Data/JsonVariantAs.hpp
Normal file
42
src/ArduinoJson/Data/JsonVariantAs.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// JsonVariant::as<T>()
|
||||
template <typename T>
|
||||
struct JsonVariantAs {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<char*> {
|
||||
typedef const char* type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<JsonArray> {
|
||||
typedef JsonArray& type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<const JsonArray> {
|
||||
typedef const JsonArray& type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<JsonObject> {
|
||||
typedef JsonObject& type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<const JsonObject> {
|
||||
typedef const JsonObject& type;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,11 +1,12 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
@ -13,16 +14,14 @@ class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// A union that defines the actual content of a JsonVariant.
|
||||
// The enum JsonVariantType determines which member is in use.
|
||||
union JsonVariantContent {
|
||||
bool asBoolean;
|
||||
double asDouble; // asDouble is also used for float
|
||||
long asLong; // asLong is also used for char, short and int
|
||||
JsonFloat asFloat; // used for double and float
|
||||
JsonUInt asInteger; // used for bool, char, short, int and longs
|
||||
const char* asString; // asString can be null
|
||||
JsonArray* asArray; // asArray cannot be null
|
||||
JsonObject* asObject; // asObject cannot be null
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
23
src/ArduinoJson/Data/JsonVariantDefault.hpp
Normal file
23
src/ArduinoJson/Data/JsonVariantDefault.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault {
|
||||
static T get() {
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
27
src/ArduinoJson/Data/JsonVariantType.hpp
Normal file
27
src/ArduinoJson/Data/JsonVariantType.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_UNDEFINED, // JsonVariant has not been initialized
|
||||
JSON_UNPARSED, // JsonVariant contains an unparsed string
|
||||
JSON_STRING, // JsonVariant stores a const char*
|
||||
JSON_BOOLEAN, // JsonVariant stores a bool
|
||||
JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt
|
||||
JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated
|
||||
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray
|
||||
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
|
||||
JSON_FLOAT // JsonVariant stores a JsonFloat
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,8 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -35,38 +33,62 @@ class List {
|
||||
// Would return false in the following situation:
|
||||
// - the memory allocation failed (StaticJsonBuffer was too small)
|
||||
// - the JSON parsing failed
|
||||
bool success() const { return _buffer != NULL; }
|
||||
bool success() const {
|
||||
return _buffer != NULL;
|
||||
}
|
||||
|
||||
// Returns the numbers of elements in the list.
|
||||
// For a JsonObject, it would return the number of key-value pairs
|
||||
int size() const;
|
||||
|
||||
iterator begin() { return iterator(_firstNode); }
|
||||
iterator end() { return iterator(NULL); }
|
||||
|
||||
const_iterator begin() const { return const_iterator(_firstNode); }
|
||||
const_iterator end() const { return const_iterator(NULL); }
|
||||
|
||||
protected:
|
||||
node_type *createNode() {
|
||||
if (!_buffer) return NULL;
|
||||
return new (_buffer) node_type();
|
||||
size_t size() const {
|
||||
size_t nodeCount = 0;
|
||||
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
void addNode(node_type *nodeToAdd) {
|
||||
iterator add() {
|
||||
node_type *newNode = new (_buffer) node_type();
|
||||
|
||||
if (_firstNode) {
|
||||
node_type *lastNode = _firstNode;
|
||||
while (lastNode->next) lastNode = lastNode->next;
|
||||
lastNode->next = nodeToAdd;
|
||||
lastNode->next = newNode;
|
||||
} else {
|
||||
_firstNode = nodeToAdd;
|
||||
_firstNode = newNode;
|
||||
}
|
||||
|
||||
return iterator(newNode);
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return iterator(_firstNode);
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(NULL);
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return const_iterator(_firstNode);
|
||||
}
|
||||
const_iterator end() const {
|
||||
return const_iterator(NULL);
|
||||
}
|
||||
|
||||
void remove(iterator it) {
|
||||
node_type *nodeToRemove = it._node;
|
||||
if (!nodeToRemove) return;
|
||||
if (nodeToRemove == _firstNode) {
|
||||
_firstNode = nodeToRemove->next;
|
||||
} else {
|
||||
for (node_type *node = _firstNode; node; node = node->next)
|
||||
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
|
||||
}
|
||||
}
|
||||
|
||||
void removeNode(node_type *nodeToRemove);
|
||||
|
||||
protected:
|
||||
JsonBuffer *_buffer;
|
||||
|
||||
private:
|
||||
node_type *_firstNode;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,8 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -17,8 +15,12 @@ class ListConstIterator {
|
||||
public:
|
||||
explicit ListConstIterator(const ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
const T &operator*() const { return _node->content; }
|
||||
const T *operator->() { return &_node->content; }
|
||||
const T &operator*() const {
|
||||
return _node->content;
|
||||
}
|
||||
const T *operator->() {
|
||||
return &_node->content;
|
||||
}
|
||||
|
||||
bool operator==(const ListConstIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
@ -33,8 +35,16 @@ class ListConstIterator {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,25 +1,32 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ListNode.hpp"
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListNode.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename T>
|
||||
class List;
|
||||
|
||||
// A read-write forward iterator for List<T>
|
||||
template <typename T>
|
||||
class ListIterator {
|
||||
friend class List<T>;
|
||||
|
||||
public:
|
||||
explicit ListIterator(ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
T &operator*() const { return _node->content; }
|
||||
T *operator->() { return &_node->content; }
|
||||
T &operator*() const {
|
||||
return _node->content;
|
||||
}
|
||||
T *operator->() {
|
||||
return &_node->content;
|
||||
}
|
||||
|
||||
bool operator==(const ListIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
@ -34,10 +41,20 @@ class ListIterator {
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator ListConstIterator<T>() const { return ListConstIterator<T>(_node); }
|
||||
ListIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator ListConstIterator<T>() const {
|
||||
return ListConstIterator<T>(_node);
|
||||
}
|
||||
|
||||
private:
|
||||
ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,8 +1,6 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -17,10 +15,10 @@ namespace Internals {
|
||||
// Used by List<T> and its iterators.
|
||||
template <typename T>
|
||||
struct ListNode : public Internals::JsonBufferAllocated {
|
||||
ListNode() : next(NULL) {}
|
||||
ListNode() throw() : next(NULL) {}
|
||||
|
||||
ListNode<T> *next;
|
||||
T content;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
23
src/ArduinoJson/Data/NonCopyable.hpp
Normal file
23
src/ArduinoJson/Data/NonCopyable.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A type that cannot be copied
|
||||
class NonCopyable {
|
||||
protected:
|
||||
NonCopyable() {}
|
||||
|
||||
private:
|
||||
// copy constructor is private
|
||||
NonCopyable(const NonCopyable&);
|
||||
|
||||
// copy operator is private
|
||||
NonCopyable& operator=(const NonCopyable&);
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
24
src/ArduinoJson/Data/ReferenceType.hpp
Normal file
24
src/ArduinoJson/Data/ReferenceType.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A type that is meant to be used by reference only (JsonArray and JsonObject)
|
||||
class ReferenceType {
|
||||
public:
|
||||
bool operator==(const ReferenceType& other) const {
|
||||
// two JsonArray are equal if they are the same instance
|
||||
// (we don't compare the content)
|
||||
return this == &other;
|
||||
}
|
||||
|
||||
bool operator!=(const ReferenceType& other) const {
|
||||
return this != &other;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
52
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
52
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename Source, typename Enable = void>
|
||||
struct ValueSaver {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& destination, Source source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
struct ValueSaver<
|
||||
Source, typename EnableIf<StringTraits<Source>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer* buffer, Destination& dest, Source source) {
|
||||
if (!StringTraits<Source>::is_null(source)) {
|
||||
typename StringTraits<Source>::duplicate_t dup =
|
||||
StringTraits<Source>::duplicate(source, buffer);
|
||||
if (!dup) return false;
|
||||
dest = dup;
|
||||
} else {
|
||||
dest = reinterpret_cast<const char*>(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// const char*, const signed char*, const unsigned char*
|
||||
template <typename Char>
|
||||
struct ValueSaver<
|
||||
Char*, typename EnableIf<!StringTraits<Char*>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& dest, Char* source) {
|
||||
dest = reinterpret_cast<const char*>(source);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
61
src/ArduinoJson/Deserialization/Comments.hpp
Normal file
61
src/ArduinoJson/Deserialization/Comments.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TInput>
|
||||
void skipSpacesAndComments(TInput& input) {
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
input.move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
switch (input.next()) {
|
||||
// C-style block comment
|
||||
case '*':
|
||||
input.move(); // skip '/'
|
||||
// no need to skip '*'
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '*' && input.next() == '/') {
|
||||
input.move(); // skip '*'
|
||||
input.move(); // skip '/'
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// C++-style line comment
|
||||
case '/':
|
||||
// not need to skip "//"
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '\n') break;
|
||||
}
|
||||
break;
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
102
src/ArduinoJson/Deserialization/JsonParser.hpp
Normal file
102
src/ArduinoJson/Deserialization/JsonParser.hpp
Normal file
@ -0,0 +1,102 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../TypeTraits/IsConst.hpp"
|
||||
#include "StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Parse JSON string to create JsonArrays and JsonObjects
|
||||
// This internal class is not indended to be used directly.
|
||||
// Instead, use JsonBuffer.parseArray() or .parseObject()
|
||||
template <typename TReader, typename TWriter>
|
||||
class JsonParser {
|
||||
public:
|
||||
JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
_reader(reader),
|
||||
_writer(writer),
|
||||
_nestingLimit(nestingLimit) {}
|
||||
|
||||
JsonArray &parseArray();
|
||||
JsonObject &parseObject();
|
||||
|
||||
JsonVariant parseVariant() {
|
||||
JsonVariant result;
|
||||
parseAnythingTo(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonParser &operator=(const JsonParser &); // non-copiable
|
||||
|
||||
static bool eat(TReader &, char charToSkip);
|
||||
FORCE_INLINE bool eat(char charToSkip) {
|
||||
return eat(_reader, charToSkip);
|
||||
}
|
||||
|
||||
const char *parseString();
|
||||
bool parseAnythingTo(JsonVariant *destination);
|
||||
|
||||
inline bool parseArrayTo(JsonVariant *destination);
|
||||
inline bool parseObjectTo(JsonVariant *destination);
|
||||
inline bool parseStringTo(JsonVariant *destination);
|
||||
|
||||
static inline bool isBetween(char c, char min, char max) {
|
||||
return min <= c && c <= max;
|
||||
}
|
||||
|
||||
static inline bool canBeInNonQuotedString(char c) {
|
||||
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
|
||||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) {
|
||||
return c == '\'' || c == '\"';
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
TReader _reader;
|
||||
TWriter _writer;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString, typename Enable = void>
|
||||
struct JsonParserBuilder {
|
||||
typedef typename StringTraits<TString>::Reader InputReader;
|
||||
typedef JsonParser<InputReader, TJsonBuffer &> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TString &json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct JsonParserBuilder<TJsonBuffer, TChar *,
|
||||
typename EnableIf<!IsConst<TChar>::value>::type> {
|
||||
typedef typename StringTraits<TChar *>::Reader TReader;
|
||||
typedef StringWriter<TChar> TWriter;
|
||||
typedef JsonParser<TReader, TWriter> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString>
|
||||
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
|
||||
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
|
||||
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
|
||||
nestingLimit);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
189
src/ArduinoJson/Deserialization/JsonParserImpl.hpp
Normal file
189
src/ArduinoJson/Deserialization/JsonParserImpl.hpp
Normal file
@ -0,0 +1,189 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Comments.hpp"
|
||||
#include "JsonParser.hpp"
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
|
||||
TReader &reader, char charToSkip) {
|
||||
skipSpacesAndComments(reader);
|
||||
if (reader.current() != charToSkip) return false;
|
||||
reader.move();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingTo(
|
||||
JsonVariant *destination) {
|
||||
skipSpacesAndComments(_reader);
|
||||
|
||||
switch (_reader.current()) {
|
||||
case '[':
|
||||
return parseArrayTo(destination);
|
||||
|
||||
case '{':
|
||||
return parseObjectTo(destination);
|
||||
|
||||
default:
|
||||
return parseStringTo(destination);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline ArduinoJson::JsonArray &
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray() {
|
||||
if (_nestingLimit == 0) return JsonArray::invalid();
|
||||
_nestingLimit--;
|
||||
|
||||
// Create an empty array
|
||||
JsonArray &array = _buffer->createArray();
|
||||
|
||||
// Check opening braket
|
||||
if (!eat('[')) goto ERROR_MISSING_BRACKET;
|
||||
if (eat(']')) goto SUCCESS_EMPTY_ARRAY;
|
||||
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// 1 - Parse value
|
||||
JsonVariant value;
|
||||
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
|
||||
if (!array.add(value)) goto ERROR_NO_MEMORY;
|
||||
|
||||
// 2 - More values?
|
||||
if (eat(']')) goto SUCCES_NON_EMPTY_ARRAY;
|
||||
if (!eat(',')) goto ERROR_MISSING_COMMA;
|
||||
}
|
||||
|
||||
SUCCESS_EMPTY_ARRAY:
|
||||
SUCCES_NON_EMPTY_ARRAY:
|
||||
_nestingLimit++;
|
||||
return array;
|
||||
|
||||
ERROR_INVALID_VALUE:
|
||||
ERROR_MISSING_BRACKET:
|
||||
ERROR_MISSING_COMMA:
|
||||
ERROR_NO_MEMORY:
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArrayTo(
|
||||
JsonVariant *destination) {
|
||||
JsonArray &array = parseArray();
|
||||
if (!array.success()) return false;
|
||||
|
||||
*destination = array;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline ArduinoJson::JsonObject &
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject() {
|
||||
if (_nestingLimit == 0) return JsonObject::invalid();
|
||||
_nestingLimit--;
|
||||
|
||||
// Create an empty object
|
||||
JsonObject &object = _buffer->createObject();
|
||||
|
||||
// Check opening brace
|
||||
if (!eat('{')) goto ERROR_MISSING_BRACE;
|
||||
if (eat('}')) goto SUCCESS_EMPTY_OBJECT;
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// 1 - Parse key
|
||||
const char *key = parseString();
|
||||
if (!key) goto ERROR_INVALID_KEY;
|
||||
if (!eat(':')) goto ERROR_MISSING_COLON;
|
||||
|
||||
// 2 - Parse value
|
||||
JsonVariant value;
|
||||
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
|
||||
if (!object.set(key, value)) goto ERROR_NO_MEMORY;
|
||||
|
||||
// 3 - More keys/values?
|
||||
if (eat('}')) goto SUCCESS_NON_EMPTY_OBJECT;
|
||||
if (!eat(',')) goto ERROR_MISSING_COMMA;
|
||||
}
|
||||
|
||||
SUCCESS_EMPTY_OBJECT:
|
||||
SUCCESS_NON_EMPTY_OBJECT:
|
||||
_nestingLimit++;
|
||||
return object;
|
||||
|
||||
ERROR_INVALID_KEY:
|
||||
ERROR_INVALID_VALUE:
|
||||
ERROR_MISSING_BRACE:
|
||||
ERROR_MISSING_COLON:
|
||||
ERROR_MISSING_COMMA:
|
||||
ERROR_NO_MEMORY:
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObjectTo(
|
||||
JsonVariant *destination) {
|
||||
JsonObject &object = parseObject();
|
||||
if (!object.success()) return false;
|
||||
|
||||
*destination = object;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline const char *
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
|
||||
typename RemoveReference<TWriter>::type::String str = _writer.startString();
|
||||
|
||||
skipSpacesAndComments(_reader);
|
||||
char c = _reader.current();
|
||||
|
||||
if (isQuote(c)) { // quotes
|
||||
_reader.move();
|
||||
char stopChar = c;
|
||||
for (;;) {
|
||||
c = _reader.current();
|
||||
if (c == '\0') break;
|
||||
_reader.move();
|
||||
|
||||
if (c == stopChar) break;
|
||||
|
||||
if (c == '\\') {
|
||||
// replace char
|
||||
c = Encoding::unescapeChar(_reader.current());
|
||||
if (c == '\0') break;
|
||||
_reader.move();
|
||||
}
|
||||
|
||||
str.append(c);
|
||||
}
|
||||
} else { // no quotes
|
||||
for (;;) {
|
||||
if (!canBeInNonQuotedString(c)) break;
|
||||
_reader.move();
|
||||
str.append(c);
|
||||
c = _reader.current();
|
||||
}
|
||||
}
|
||||
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseStringTo(
|
||||
JsonVariant *destination) {
|
||||
bool hasQuotes = isQuote(_reader.current());
|
||||
const char *value = parseString();
|
||||
if (value == NULL) return false;
|
||||
if (hasQuotes) {
|
||||
*destination = value;
|
||||
} else {
|
||||
*destination = RawJson(value);
|
||||
}
|
||||
return true;
|
||||
}
|
41
src/ArduinoJson/Deserialization/StringWriter.hpp
Normal file
41
src/ArduinoJson/Deserialization/StringWriter.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TChar>
|
||||
class StringWriter {
|
||||
public:
|
||||
class String {
|
||||
public:
|
||||
String(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
|
||||
|
||||
void append(char c) {
|
||||
*(*_writePtr)++ = TChar(c);
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
*(*_writePtr)++ = 0;
|
||||
return reinterpret_cast<const char*>(_startPtr);
|
||||
}
|
||||
|
||||
private:
|
||||
TChar** _writePtr;
|
||||
TChar* _startPtr;
|
||||
};
|
||||
|
||||
StringWriter(TChar* buffer) : _ptr(buffer) {}
|
||||
|
||||
String startString() {
|
||||
return String(&_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
TChar* _ptr;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
170
src/ArduinoJson/DynamicJsonBuffer.hpp
Normal file
170
src/ArduinoJson/DynamicJsonBuffer.hpp
Normal file
@ -0,0 +1,170 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonBufferBase.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#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 Internals {
|
||||
class DefaultAllocator {
|
||||
public:
|
||||
void* allocate(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
void deallocate(void* pointer) {
|
||||
free(pointer);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TAllocator>
|
||||
class DynamicJsonBufferBase
|
||||
: public JsonBufferBase<DynamicJsonBufferBase<TAllocator> > {
|
||||
struct Block;
|
||||
struct EmptyBlock {
|
||||
Block* next;
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
};
|
||||
struct Block : EmptyBlock {
|
||||
uint8_t data[1];
|
||||
};
|
||||
|
||||
public:
|
||||
enum { EmptyBlockSize = sizeof(EmptyBlock) };
|
||||
|
||||
DynamicJsonBufferBase(size_t initialSize = 256)
|
||||
: _head(NULL), _nextBlockCapacity(initialSize) {}
|
||||
|
||||
~DynamicJsonBufferBase() {
|
||||
clear();
|
||||
}
|
||||
|
||||
// Gets the number of bytes occupied in the buffer
|
||||
size_t size() const {
|
||||
size_t total = 0;
|
||||
for (const Block* b = _head; b; b = b->next) total += b->size;
|
||||
return total;
|
||||
}
|
||||
|
||||
// Allocates the specified amount of bytes in the buffer
|
||||
virtual void* alloc(size_t bytes) {
|
||||
alignNextAlloc();
|
||||
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
|
||||
}
|
||||
|
||||
// Resets the buffer.
|
||||
// USE WITH CAUTION: this invalidates all previously allocated data
|
||||
void clear() {
|
||||
Block* currentBlock = _head;
|
||||
while (currentBlock != NULL) {
|
||||
_nextBlockCapacity = currentBlock->capacity;
|
||||
Block* nextBlock = currentBlock->next;
|
||||
_allocator.deallocate(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
}
|
||||
_head = 0;
|
||||
}
|
||||
|
||||
class String {
|
||||
public:
|
||||
String(DynamicJsonBufferBase* parent)
|
||||
: _parent(parent), _start(NULL), _length(0) {}
|
||||
|
||||
void append(char c) {
|
||||
if (_parent->canAllocInHead(1)) {
|
||||
char* end = static_cast<char*>(_parent->allocInHead(1));
|
||||
*end = c;
|
||||
if (_length == 0) _start = end;
|
||||
} else {
|
||||
char* newStart =
|
||||
static_cast<char*>(_parent->allocInNewBlock(_length + 1));
|
||||
if (_start && newStart) memcpy(newStart, _start, _length);
|
||||
if (newStart) newStart[_length] = c;
|
||||
_start = newStart;
|
||||
}
|
||||
_length++;
|
||||
}
|
||||
|
||||
const char* c_str() {
|
||||
append(0);
|
||||
return _start;
|
||||
}
|
||||
|
||||
private:
|
||||
DynamicJsonBufferBase* _parent;
|
||||
char* _start;
|
||||
size_t _length;
|
||||
};
|
||||
|
||||
String startString() {
|
||||
return String(this);
|
||||
}
|
||||
|
||||
private:
|
||||
void alignNextAlloc() {
|
||||
if (_head) _head->size = this->round_size_up(_head->size);
|
||||
}
|
||||
|
||||
bool canAllocInHead(size_t bytes) const {
|
||||
return _head != NULL && _head->size + bytes <= _head->capacity;
|
||||
}
|
||||
|
||||
void* allocInHead(size_t bytes) {
|
||||
void* p = _head->data + _head->size;
|
||||
_head->size += bytes;
|
||||
return p;
|
||||
}
|
||||
|
||||
void* allocInNewBlock(size_t bytes) {
|
||||
size_t capacity = _nextBlockCapacity;
|
||||
if (bytes > capacity) capacity = bytes;
|
||||
if (!addNewBlock(capacity)) return NULL;
|
||||
_nextBlockCapacity *= 2;
|
||||
return allocInHead(bytes);
|
||||
}
|
||||
|
||||
bool addNewBlock(size_t capacity) {
|
||||
size_t bytes = EmptyBlockSize + capacity;
|
||||
Block* block = static_cast<Block*>(_allocator.allocate(bytes));
|
||||
if (block == NULL) return false;
|
||||
block->capacity = capacity;
|
||||
block->size = 0;
|
||||
block->next = _head;
|
||||
_head = block;
|
||||
return true;
|
||||
}
|
||||
|
||||
TAllocator _allocator;
|
||||
Block* _head;
|
||||
size_t _nextBlockCapacity;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Implements a JsonBuffer with dynamic memory allocation.
|
||||
// You are strongly encouraged to consider using StaticJsonBuffer which is much
|
||||
// more suitable for embedded systems.
|
||||
typedef Internals::DynamicJsonBufferBase<Internals::DefaultAllocator>
|
||||
DynamicJsonBuffer;
|
||||
} // namespace ArduinoJson
|
227
src/ArduinoJson/JsonArray.hpp
Normal file
227
src/ArduinoJson/JsonArray.hpp
Normal file
@ -0,0 +1,227 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonBufferAllocated.hpp"
|
||||
#include "Data/List.hpp"
|
||||
#include "Data/ReferenceType.hpp"
|
||||
#include "Data/ValueSaver.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsArray.hpp"
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(JsonArray) + (NUMBER_OF_ELEMENTS) * sizeof(JsonArray::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonObject;
|
||||
class JsonBuffer;
|
||||
namespace Internals {
|
||||
class JsonArraySubscript;
|
||||
}
|
||||
|
||||
// An array of JsonVariant.
|
||||
//
|
||||
// The constructor is private, instances must be created via
|
||||
// JsonBuffer::createArray() or JsonBuffer::parseArray().
|
||||
// A JsonArray can be serialized to a JSON string via JsonArray::printTo().
|
||||
// It can also be deserialized from a JSON string via JsonBuffer::parseArray().
|
||||
class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
public Internals::ReferenceType,
|
||||
public Internals::NonCopyable,
|
||||
public Internals::List<JsonVariant>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
public:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not call this constructor directly.
|
||||
// Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray().
|
||||
explicit JsonArray(JsonBuffer *buffer) throw()
|
||||
: Internals::List<JsonVariant>(buffer) {}
|
||||
|
||||
// Gets the value at the specified index
|
||||
const Internals::JsonArraySubscript operator[](size_t index) const;
|
||||
|
||||
// Gets or sets the value at specified index
|
||||
Internals::JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
bool add(const T &value) {
|
||||
return add_impl<const T &>(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool add(T *value) {
|
||||
return add_impl<T *>(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue value, uint8_t decimals);
|
||||
// TValue = float, double
|
||||
template <typename T>
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
bool add(T value, uint8_t) {
|
||||
return add_impl<const JsonVariant &>(JsonVariant(value));
|
||||
}
|
||||
|
||||
// Sets the value at specified index.
|
||||
//
|
||||
// bool add(size_t index, const TValue&);
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
bool set(size_t index, const T &value) {
|
||||
return set_impl<const T &>(index, value);
|
||||
}
|
||||
//
|
||||
// bool add(size_t index, TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool set(size_t index, T *value) {
|
||||
return set_impl<T *>(index, value);
|
||||
}
|
||||
//
|
||||
// bool set(size_t index, TValue value, uint8_t decimals);
|
||||
// TValue = float, double
|
||||
template <typename T>
|
||||
typename Internals::EnableIf<Internals::IsFloatingPoint<T>::value, bool>::type
|
||||
set(size_t index, T value, uint8_t decimals) {
|
||||
return set_impl<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
// Gets the value at the specified index.
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
|
||||
const_iterator it = begin() += index;
|
||||
return it != end() ? it->as<T>() : Internals::JsonVariantDefault<T>::get();
|
||||
}
|
||||
|
||||
// Check the type of the value at specified index.
|
||||
template <typename T>
|
||||
bool is(size_t index) const {
|
||||
const_iterator it = begin() += index;
|
||||
return it != end() ? it->is<T>() : false;
|
||||
}
|
||||
|
||||
// Creates a JsonArray and adds a reference at the end of the array.
|
||||
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
|
||||
JsonArray &createNestedArray();
|
||||
|
||||
// Creates a JsonObject and adds a reference at the end of the array.
|
||||
// It's a shortcut for JsonBuffer::createObject() and JsonArray::add()
|
||||
JsonObject &createNestedObject();
|
||||
|
||||
// Removes element at specified index.
|
||||
void remove(size_t index) {
|
||||
remove(begin() += index);
|
||||
}
|
||||
using Internals::List<JsonVariant>::remove;
|
||||
|
||||
// Returns a reference an invalid JsonArray.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
// This is used when memory allocation or JSON parsing fail.
|
||||
static JsonArray &invalid() {
|
||||
static JsonArray instance(NULL);
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T, size_t N>
|
||||
bool copyFrom(T (&array)[N]) {
|
||||
return copyFrom(array, N);
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T>
|
||||
bool copyFrom(T *array, size_t len) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ok &= add(array[i]);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Imports a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
bool copyFrom(T (&array)[N1][N2]) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < N1; i++) {
|
||||
JsonArray &nestedArray = createNestedArray();
|
||||
for (size_t j = 0; j < N2; j++) {
|
||||
ok &= nestedArray.add(array[i][j]);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T, size_t N>
|
||||
size_t copyTo(T (&array)[N]) const {
|
||||
return copyTo(array, N);
|
||||
}
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T>
|
||||
size_t copyTo(T *array, size_t len) const {
|
||||
size_t i = 0;
|
||||
for (const_iterator it = begin(); it != end() && i < len; ++it)
|
||||
array[i++] = *it;
|
||||
return i;
|
||||
}
|
||||
|
||||
// Exports a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
void copyTo(T (&array)[N1][N2]) const {
|
||||
size_t i = 0;
|
||||
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
|
||||
it->as<JsonArray>().copyTo(array[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_DEPRECATED
|
||||
DEPRECATED("use remove() instead")
|
||||
FORCE_INLINE void removeAt(size_t index) {
|
||||
return remove(index);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
template <typename TValueRef>
|
||||
bool set_impl(size_t index, TValueRef value) {
|
||||
iterator it = begin() += index;
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
|
||||
}
|
||||
|
||||
template <typename TValueRef>
|
||||
bool add_impl(TValueRef value) {
|
||||
iterator it = Internals::List<JsonVariant>::add();
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
|
||||
}
|
||||
};
|
||||
|
||||
namespace Internals {
|
||||
template <>
|
||||
struct JsonVariantDefault<JsonArray> {
|
||||
static JsonArray &get() {
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
26
src/ArduinoJson/JsonArrayImpl.hpp
Normal file
26
src/ArduinoJson/JsonArrayImpl.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonArraySubscript.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonArray &JsonArray::createNestedArray() {
|
||||
if (!_buffer) return JsonArray::invalid();
|
||||
JsonArray &array = _buffer->createArray();
|
||||
add(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
inline JsonObject &JsonArray::createNestedObject() {
|
||||
if (!_buffer) return JsonObject::invalid();
|
||||
JsonObject &object = _buffer->createObject();
|
||||
add(object);
|
||||
return object;
|
||||
}
|
||||
} // namespace ArduinoJson
|
122
src/ArduinoJson/JsonArraySubscript.hpp
Normal file
122
src/ArduinoJson/JsonArraySubscript.hpp
Normal file
@ -0,0 +1,122 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
public:
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// operator=(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue)
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(T* src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool success() const {
|
||||
return _index < _array.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename JsonVariantAs<T>::type as() const {
|
||||
return _array.get<T>(_index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is() const {
|
||||
return _array.is<T>(_index);
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// bool set(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue& value) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue)
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue* value) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue, uint8_t decimals);
|
||||
// TValue = float, double
|
||||
template <typename TValue>
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
FORCE_INLINE bool set(const TValue& value, uint8_t) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonArray& _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
inline const JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) const {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
const JsonArraySubscript& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
} // namespace Internals
|
||||
|
||||
inline Internals::JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||
return Internals::JsonArraySubscript(*this, index);
|
||||
}
|
||||
|
||||
inline const Internals::JsonArraySubscript JsonArray::operator[](
|
||||
size_t index) const {
|
||||
return Internals::JsonArraySubscript(*const_cast<JsonArray*>(this), index);
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
78
src/ArduinoJson/JsonBuffer.hpp
Normal file
78
src/ArduinoJson/JsonBuffer.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <string.h>
|
||||
|
||||
#include "Data/NonCopyable.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsArray.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
// Entry point for using the library.
|
||||
//
|
||||
// Handle the memory management (done in derived classes) and calls the parser.
|
||||
// This abstract class is implemented by StaticJsonBuffer which implements a
|
||||
// fixed memory allocation.
|
||||
class JsonBuffer : Internals::NonCopyable {
|
||||
public:
|
||||
// Allocates an empty JsonArray.
|
||||
//
|
||||
// Returns a reference to the new JsonArray or JsonArray::invalid() if the
|
||||
// allocation fails.
|
||||
JsonArray &createArray();
|
||||
|
||||
// Allocates an empty JsonObject.
|
||||
//
|
||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||
// allocation fails.
|
||||
JsonObject &createObject();
|
||||
|
||||
// Duplicates a string
|
||||
//
|
||||
// const char* strdup(TValue);
|
||||
// TValue = const std::string&, const String&,
|
||||
template <typename TString>
|
||||
DEPRECATED("char* are duplicated, you don't need strdup() anymore")
|
||||
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
|
||||
const char *>::type strdup(const TString &src) {
|
||||
return Internals::StringTraits<TString>::duplicate(src, this);
|
||||
}
|
||||
//
|
||||
// const char* strdup(TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TString>
|
||||
DEPRECATED("char* are duplicated, you don't need strdup() anymore")
|
||||
const char *strdup(TString *src) {
|
||||
return Internals::StringTraits<TString *>::duplicate(src, this);
|
||||
}
|
||||
|
||||
// Allocates n bytes in the JsonBuffer.
|
||||
// Return a pointer to the allocated memory or NULL if allocation fails.
|
||||
virtual void *alloc(size_t size) = 0;
|
||||
|
||||
protected:
|
||||
// CAUTION: NO VIRTUAL DESTRUCTOR!
|
||||
// If we add a virtual constructor the Arduino compiler will add malloc()
|
||||
// and free() to the binary, adding 706 useless bytes.
|
||||
~JsonBuffer() {}
|
||||
|
||||
// Preserve aligment if necessary
|
||||
static FORCE_INLINE size_t round_size_up(size_t bytes) {
|
||||
#if ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
const size_t x = sizeof(void *) - 1;
|
||||
return (bytes + x) & ~x;
|
||||
#else
|
||||
return bytes;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
} // namespace ArduinoJson
|
127
src/ArduinoJson/JsonBufferBase.hpp
Normal file
127
src/ArduinoJson/JsonBufferBase.hpp
Normal file
@ -0,0 +1,127 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Deserialization/JsonParser.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TDerived>
|
||||
class JsonBufferBase : public JsonBuffer {
|
||||
public:
|
||||
// Allocates and populate a JsonArray from a JSON string.
|
||||
//
|
||||
// The First argument is a pointer to the JSON string, the memory must be
|
||||
// writable
|
||||
// because the parser will insert null-terminators and replace escaped chars.
|
||||
//
|
||||
// The second argument set the nesting limit
|
||||
//
|
||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||
// allocation fails.
|
||||
// With this overload, the JsonBuffer will make a copy of the string
|
||||
//
|
||||
// JsonArray& parseArray(TString);
|
||||
// TString = const std::string&, const String&
|
||||
template <typename TString>
|
||||
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
|
||||
JsonArray &>::type
|
||||
parseArray(const TString &json,
|
||||
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseArray();
|
||||
}
|
||||
//
|
||||
// JsonArray& parseArray(TString);
|
||||
// TString = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonArray &parseArray(
|
||||
TString *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseArray();
|
||||
}
|
||||
//
|
||||
// JsonArray& parseArray(TString);
|
||||
// TString = std::istream&, Stream&
|
||||
template <typename TString>
|
||||
JsonArray &parseArray(
|
||||
TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseArray();
|
||||
}
|
||||
|
||||
// Allocates and populate a JsonObject from a JSON string.
|
||||
//
|
||||
// The First argument is a pointer to the JSON string, the memory must be
|
||||
// writable
|
||||
// because the parser will insert null-terminators and replace escaped chars.
|
||||
//
|
||||
// The second argument set the nesting limit
|
||||
//
|
||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||
// allocation fails.
|
||||
//
|
||||
// JsonObject& parseObject(TString);
|
||||
// TString = const std::string&, const String&
|
||||
template <typename TString>
|
||||
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
|
||||
JsonObject &>::type
|
||||
parseObject(const TString &json,
|
||||
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseObject();
|
||||
}
|
||||
//
|
||||
// JsonObject& parseObject(TString);
|
||||
// TString = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonObject &parseObject(
|
||||
TString *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseObject();
|
||||
}
|
||||
//
|
||||
// JsonObject& parseObject(TString);
|
||||
// TString = std::istream&, Stream&
|
||||
template <typename TString>
|
||||
JsonObject &parseObject(
|
||||
TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseObject();
|
||||
}
|
||||
|
||||
// Generalized version of parseArray() and parseObject(), also works for
|
||||
// integral types.
|
||||
//
|
||||
// JsonVariant parse(TString);
|
||||
// TString = const std::string&, const String&
|
||||
template <typename TString>
|
||||
typename Internals::EnableIf<!Internals::IsArray<TString>::value,
|
||||
JsonVariant>::type
|
||||
parse(const TString &json,
|
||||
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseVariant();
|
||||
}
|
||||
//
|
||||
// JsonVariant parse(TString);
|
||||
// TString = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonVariant parse(TString *json,
|
||||
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseVariant();
|
||||
}
|
||||
//
|
||||
// JsonVariant parse(TString);
|
||||
// TString = std::istream&, Stream&
|
||||
template <typename TString>
|
||||
JsonVariant parse(TString &json,
|
||||
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseVariant();
|
||||
}
|
||||
|
||||
protected:
|
||||
~JsonBufferBase() {}
|
||||
|
||||
private:
|
||||
TDerived *that() {
|
||||
return static_cast<TDerived *>(this);
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
17
src/ArduinoJson/JsonBufferImpl.hpp
Normal file
17
src/ArduinoJson/JsonBufferImpl.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Deserialization/JsonParser.hpp"
|
||||
|
||||
inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::createArray() {
|
||||
JsonArray *ptr = new (this) JsonArray(this);
|
||||
return ptr ? *ptr : JsonArray::invalid();
|
||||
}
|
||||
|
||||
inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::createObject() {
|
||||
JsonObject *ptr = new (this) JsonObject(this);
|
||||
return ptr ? *ptr : JsonObject::invalid();
|
||||
}
|
328
src/ArduinoJson/JsonObject.hpp
Normal file
328
src/ArduinoJson/JsonObject.hpp
Normal file
@ -0,0 +1,328 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonBufferAllocated.hpp"
|
||||
#include "Data/List.hpp"
|
||||
#include "Data/ReferenceType.hpp"
|
||||
#include "Data/ValueSaver.hpp"
|
||||
#include "JsonPair.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsArray.hpp"
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonArray;
|
||||
class JsonBuffer;
|
||||
namespace Internals {
|
||||
template <typename>
|
||||
class JsonObjectSubscript;
|
||||
}
|
||||
|
||||
// A dictionary of JsonVariant indexed by string (char*)
|
||||
//
|
||||
// The constructor is private, instances must be created via
|
||||
// JsonBuffer::createObject() or JsonBuffer::parseObject().
|
||||
// A JsonObject can be serialized to a JSON string via JsonObject::printTo().
|
||||
// It can also be deserialized from a JSON string via JsonBuffer::parseObject().
|
||||
class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
public Internals::ReferenceType,
|
||||
public Internals::NonCopyable,
|
||||
public Internals::List<JsonPair>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
public:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not use this constructor directly.
|
||||
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
|
||||
explicit JsonObject(JsonBuffer* buffer) throw()
|
||||
: Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
Internals::JsonObjectSubscript<const TString&> operator[](
|
||||
const TString& key) {
|
||||
return Internals::JsonObjectSubscript<const TString&>(*this, key);
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
Internals::JsonObjectSubscript<TString*> operator[](TString* key) {
|
||||
return Internals::JsonObjectSubscript<TString*>(*this, key);
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
const Internals::JsonObjectSubscript<const TString&> operator[](
|
||||
const TString& key) const {
|
||||
return Internals::JsonObjectSubscript<const TString&>(
|
||||
*const_cast<JsonObject*>(this), key);
|
||||
}
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
const Internals::JsonObjectSubscript<TString*> operator[](
|
||||
TString* key) const {
|
||||
return Internals::JsonObjectSubscript<TString*>(
|
||||
*const_cast<JsonObject*>(this), key);
|
||||
}
|
||||
|
||||
// Sets the specified key with the specified value.
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool set(const TString& key, const TValue& value) {
|
||||
return set_impl<const TString&, const TValue&>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue, typename TString>
|
||||
bool set(const TString& key, TValue* value) {
|
||||
return set_impl<const TString&, TValue*>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, const TValue&);
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool set(TString* key, const TValue& value) {
|
||||
return set_impl<TString*, const TValue&>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue, typename TString>
|
||||
bool set(TString* key, TValue* value) {
|
||||
return set_impl<TString*, TValue*>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue, uint8_t decimals);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = float, double
|
||||
template <typename TValue, typename TString>
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
typename Internals::EnableIf<Internals::IsFloatingPoint<TValue>::value,
|
||||
bool>::type
|
||||
set(const TString& key, TValue value, uint8_t) {
|
||||
return set_impl<const TString&, const JsonVariant&>(key,
|
||||
JsonVariant(value));
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue, uint8_t decimals);
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = float, double
|
||||
template <typename TValue, typename TString>
|
||||
DEPRECATED("Second argument is not supported anymore")
|
||||
typename Internals::EnableIf<Internals::IsFloatingPoint<TValue>::value,
|
||||
bool>::type
|
||||
set(TString* key, TValue value, uint8_t) {
|
||||
return set_impl<TString*, const JsonVariant&>(key, JsonVariant(value));
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
typename Internals::JsonVariantAs<TValue>::type get(
|
||||
const TString& key) const {
|
||||
return get_impl<const TString&, TValue>(key);
|
||||
}
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
typename Internals::JsonVariantAs<TValue>::type get(TString* key) const {
|
||||
return get_impl<TString*, TValue>(key);
|
||||
}
|
||||
|
||||
// Checks the type of the value associated with the specified key.
|
||||
//
|
||||
//
|
||||
// bool is<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool is(const TString& key) const {
|
||||
return is_impl<const TString&, TValue>(key);
|
||||
}
|
||||
//
|
||||
// bool is<TValue>(TKey) const;
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool is(TString* key) const {
|
||||
return is_impl<TString*, TValue>(key);
|
||||
}
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
//
|
||||
// JsonArray& createNestedArray(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
JsonArray& createNestedArray(const TString& key) {
|
||||
return createNestedArray_impl<const TString&>(key);
|
||||
}
|
||||
// JsonArray& createNestedArray(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonArray& createNestedArray(TString* key) {
|
||||
return createNestedArray_impl<TString*>(key);
|
||||
}
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
//
|
||||
// JsonObject& createNestedObject(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
JsonObject& createNestedObject(const TString& key) {
|
||||
return createNestedObject_impl<const TString&>(key);
|
||||
}
|
||||
//
|
||||
// JsonObject& createNestedObject(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonObject& createNestedObject(TString* key) {
|
||||
return createNestedObject_impl<TString*>(key);
|
||||
}
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
bool containsKey(const TString& key) const {
|
||||
return findKey<const TString&>(key) != end();
|
||||
}
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
bool containsKey(TString* key) const {
|
||||
return findKey<TString*>(key) != end();
|
||||
}
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
void remove(const TString& key) {
|
||||
remove(findKey<const TString&>(key));
|
||||
}
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
void remove(TString* key) {
|
||||
remove(findKey<TString*>(key));
|
||||
}
|
||||
//
|
||||
// void remove(iterator)
|
||||
using Internals::List<JsonPair>::remove;
|
||||
|
||||
// Returns a reference an invalid JsonObject.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
// This is used when memory allocation or JSON parsing fail.
|
||||
static JsonObject& invalid() {
|
||||
static JsonObject instance(NULL);
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns the list node that matches the specified key.
|
||||
template <typename TStringRef>
|
||||
iterator findKey(TStringRef key) {
|
||||
iterator it;
|
||||
for (it = begin(); it != end(); ++it) {
|
||||
if (Internals::StringTraits<TStringRef>::equals(key, it->key)) break;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
template <typename TStringRef>
|
||||
const_iterator findKey(TStringRef key) const {
|
||||
return const_cast<JsonObject*>(this)->findKey<TStringRef>(key);
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValue>
|
||||
typename Internals::JsonVariantAs<TValue>::type get_impl(
|
||||
TStringRef key) const {
|
||||
const_iterator it = findKey<TStringRef>(key);
|
||||
return it != end() ? it->value.as<TValue>()
|
||||
: Internals::JsonVariantDefault<TValue>::get();
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValueRef>
|
||||
bool set_impl(TStringRef key, TValueRef value) {
|
||||
// ignore null key
|
||||
if (Internals::StringTraits<TStringRef>::is_null(key)) return false;
|
||||
|
||||
// search a matching key
|
||||
iterator it = findKey<TStringRef>(key);
|
||||
if (it == end()) {
|
||||
// add the key
|
||||
it = Internals::List<JsonPair>::add();
|
||||
if (it == end()) return false;
|
||||
bool key_ok =
|
||||
Internals::ValueSaver<TStringRef>::save(_buffer, it->key, key);
|
||||
if (!key_ok) return false;
|
||||
}
|
||||
|
||||
// save the value
|
||||
return Internals::ValueSaver<TValueRef>::save(_buffer, it->value, value);
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValue>
|
||||
bool is_impl(TStringRef key) const {
|
||||
const_iterator it = findKey<TStringRef>(key);
|
||||
return it != end() ? it->value.is<TValue>() : false;
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
JsonArray& createNestedArray_impl(TStringRef key);
|
||||
|
||||
template <typename TStringRef>
|
||||
JsonObject& createNestedObject_impl(TStringRef key);
|
||||
};
|
||||
|
||||
namespace Internals {
|
||||
template <>
|
||||
struct JsonVariantDefault<JsonObject> {
|
||||
static JsonObject& get() {
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user