mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-06-29 03:11:00 +02:00
Compare commits
182 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
@ -1,3 +1,5 @@
|
||||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
|
||||
BasedOnStyle: Google
|
||||
BasedOnStyle: Google
|
||||
Standard: Cpp03
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
|
11
.github/ISSUE_TEMPLATE.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<!--
|
||||
Thanks for using ArduinoJson :-)
|
||||
|
||||
Before opening an issue, please make sure you've read these:
|
||||
https://bblanchon.github.io/ArduinoJson/faq/
|
||||
https://bblanchon.github.io/ArduinoJson/doc/pitfalls/
|
||||
|
||||
Next, make sure you provide all the relevant information: platform, code snippet, and error messages.
|
||||
|
||||
Please be concise!
|
||||
-->
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -4,3 +4,8 @@
|
||||
/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/
|
118
.travis.yml
118
.travis.yml
@ -1,20 +1,98 @@
|
||||
language: c++
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
before_install:
|
||||
- "/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
|
||||
- wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz
|
||||
- tar xf arduino-1.6.5-linux64.tar.xz
|
||||
- sudo mv arduino-1.6.5 /usr/local/share/arduino
|
||||
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
|
||||
- sudo ln -s $PWD /usr/local/share/arduino/libraries/ArduinoJson
|
||||
- sudo pip install cpp-coveralls
|
||||
script:
|
||||
- cmake -DCOVERAGE=true . && make && make test
|
||||
- arduino --verify --board arduino:avr:uno $PWD/examples/JsonParserExample/JsonParserExample.ino
|
||||
- arduino --verify --board arduino:avr:uno $PWD/examples/JsonGeneratorExample/JsonGeneratorExample.ino
|
||||
after_success:
|
||||
- if [ "$CC" = "gcc" ]; then coveralls --exclude third-party --gcov-options '\-lp'; fi
|
||||
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.5']
|
||||
env: SCRIPT=cmake GCC=4.5
|
||||
- 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 SANITIZE=undefined
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-6']
|
||||
env: SCRIPT=cmake GCC=6
|
||||
- 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: gcc
|
||||
env: SCRIPT=coverage
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
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=due
|
||||
- env: SCRIPT=platformio BOARD=esp01
|
||||
#- env: SCRIPT=platformio BOARD=teensy31C
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
script: scripts/travis/$SCRIPT.sh
|
||||
|
8
ArduinoJson.h
Normal file
8
ArduinoJson.h
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include "src/ArduinoJson.h"
|
300
CHANGELOG.md
300
CHANGELOG.md
@ -1,10 +1,299 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v5.10.0
|
||||
-------
|
||||
|
||||
* Removed configurable number of decimal places (issues #288, #427 and #506)
|
||||
* Changed exponentation 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**:
|
||||
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
|
||||
* 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)
|
||||
@ -29,7 +318,8 @@ v5.0.0
|
||||
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66)
|
||||
* Switched to new the library layout (requires Arduino 1.0.6 or above)
|
||||
|
||||
**BREAKING CHANGES**:
|
||||
### 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()`
|
||||
@ -120,14 +410,14 @@ v3.1
|
||||
|
||||
Old generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
JsonObject<3> root;
|
||||
root.add("sensor", "gps");
|
||||
root.add("time", 1351824120);
|
||||
root.add("data", array);
|
||||
|
||||
New generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
JsonObject<3> root;
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
root["data"] = array;
|
||||
@ -184,7 +474,7 @@ 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
|
||||
v1.0
|
||||
----
|
||||
|
||||
Initial release
|
||||
|
@ -1,19 +1,19 @@
|
||||
cmake_minimum_required(VERSION 2.8.4)
|
||||
# Copyright Benoit Blanchon 2014-2017
|
||||
# MIT License
|
||||
#
|
||||
# Arduino JSON library
|
||||
# https://bblanchon.github.io/ArduinoJson/
|
||||
# If you like this project, please add a star!
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(ArduinoJson)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -W4)
|
||||
endif()
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
add_subdirectory(third-party/catch)
|
||||
add_subdirectory(test)
|
||||
|
@ -1,7 +1,7 @@
|
||||
The MIT License (MIT)
|
||||
---------------------
|
||||
|
||||
Copyright © 2014-2015 Benoit BLANCHON
|
||||
Copyright © 2014-2017 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:
|
||||
|
||||
|
107
README.md
107
README.md
@ -1,13 +1,14 @@
|
||||
Arduino JSON library
|
||||
ArduinoJson - C++ JSON library for IoT
|
||||
====================
|
||||
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
|
||||
[](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)
|
||||
|
||||
*An elegant and efficient JSON library for embedded systems.*
|
||||
|
||||
It's designed to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
|
||||
It's designed to have the most intuitive API, the smallest footprint and is able to work without any allocation on the heap (no malloc).
|
||||
|
||||
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.
|
||||
For instance, it supports Aduino's `String` and `Stream`, but also `std::string`, `std::istream` and `std::ostream`.
|
||||
|
||||
Features
|
||||
--------
|
||||
@ -15,68 +16,102 @@ Features
|
||||
* JSON decoding (comments are supported)
|
||||
* JSON encoding (with optional indentation)
|
||||
* Elegant API, very easy to use
|
||||
* Efficient (no malloc, nor copy)
|
||||
* Fixed memory allocation (zero malloc)
|
||||
* No data duplication (zero copy)
|
||||
* Portable (written in C++98)
|
||||
* Self-contained (no external dependency)
|
||||
* Small footprint
|
||||
* Header-only library
|
||||
* MIT License
|
||||
|
||||
Works on
|
||||
--------
|
||||
|
||||
* Arduino boards: Uno, Due, Mini, Micro, Yun...
|
||||
* ESP8266, ESP32
|
||||
* Teensy
|
||||
* RedBearLab boards (BLE Nano...)
|
||||
* Intel Edison and Galileo
|
||||
* WeMos boards: D1...
|
||||
* Computers: Windows, Linux, OSX...
|
||||
* PlatformIO
|
||||
* Particle
|
||||
* Energia
|
||||
|
||||
Quick start
|
||||
-----------
|
||||
|
||||
#### Decoding / Parsing
|
||||
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
```c++
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
```
|
||||
|
||||
[See JsonParserExample.ino](examples/JsonParserExample/JsonParserExample.ino)
|
||||
|
||||
#### Encoding / Generating
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
```c++
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
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
|
||||
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]}
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
```
|
||||
|
||||
[See JsonGeneratorExample.ino](examples/JsonGeneratorExample/JsonGeneratorExample.ino)
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The documentation is available online in the [Arduino JSON wiki](https://github.com/bblanchon/ArduinoJson/wiki)
|
||||
The documentation is available online in the [ArduinoJson Website](https://bblanchon.github.io/ArduinoJson/).
|
||||
|
||||
Testimonials
|
||||
------------
|
||||
The [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) helps you get started with the library.
|
||||
|
||||
From Arduino's Forum user `jflaplante`:
|
||||
> I tried aJson json-arduino before trying your library. I always ran into memory problem after a while.
|
||||
> I have no such problem so far with your library. It is working perfectly with my web services.
|
||||
|
||||
From 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.
|
||||
Donators
|
||||
--------
|
||||
|
||||
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.
|
||||
Special thanks to the following persons and companies who made generous donations to the library author:
|
||||
|
||||
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!!
|
||||
* Robert Murphy <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Surge Communications <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Alex Scott <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'>
|
||||
* Firepick Services LLC <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* A B Doodkorte <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
* Scott Smith <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Johann Stieger <img alt='Austria' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e6-1f1f9.svg' width='18' height='18'>
|
||||
* Gustavo Donizeti Gini <img alt='Brazil' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e7-1f1f7.svg' width='18' height='18'>
|
||||
* Charles-Henri Hallard <img alt='France' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1eb-1f1f7.svg' width='18' height='18'>
|
||||
* Martijn van den Burg <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
* Nick Koumaris <img alt='Greece' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1f7.svg' width='18' height='18'>
|
||||
* Jon Williams <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Kestutis Liaugminas <img alt='Lithuania' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1f9.svg' width='18' height='18'>
|
||||
* Darlington Adibe <img alt='Nigeria' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1ec.svg' width='18' height='18'>
|
||||
* Yoeri Kroon <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
* Andrew Melvin <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'>
|
||||
* Doanh Luong <img alt ='Vietnam' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fb-1f1f3.svg' width='18' height='18'>
|
||||
* Christoph Schmidt <img alt='Germany' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e9-1f1ea.svg' width='18' height='18'>
|
||||
* OpenEVSE LLC <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Prokhoryatov Alexey <img alt='Russia' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f7-1f1fa.svg' width='18' height='18'>
|
||||
|
||||
---
|
||||
|
||||
|
18
appveyor.yml
Normal file
18
appveyor.yml
Normal file
@ -0,0 +1,18 @@
|
||||
version: 5.10.0.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
- CMAKE_GENERATOR: Visual Studio 12 2013
|
||||
- CMAKE_GENERATOR: Visual Studio 11 2012
|
||||
- CMAKE_GENERATOR: Visual Studio 10 2010
|
||||
# - CMAKE_GENERATOR: MinGW Makefiles
|
||||
# Note: Disabled because of unexplicated error -1073741511
|
||||
# This used to work fine with GCC 4.8.2 then failed after they upgraded to GCC 4.9.3
|
||||
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 .
|
@ -1,31 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#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
|
||||
}
|
@ -1,23 +1,51 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
// wait serial port initialization
|
||||
}
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// If the JSON object is more complex, you need to increase that value.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
// It's simpler but less efficient.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
// 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(double_with_n_digits(48.756080, 6));
|
||||
data.add(double_with_n_digits(2.302038, 6));
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
|
184
examples/JsonHttpClient/JsonHttpClient.ino
Normal file
184
examples/JsonHttpClient/JsonHttpClient.ino
Normal file
@ -0,0 +1,184 @@
|
||||
// Sample Arduino Json Web Client
|
||||
// Downloads and parse http://jsonplaceholder.typicode.com/users/1
|
||||
//
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <Ethernet.h>
|
||||
#include <SPI.h>
|
||||
|
||||
EthernetClient client;
|
||||
|
||||
const char* server = "jsonplaceholder.typicode.com"; // server's address
|
||||
const char* resource = "/users/1"; // http resource
|
||||
const unsigned long BAUD_RATE = 9600; // serial connection speed
|
||||
const unsigned long HTTP_TIMEOUT = 10000; // max respone time from server
|
||||
const size_t MAX_CONTENT_SIZE = 512; // max size of the HTTP response
|
||||
|
||||
// The type of data that we want to extract from the page
|
||||
struct UserData {
|
||||
char name[32];
|
||||
char company[32];
|
||||
};
|
||||
|
||||
// ARDUINO entry point #1: runs once when you press reset or power the board
|
||||
void setup() {
|
||||
initSerial();
|
||||
initEthernet();
|
||||
}
|
||||
|
||||
// ARDUINO entry point #2: runs over and over again forever
|
||||
void loop() {
|
||||
if (connect(server)) {
|
||||
if (sendRequest(server, resource) && skipResponseHeaders()) {
|
||||
UserData userData;
|
||||
if (readReponseContent(&userData)) {
|
||||
printUserData(&userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
disconnect();
|
||||
wait();
|
||||
}
|
||||
|
||||
// Initialize Serial port
|
||||
void initSerial() {
|
||||
Serial.begin(BAUD_RATE);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to initialize
|
||||
}
|
||||
Serial.println("Serial ready");
|
||||
}
|
||||
|
||||
// Initialize Ethernet library
|
||||
void initEthernet() {
|
||||
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||
if (!Ethernet.begin(mac)) {
|
||||
Serial.println("Failed to configure Ethernet");
|
||||
return;
|
||||
}
|
||||
Serial.println("Ethernet ready");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// Open connection to the HTTP server
|
||||
bool connect(const char* hostName) {
|
||||
Serial.print("Connect to ");
|
||||
Serial.println(hostName);
|
||||
|
||||
bool ok = client.connect(hostName, 80);
|
||||
|
||||
Serial.println(ok ? "Connected" : "Connection Failed!");
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Send the HTTP GET request to the server
|
||||
bool sendRequest(const char* host, const char* resource) {
|
||||
Serial.print("GET ");
|
||||
Serial.println(resource);
|
||||
|
||||
client.print("GET ");
|
||||
client.print(resource);
|
||||
client.println(" HTTP/1.0");
|
||||
client.print("Host: ");
|
||||
client.println(host);
|
||||
client.println("Connection: close");
|
||||
client.println();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip HTTP headers so that we are at the beginning of the response's body
|
||||
bool skipResponseHeaders() {
|
||||
// HTTP headers end with an empty line
|
||||
char endOfHeaders[] = "\r\n\r\n";
|
||||
|
||||
client.setTimeout(HTTP_TIMEOUT);
|
||||
bool ok = client.find(endOfHeaders);
|
||||
|
||||
if (!ok) {
|
||||
Serial.println("No response or invalid response!");
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Parse the JSON from the input string and extract the interesting values
|
||||
// Here is the JSON we need to parse
|
||||
// {
|
||||
// "id": 1,
|
||||
// "name": "Leanne Graham",
|
||||
// "username": "Bret",
|
||||
// "email": "Sincere@april.biz",
|
||||
// "address": {
|
||||
// "street": "Kulas Light",
|
||||
// "suite": "Apt. 556",
|
||||
// "city": "Gwenborough",
|
||||
// "zipcode": "92998-3874",
|
||||
// "geo": {
|
||||
// "lat": "-37.3159",
|
||||
// "lng": "81.1496"
|
||||
// }
|
||||
// },
|
||||
// "phone": "1-770-736-8031 x56442",
|
||||
// "website": "hildegard.org",
|
||||
// "company": {
|
||||
// "name": "Romaguera-Crona",
|
||||
// "catchPhrase": "Multi-layered client-server neural-net",
|
||||
// "bs": "harness real-time e-markets"
|
||||
// }
|
||||
// }
|
||||
bool readReponseContent(struct UserData* userData) {
|
||||
// Compute optimal size of the JSON buffer according to what we need to parse.
|
||||
// This is only required if you use StaticJsonBuffer.
|
||||
const size_t BUFFER_SIZE =
|
||||
JSON_OBJECT_SIZE(8) // the root object has 8 elements
|
||||
+ JSON_OBJECT_SIZE(5) // the "address" object has 5 elements
|
||||
+ JSON_OBJECT_SIZE(2) // the "geo" object has 2 elements
|
||||
+ JSON_OBJECT_SIZE(3) // the "company" object has 3 elements
|
||||
+ MAX_CONTENT_SIZE; // additional space for strings
|
||||
|
||||
// Allocate a temporary memory pool
|
||||
DynamicJsonBuffer jsonBuffer(BUFFER_SIZE);
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(client);
|
||||
|
||||
if (!root.success()) {
|
||||
Serial.println("JSON parsing failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Here were copy the strings we're interested in
|
||||
strcpy(userData->name, root["name"]);
|
||||
strcpy(userData->company, root["company"]["name"]);
|
||||
// It's not mandatory to make a copy, you could just use the pointers
|
||||
// Since, they are pointing inside the "content" buffer, so you need to make
|
||||
// sure it's still in memory when you read the string
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Print the data extracted from the JSON
|
||||
void printUserData(const struct UserData* userData) {
|
||||
Serial.print("Name = ");
|
||||
Serial.println(userData->name);
|
||||
Serial.print("Company = ");
|
||||
Serial.println(userData->company);
|
||||
}
|
||||
|
||||
// Close the connection with the HTTP server
|
||||
void disconnect() {
|
||||
Serial.println("Disconnect");
|
||||
client.stop();
|
||||
}
|
||||
|
||||
// Pause for a 1 minute
|
||||
void wait() {
|
||||
Serial.println("Wait 60 seconds");
|
||||
delay(60000);
|
||||
}
|
@ -1,31 +1,61 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
// wait serial port initialization
|
||||
}
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the pool in bytes,
|
||||
// If the JSON object is more complex, you need to increase that value.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
// It's simpler but less efficient.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
// 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);
|
||||
|
@ -3,11 +3,11 @@
|
||||
// You can easily test this program with netcat:
|
||||
// $ nc -ulp 8888
|
||||
//
|
||||
// by Benoit Blanchon, MIT License 2015
|
||||
// by Benoit Blanchon, MIT License 2015-2017
|
||||
|
||||
#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);
|
||||
|
56
examples/ProgmemExample/ProgmemExample.ino
Normal file
56
examples/ProgmemExample/ProgmemExample.ino
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
// About
|
||||
// -----
|
||||
// This example shows the different ways you can use PROGMEM with ArduinoJson.
|
||||
// Please don't see this as an invitation to use PROGMEM.
|
||||
// On the contrary, you should always use char[] when possible, it's much more
|
||||
// efficient in term of code size, speed and memory usage.
|
||||
|
||||
void setup() {
|
||||
#ifdef PROGMEM
|
||||
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");
|
||||
|
||||
// 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
|
||||
}
|
63
examples/StringExample/StringExample.ino
Normal file
63
examples/StringExample/StringExample.ino
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
// About
|
||||
// -----
|
||||
// This example shows the different ways you can use String with ArduinoJson.
|
||||
// Please don't see this as an invitation to use String.
|
||||
// On the contrary, you should always use char[] when possible, it's much more
|
||||
// efficient in term of code size, speed and memory usage.
|
||||
|
||||
void setup() {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
}
|
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" >> $@
|
9
fuzzing/fuzz.sh
Executable file
9
fuzzing/fuzz.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
# This script mimics an invocation from https://github.com/google/oss-fuzz
|
||||
|
||||
cd $(dirname $0)
|
||||
export CXX='clang++'
|
||||
export CXXFLAGS='-fsanitize-coverage=trace-pc-guard -fsanitize=address'
|
||||
export LIB_FUZZING_ENGINE=-lFuzzer
|
||||
make OUT=.
|
||||
./json_fuzzer my_corpus seed_corpus -max_len=1024 -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 "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#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
|
||||
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,26 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include <string>
|
||||
|
||||
// This class reproduces Arduino's String class
|
||||
class String : public std::string {
|
||||
public:
|
||||
String(const char *cstr = "") : std::string(cstr) {}
|
||||
String(const String &str) : std::string(str) {}
|
||||
explicit String(long);
|
||||
explicit String(double, unsigned char decimalPlaces = 2);
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <WString.h>
|
||||
|
||||
#endif
|
@ -1,17 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Internals/BlockJsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
// 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::BlockJsonBuffer<Internals::DefaultAllocator>
|
||||
DynamicJsonBuffer;
|
||||
}
|
@ -1,93 +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 {
|
||||
namespace Internals {
|
||||
class DefaultAllocator {
|
||||
public:
|
||||
void* allocate(size_t size) { return malloc(size); }
|
||||
void deallocate(void* pointer) { free(pointer); }
|
||||
};
|
||||
|
||||
template <typename TAllocator>
|
||||
class BlockJsonBuffer : public JsonBuffer {
|
||||
struct Block;
|
||||
struct EmptyBlock {
|
||||
Block* next;
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
};
|
||||
struct Block : EmptyBlock {
|
||||
uint8_t data[1];
|
||||
};
|
||||
|
||||
public:
|
||||
BlockJsonBuffer() : _head(NULL) {}
|
||||
|
||||
~BlockJsonBuffer() {
|
||||
Block* currentBlock = _head;
|
||||
|
||||
while (currentBlock != NULL) {
|
||||
Block* nextBlock = currentBlock->next;
|
||||
_allocator.deallocate(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
size_t total = 0;
|
||||
for (const Block* b = _head; b; b = b->next) total += b->size;
|
||||
return total;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void* alloc(size_t bytes) {
|
||||
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
|
||||
}
|
||||
|
||||
private:
|
||||
static const size_t FIRST_BLOCK_CAPACITY = 32;
|
||||
|
||||
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 += round_size_up(bytes);
|
||||
return p;
|
||||
}
|
||||
|
||||
void* allocInNewBlock(size_t bytes) {
|
||||
size_t capacity = FIRST_BLOCK_CAPACITY;
|
||||
if (_head != NULL) capacity = _head->capacity * 2;
|
||||
if (bytes > capacity) capacity = bytes;
|
||||
if (!addNewBlock(capacity)) return NULL;
|
||||
return allocInHead(bytes);
|
||||
}
|
||||
|
||||
bool addNewBlock(size_t capacity) {
|
||||
size_t bytes = sizeof(EmptyBlock) + 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;
|
||||
}
|
||||
|
||||
Block* _head;
|
||||
TAllocator _allocator;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
const char *skipSpacesAndComments(const char *ptr);
|
||||
}
|
||||
}
|
@ -1,20 +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 dummy Print implementation used in JsonPrintable::measureLength()
|
||||
class DummyPrint : public Print {
|
||||
public:
|
||||
virtual size_t write(uint8_t) { return 1; }
|
||||
};
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
#include "../Arduino/String.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A Print implementation that allows to write in a String
|
||||
class DynamicStringBuilder : public Print {
|
||||
public:
|
||||
DynamicStringBuilder(String &str) : _str(str) {}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
_str += c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
DynamicStringBuilder &operator=(const DynamicStringBuilder &);
|
||||
|
||||
String &_str;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FORCE_INLINE __forceinline
|
||||
#else
|
||||
#define FORCE_INLINE __attribute__((always_inline))
|
||||
#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 "../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),
|
||||
_readPtr(json ? json : ""),
|
||||
_writePtr(json),
|
||||
_nestingLimit(nestingLimit) {}
|
||||
|
||||
JsonArray &parseArray();
|
||||
JsonObject &parseObject();
|
||||
|
||||
private:
|
||||
bool skip(char charToSkip);
|
||||
|
||||
const char *parseString();
|
||||
bool parseAnythingTo(JsonVariant *destination);
|
||||
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
|
||||
|
||||
inline bool parseArrayTo(JsonVariant *destination);
|
||||
inline bool parseObjectTo(JsonVariant *destination);
|
||||
inline bool parseStringTo(JsonVariant *destination);
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
const char *_readPtr;
|
||||
char *_writePtr;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DummyPrint.hpp"
|
||||
#include "IndentedPrint.hpp"
|
||||
#include "JsonWriter.hpp"
|
||||
#include "Prettyfier.hpp"
|
||||
#include "StaticStringBuilder.hpp"
|
||||
#include "DynamicStringBuilder.hpp"
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include "StreamPrintAdapter.hpp"
|
||||
#endif
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
std::ostream &printTo(std::ostream &os) const {
|
||||
StreamPrintAdapter adapter(os);
|
||||
printTo(adapter);
|
||||
return os;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t printTo(char *buffer, size_t bufferSize) const {
|
||||
StaticStringBuilder sb(buffer, bufferSize);
|
||||
return printTo(sb);
|
||||
}
|
||||
|
||||
size_t printTo(String &str) const {
|
||||
DynamicStringBuilder sb(str);
|
||||
return printTo(sb);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(IndentedPrint &print) const {
|
||||
Prettyfier p(print);
|
||||
return printTo(p);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(char *buffer, size_t bufferSize) const {
|
||||
StaticStringBuilder sb(buffer, bufferSize);
|
||||
return prettyPrintTo(sb);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(Print &print) const {
|
||||
IndentedPrint indentedPrint = IndentedPrint(print);
|
||||
return prettyPrintTo(indentedPrint);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(String &str) const {
|
||||
DynamicStringBuilder sb(str);
|
||||
return prettyPrintTo(sb);
|
||||
}
|
||||
|
||||
size_t measureLength() const {
|
||||
DummyPrint dp;
|
||||
return printTo(dp);
|
||||
}
|
||||
|
||||
size_t measurePrettyLength() const {
|
||||
DummyPrint dp;
|
||||
return prettyPrintTo(dp);
|
||||
}
|
||||
|
||||
private:
|
||||
const T &downcast() const { return *static_cast<const T *>(this); }
|
||||
};
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
template <typename T>
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonPrintable<T> &v) {
|
||||
return v.printTo(os);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#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, // the JsonVariant has not been initialized
|
||||
JSON_UNPARSED, // the JsonVariant contains an unparsed string
|
||||
JSON_STRING, // the JsonVariant stores a const char*
|
||||
JSON_BOOLEAN, // the JsonVariant stores a bool
|
||||
JSON_LONG, // the JsonVariant stores a long
|
||||
JSON_ARRAY, // the JsonVariant stores a pointer to a JsonArray
|
||||
JSON_OBJECT, // the JsonVariant stores a pointer to a JsonObject
|
||||
|
||||
// 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,82 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
#include "Encoding.hpp"
|
||||
#include "ForceInline.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() const { return _length; }
|
||||
|
||||
void beginArray() { write('['); }
|
||||
void endArray() { write(']'); }
|
||||
|
||||
void beginObject() { write('{'); }
|
||||
void endObject() { write('}'); }
|
||||
|
||||
void writeColon() { write(':'); }
|
||||
void writeComma() { write(','); }
|
||||
|
||||
void writeBoolean(bool value) { write(value ? "true" : "false"); }
|
||||
|
||||
void writeString(const char *value) {
|
||||
if (!value) {
|
||||
write("null");
|
||||
} else {
|
||||
write('\"');
|
||||
while (*value) writeChar(*value++);
|
||||
write('\"');
|
||||
}
|
||||
}
|
||||
|
||||
void writeChar(char c) {
|
||||
char specialChar = Encoding::escapeChar(c);
|
||||
if (specialChar) {
|
||||
write('\\');
|
||||
write(specialChar);
|
||||
} else {
|
||||
write(c);
|
||||
}
|
||||
}
|
||||
|
||||
void writeLong(long value) { _length += _sink.print(value); }
|
||||
|
||||
void writeDouble(double value, uint8_t decimals) {
|
||||
_length += _sink.print(value, decimals);
|
||||
}
|
||||
|
||||
void writeRaw(const char *s) { return write(s); }
|
||||
|
||||
protected:
|
||||
void write(char c) { _length += _sink.write(c); }
|
||||
FORCE_INLINE void write(const char *s) { _length += _sink.print(s); }
|
||||
|
||||
Print &_sink;
|
||||
size_t _length;
|
||||
|
||||
private:
|
||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||
};
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListIterator.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A singly linked list of T.
|
||||
// The linked list is composed of ListNode<T>.
|
||||
// It is derived by JsonArray and JsonObject
|
||||
template <typename T>
|
||||
class List {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ListNode<T> node_type;
|
||||
typedef ListIterator<T> iterator;
|
||||
typedef ListConstIterator<T> const_iterator;
|
||||
|
||||
// Creates an empty List<T> attached to a JsonBuffer.
|
||||
// The JsonBuffer allows to allocate new nodes.
|
||||
// When buffer is NULL, the List is not able to grow and success() returns
|
||||
// false. This is used to identify bad memory allocations and parsing
|
||||
// failures.
|
||||
explicit List(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {}
|
||||
|
||||
// Returns true if the object is valid
|
||||
// Would return false in the following situation:
|
||||
// - the memory allocation failed (StaticJsonBuffer was too small)
|
||||
// - the JSON parsing failed
|
||||
bool success() const { return _buffer != NULL; }
|
||||
|
||||
// Returns the numbers of elements in the list.
|
||||
// For a JsonObject, it would return the number of key-value pairs
|
||||
size_t size() const;
|
||||
|
||||
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 *addNewNode();
|
||||
void removeNode(node_type *nodeToRemove);
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
node_type *_firstNode;
|
||||
};
|
||||
}
|
||||
}
|
@ -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 handleColon();
|
||||
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,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 StaticStringBuilder : public Print {
|
||||
public:
|
||||
StaticStringBuilder(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,34 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class StreamPrintAdapter : public Print {
|
||||
public:
|
||||
explicit StreamPrintAdapter(std::ostream& os) : _os(os) {}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
_os << static_cast<char>(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
// cannot be assigned
|
||||
StreamPrintAdapter& operator=(const StreamPrintAdapter&);
|
||||
|
||||
std::ostream& _os;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ARDUINOJSON_ENABLE_STD_STREAM
|
@ -1,20 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class Unparsed {
|
||||
public:
|
||||
explicit Unparsed(const char* str) : _str(str) {}
|
||||
operator const char*() const { return _str; }
|
||||
|
||||
private:
|
||||
const char* _str;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,133 +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;
|
||||
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::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)
|
||||
: Internals::List<JsonVariant>(buffer) {}
|
||||
|
||||
// Gets the value at the specified index
|
||||
FORCE_INLINE JsonVariant operator[](size_t index) const;
|
||||
|
||||
// Gets or sets the value at specified index
|
||||
FORCE_INLINE JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
FORCE_INLINE bool add(bool value);
|
||||
FORCE_INLINE bool add(float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool add(double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool add(signed char value);
|
||||
FORCE_INLINE bool add(signed long value);
|
||||
FORCE_INLINE bool add(signed int value);
|
||||
FORCE_INLINE bool add(signed short value);
|
||||
FORCE_INLINE bool add(unsigned char value);
|
||||
FORCE_INLINE bool add(unsigned long value);
|
||||
FORCE_INLINE bool add(unsigned int value);
|
||||
FORCE_INLINE bool add(unsigned short value);
|
||||
FORCE_INLINE bool add(const char *value);
|
||||
FORCE_INLINE bool add(const String &value);
|
||||
FORCE_INLINE bool add(JsonArray &array);
|
||||
FORCE_INLINE bool add(JsonObject &object);
|
||||
FORCE_INLINE bool add(const JsonVariant &object);
|
||||
|
||||
// Sets the value at specified index.
|
||||
FORCE_INLINE void set(size_t index, bool value);
|
||||
FORCE_INLINE void set(size_t index, float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE void set(size_t index, double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE void set(size_t index, signed char value);
|
||||
FORCE_INLINE void set(size_t index, signed long value);
|
||||
FORCE_INLINE void set(size_t index, signed int value);
|
||||
FORCE_INLINE void set(size_t index, signed short value);
|
||||
FORCE_INLINE void set(size_t index, unsigned char value);
|
||||
FORCE_INLINE void set(size_t index, unsigned long value);
|
||||
FORCE_INLINE void set(size_t index, unsigned int value);
|
||||
FORCE_INLINE void set(size_t index, unsigned short value);
|
||||
FORCE_INLINE void set(size_t index, const char *value);
|
||||
FORCE_INLINE void set(size_t index, const String &value);
|
||||
FORCE_INLINE void set(size_t index, JsonArray &array);
|
||||
FORCE_INLINE void set(size_t index, JsonObject &object);
|
||||
FORCE_INLINE void set(size_t index, const JsonVariant &object);
|
||||
|
||||
// Gets the value at the specified index.
|
||||
FORCE_INLINE JsonVariant get(size_t index) const;
|
||||
|
||||
// Gets the value at the specified index.
|
||||
template <typename T>
|
||||
FORCE_INLINE T get(size_t index) const;
|
||||
|
||||
// Check the type of the value at specified index.
|
||||
template <typename T>
|
||||
FORCE_INLINE T is(size_t index) const;
|
||||
|
||||
// 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(size_t 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:
|
||||
node_type *getNodeAt(size_t index) const;
|
||||
|
||||
template <typename TValue>
|
||||
void setNodeAt(size_t index, TValue value);
|
||||
|
||||
template <typename TValue>
|
||||
bool addNode(TValue);
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE void setNodeValue(node_type *, T value);
|
||||
|
||||
// The instance returned by JsonArray::invalid()
|
||||
static JsonArray _invalid;
|
||||
};
|
||||
}
|
||||
|
||||
#include "JsonArray.ipp"
|
@ -1,217 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonArraySubscript.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||
return JsonArraySubscript(*this, index);
|
||||
}
|
||||
|
||||
inline JsonVariant JsonArray::operator[](size_t index) const {
|
||||
return get(index);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(bool value) { return addNode<bool>(value); }
|
||||
|
||||
inline bool JsonArray::add(float value, uint8_t decimals) {
|
||||
return addNode<const JsonVariant &>(JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(double value, uint8_t decimals) {
|
||||
return addNode<const JsonVariant &>(JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed char value) {
|
||||
return addNode<signed char>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed long value) {
|
||||
return addNode<signed long>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed int value) {
|
||||
return addNode<signed int>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed short value) {
|
||||
return addNode<signed short>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned char value) {
|
||||
return addNode<unsigned char>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned long value) {
|
||||
return addNode<unsigned long>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned int value) {
|
||||
return addNode<unsigned int>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned short value) {
|
||||
return addNode<unsigned short>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(const char *value) {
|
||||
return addNode<const char *>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(const String &value) {
|
||||
return addNode<const String &>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(JsonArray &array) {
|
||||
return addNode<JsonArray &>(array);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(JsonObject &object) {
|
||||
return addNode<JsonObject &>(object);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(const JsonVariant &object) {
|
||||
return addNode<const JsonVariant &>(object);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline bool JsonArray::addNode(TValue value) {
|
||||
node_type *node = addNewNode();
|
||||
if (node == NULL) return false;
|
||||
setNodeValue<TValue>(node, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, bool value) {
|
||||
return setNodeAt<bool>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, float value, uint8_t decimals) {
|
||||
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, double value, uint8_t decimals) {
|
||||
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed char value) {
|
||||
return setNodeAt<signed char>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed long value) {
|
||||
return setNodeAt<signed long>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed int value) {
|
||||
return setNodeAt<signed int>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed short value) {
|
||||
return setNodeAt<signed short>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned char value) {
|
||||
return setNodeAt<unsigned char>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned long value) {
|
||||
return setNodeAt<unsigned long>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned int value) {
|
||||
return setNodeAt<unsigned int>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned short value) {
|
||||
return setNodeAt<unsigned short>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, const char *value) {
|
||||
return setNodeAt<const char *>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, const String &value) {
|
||||
return setNodeAt<const String &>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, JsonArray &array) {
|
||||
return setNodeAt<JsonArray &>(index, array);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, JsonObject &object) {
|
||||
return setNodeAt<JsonObject &>(index, object);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, const JsonVariant &object) {
|
||||
return setNodeAt<const JsonVariant &>(index, object);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline void JsonArray::setNodeAt(size_t index, TValue value) {
|
||||
node_type *node = getNodeAt(index);
|
||||
if (node == NULL) return;
|
||||
setNodeValue<TValue>(node, value);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline void JsonArray::setNodeValue(node_type *node, TValue value) {
|
||||
node->content = value;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonArray::setNodeValue(node_type *node, const String &value) {
|
||||
node->content = _buffer->strdup(value);
|
||||
}
|
||||
|
||||
inline JsonVariant JsonArray::get(size_t index) const {
|
||||
node_type *node = getNodeAt(index);
|
||||
return node ? node->content : JsonVariant();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonArray::get(size_t index) const {
|
||||
node_type *node = getNodeAt(index);
|
||||
return node ? node->content.as<T>() : JsonVariant::invalid<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonArray::is(size_t index) const {
|
||||
node_type *node = getNodeAt(index);
|
||||
return node ? node->content.is<T>() : false;
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
|
||||
int index) const {
|
||||
return asArray()[index];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonArray &JsonVariant::invalid<JsonArray &>() {
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonArray const &JsonVariant::invalid<JsonArray const &>() {
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonArray &JsonVariant::as<JsonArray &>() const {
|
||||
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const JsonArray &JsonVariant::as<const JsonArray &>() const {
|
||||
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonSubscriptBase.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArraySubscript : public JsonSubscriptBase<JsonArraySubscript> {
|
||||
public:
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
using JsonSubscriptBase<JsonArraySubscript>::operator=;
|
||||
|
||||
FORCE_INLINE bool success() const { return _index < _array.size(); }
|
||||
|
||||
FORCE_INLINE operator JsonVariant() const { return _array.get(_index); }
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE T as() const {
|
||||
return _array.get<T>(_index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE T is() const {
|
||||
return _array.is<T>(_index);
|
||||
}
|
||||
|
||||
void writeTo(Internals::JsonWriter& writer) const {
|
||||
_array.get(_index).writeTo(writer);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
void set(TValue value) {
|
||||
_array.set(_index, value);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonArray& _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
const JsonArraySubscript& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
@ -1,136 +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
|
||||
#include <string.h>
|
||||
|
||||
#include "Arduino/String.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
#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);
|
||||
|
||||
// Same with a const char*.
|
||||
// With this overload, the JsonBuffer will make a copy of the string
|
||||
JsonArray &parseArray(const char *json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseArray(strdup(json), nesting);
|
||||
}
|
||||
|
||||
// Same as above with a String class
|
||||
JsonArray &parseArray(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseArray(json.c_str(), nesting);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Same with a const char*.
|
||||
// With this overload, the JsonBuffer will make a copy of the string
|
||||
JsonObject &parseObject(const char *json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseObject(strdup(json), nesting);
|
||||
}
|
||||
|
||||
// Same as above with a String class
|
||||
JsonObject &parseObject(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseObject(json.c_str(), nesting);
|
||||
}
|
||||
|
||||
// Duplicate a string
|
||||
char *strdup(const char *src) {
|
||||
return src ? strdup(src, strlen(src)) : NULL;
|
||||
}
|
||||
char *strdup(const String &src) { return strdup(src.c_str(), src.length()); }
|
||||
|
||||
// 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:
|
||||
// Preserve aligment if nessary
|
||||
static FORCE_INLINE size_t round_size_up(size_t bytes) {
|
||||
#if defined ARDUINO_ARCH_AVR
|
||||
// alignment isn't needed for 8-bit AVR
|
||||
return bytes;
|
||||
#else
|
||||
const size_t x = sizeof(void *) - 1;
|
||||
return (bytes + x) & ~x;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
char *strdup(const char *, size_t);
|
||||
|
||||
// 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,146 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino/String.hpp"
|
||||
#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 {
|
||||
public:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not use this constructor directly.
|
||||
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
|
||||
FORCE_INLINE explicit JsonObject(JsonBuffer* buffer)
|
||||
: Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
FORCE_INLINE JsonObjectSubscript<const char*> operator[](const char* key);
|
||||
FORCE_INLINE JsonObjectSubscript<const String&> operator[](const String& key);
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const;
|
||||
|
||||
// Sets the specified key with the specified value.
|
||||
FORCE_INLINE bool set(const char* key, bool value);
|
||||
FORCE_INLINE bool set(const char* key, float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const char* key, double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const char* key, signed char value);
|
||||
FORCE_INLINE bool set(const char* key, signed long value);
|
||||
FORCE_INLINE bool set(const char* key, signed int value);
|
||||
FORCE_INLINE bool set(const char* key, signed short value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned char value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned long value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned int value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned short value);
|
||||
FORCE_INLINE bool set(const char* key, const char* value);
|
||||
FORCE_INLINE bool set(const char* key, const String& value);
|
||||
FORCE_INLINE bool set(const char* key, JsonArray& array);
|
||||
FORCE_INLINE bool set(const char* key, JsonObject& object);
|
||||
FORCE_INLINE bool set(const char* key, const JsonVariant& value);
|
||||
FORCE_INLINE bool set(const String& key, bool value);
|
||||
FORCE_INLINE bool set(const String& key, float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const String& key, double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const String& key, signed char value);
|
||||
FORCE_INLINE bool set(const String& key, signed long value);
|
||||
FORCE_INLINE bool set(const String& key, signed int value);
|
||||
FORCE_INLINE bool set(const String& key, signed short value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned char value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned long value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned int value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned short value);
|
||||
FORCE_INLINE bool set(const String& key, const char* value);
|
||||
FORCE_INLINE bool set(const String& key, const String& value);
|
||||
FORCE_INLINE bool set(const String& key, JsonArray& array);
|
||||
FORCE_INLINE bool set(const String& key, JsonObject& object);
|
||||
FORCE_INLINE bool set(const String& key, const JsonVariant& value);
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
FORCE_INLINE JsonVariant get(JsonObjectKey) const;
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
template <typename T>
|
||||
FORCE_INLINE T get(JsonObjectKey) const;
|
||||
|
||||
// Checks the type of the value associated with the specified key.
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is(JsonObjectKey) const;
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
||||
FORCE_INLINE JsonArray& createNestedArray(const char* key);
|
||||
FORCE_INLINE JsonArray& createNestedArray(const String& key);
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
||||
FORCE_INLINE JsonObject& createNestedObject(const char* key);
|
||||
FORCE_INLINE JsonObject& createNestedObject(const String& key);
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
FORCE_INLINE bool containsKey(JsonObjectKey key) const;
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
void remove(JsonObjectKey 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:
|
||||
// Returns the list node that matches the specified key.
|
||||
node_type* getNodeAt(JsonObjectKey key) const;
|
||||
|
||||
node_type* getOrCreateNodeAt(JsonObjectKey key);
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
FORCE_INLINE bool setNodeAt(TKey key, TValue value);
|
||||
|
||||
template <typename TKey>
|
||||
JsonArray& createArrayAt(TKey key);
|
||||
|
||||
template <typename TKey>
|
||||
JsonObject& createObjectAt(TKey key);
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE void setNodeKey(node_type*, T key);
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE void setNodeValue(node_type*, T value);
|
||||
|
||||
// The instance returned by JsonObject::invalid()
|
||||
static JsonObject _invalid;
|
||||
};
|
||||
}
|
||||
|
||||
#include "JsonObject.ipp"
|
@ -1,232 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonObject.hpp"
|
||||
#include "JsonObjectSubscript.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonVariant JsonObject::get(JsonObjectKey key) const {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value : JsonVariant();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonObject::get(JsonObjectKey key) const {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value.as<T>() : JsonVariant::invalid<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool JsonObject::is(JsonObjectKey key) const {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value.is<T>() : false;
|
||||
}
|
||||
|
||||
inline JsonObjectSubscript<const char *> JsonObject::operator[](
|
||||
const char *key) {
|
||||
return JsonObjectSubscript<const char *>(*this, key);
|
||||
}
|
||||
|
||||
inline JsonObjectSubscript<const String &> JsonObject::operator[](
|
||||
const String &key) {
|
||||
return JsonObjectSubscript<const String &>(*this, key);
|
||||
}
|
||||
|
||||
inline JsonVariant JsonObject::operator[](JsonObjectKey key) const {
|
||||
return get(key);
|
||||
}
|
||||
|
||||
inline bool JsonObject::containsKey(JsonObjectKey key) const {
|
||||
return getNodeAt(key) != NULL;
|
||||
}
|
||||
|
||||
inline JsonArray &JsonObject::createNestedArray(const char *key) {
|
||||
return createArrayAt<const char *>(key);
|
||||
}
|
||||
|
||||
inline JsonArray &JsonObject::createNestedArray(const String &key) {
|
||||
return createArrayAt<const String &>(key);
|
||||
}
|
||||
|
||||
inline JsonObject &JsonObject::createNestedObject(const char *key) {
|
||||
return createObjectAt<const char *>(key);
|
||||
}
|
||||
|
||||
inline JsonObject &JsonObject::createNestedObject(const String &key) {
|
||||
return createObjectAt<const String &>(key);
|
||||
}
|
||||
|
||||
inline void JsonObject::remove(JsonObjectKey key) {
|
||||
removeNode(getNodeAt(key));
|
||||
}
|
||||
|
||||
inline bool JsonObject::set(const char *key, bool value) {
|
||||
return setNodeAt<const char *, bool>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, float value, uint8_t decimals) {
|
||||
return setNodeAt<const char *, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, double value, uint8_t decimals) {
|
||||
return setNodeAt<const char *, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed char value) {
|
||||
return setNodeAt<const char *, signed char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed long value) {
|
||||
return setNodeAt<const char *, signed long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed int value) {
|
||||
return setNodeAt<const char *, signed int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed short value) {
|
||||
return setNodeAt<const char *, signed short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned char value) {
|
||||
return setNodeAt<const char *, unsigned char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned long value) {
|
||||
return setNodeAt<const char *, unsigned long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned int value) {
|
||||
return setNodeAt<const char *, unsigned int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned short value) {
|
||||
return setNodeAt<const char *, unsigned short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, const char *value) {
|
||||
return setNodeAt<const char *, const char *>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, const String &value) {
|
||||
return setNodeAt<const char *, const String &>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, JsonArray &array) {
|
||||
return setNodeAt<const char *, JsonArray &>(key, array);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, JsonObject &object) {
|
||||
return setNodeAt<const char *, JsonObject &>(key, object);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, const JsonVariant &value) {
|
||||
return setNodeAt<const char *, const JsonVariant &>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, bool value) {
|
||||
return setNodeAt<const String &, bool>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, float value, uint8_t decimals) {
|
||||
return setNodeAt<const String &, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, double value, uint8_t decimals) {
|
||||
return setNodeAt<const String &, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed char value) {
|
||||
return setNodeAt<const String &, signed char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed long value) {
|
||||
return setNodeAt<const String &, signed long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed int value) {
|
||||
return setNodeAt<const String &, signed int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed short value) {
|
||||
return setNodeAt<const String &, signed short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned char value) {
|
||||
return setNodeAt<const String &, unsigned char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned long value) {
|
||||
return setNodeAt<const String &, unsigned long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned int value) {
|
||||
return setNodeAt<const String &, unsigned int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned short value) {
|
||||
return setNodeAt<const String &, unsigned short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, const char *value) {
|
||||
return setNodeAt<const String &, const char *>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, const String &value) {
|
||||
return setNodeAt<const String &, const String &>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, JsonArray &array) {
|
||||
return setNodeAt<const String &, JsonArray &>(key, array);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, JsonObject &object) {
|
||||
return setNodeAt<const String &, JsonObject &>(key, object);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, const JsonVariant &value) {
|
||||
return setNodeAt<const String &, const JsonVariant &>(key, value);
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
inline bool JsonObject::setNodeAt(TKey key, TValue value) {
|
||||
node_type *node = getOrCreateNodeAt(key);
|
||||
if (!node) return false;
|
||||
setNodeKey<TKey>(node, key);
|
||||
setNodeValue<TValue>(node, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonObject::setNodeKey(node_type *node, const char *key) {
|
||||
node->content.key = key;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonObject::setNodeKey(node_type *node, const String &key) {
|
||||
node->content.key = _buffer->strdup(key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline void JsonObject::setNodeValue(node_type *node, TValue value) {
|
||||
node->content.value = value;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonObject::setNodeValue(node_type *node, const String &value) {
|
||||
node->content.value = _buffer->strdup(value);
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonObjectSubscript<const char *> JsonVariantBase<TImplem>::
|
||||
operator[](const char *key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonObjectSubscript<const String &> JsonVariantBase<TImplem>::
|
||||
operator[](const String &key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonObject const &JsonVariant::invalid<JsonObject const &>() {
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonObject &JsonVariant::invalid<JsonObject &>() {
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline JsonObject &JsonVariant::as<JsonObject &>() const {
|
||||
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline const JsonObject &JsonVariant::as<const JsonObject &>() const {
|
||||
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Arduino/String.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class JsonObjectKey {
|
||||
public:
|
||||
JsonObjectKey() {}
|
||||
JsonObjectKey(const char* key) : _data(key) {}
|
||||
JsonObjectKey(const String& key) : _data(key.c_str()) {}
|
||||
|
||||
operator const char*() const { return _data; }
|
||||
|
||||
private:
|
||||
const char* _data;
|
||||
};
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonSubscriptBase.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript
|
||||
: public JsonSubscriptBase<JsonObjectSubscript<TKey> > {
|
||||
public:
|
||||
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key)
|
||||
: _object(object), _key(key) {}
|
||||
|
||||
using JsonSubscriptBase<JsonObjectSubscript<TKey> >::operator=;
|
||||
|
||||
FORCE_INLINE bool success() const { return _object.containsKey(_key); }
|
||||
|
||||
FORCE_INLINE operator JsonVariant() const { return _object.get(_key); }
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE TValue as() const {
|
||||
return _object.get<TValue>(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE TValue is() const {
|
||||
return _object.is<TValue>(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue value) {
|
||||
return _object.set(_key, value);
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonVariant get() { return _object.get(_key); }
|
||||
|
||||
void writeTo(Internals::JsonWriter& writer) const {
|
||||
_object.get(_key).writeTo(writer);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonObject& _object;
|
||||
TKey _key;
|
||||
};
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(
|
||||
std::ostream& os, const JsonObjectSubscript<const String&>& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(
|
||||
std::ostream& os, const JsonObjectSubscript<const char*>& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantBase.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonSubscriptBase : public JsonVariantBase<TImpl> {
|
||||
public:
|
||||
FORCE_INLINE TImpl& operator=(bool value) { return assign<bool>(value); }
|
||||
|
||||
FORCE_INLINE TImpl& operator=(float value) { return assign<float>(value); }
|
||||
|
||||
FORCE_INLINE TImpl& operator=(double value) { return assign<double>(value); }
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed char value) {
|
||||
return assign<signed char>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed long value) {
|
||||
return assign<signed long>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed int value) {
|
||||
return assign<signed int>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed short value) {
|
||||
return assign<signed short>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned char value) {
|
||||
return assign<unsigned char>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned long value) {
|
||||
return assign<unsigned long>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned int value) {
|
||||
return assign<unsigned int>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned short value) {
|
||||
return assign<unsigned short>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(const char* value) {
|
||||
return assign<const char*>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(const String& value) {
|
||||
return assign<const String&>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(JsonArray& array) {
|
||||
return assign<JsonArray&>(array);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(JsonObject& object) {
|
||||
return assign<JsonObject&>(object);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(JsonVariant value) {
|
||||
return assign<JsonVariant>(value);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TValue>
|
||||
FORCE_INLINE TImpl& assign(TValue value) {
|
||||
TImpl* that = static_cast<TImpl*>(this);
|
||||
that->template set<TValue>(value);
|
||||
return *that;
|
||||
}
|
||||
};
|
||||
}
|
@ -1,103 +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"
|
||||
#include "Internals/Unparsed.hpp"
|
||||
#include "JsonVariantBase.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 JsonVariantBase<JsonVariant> {
|
||||
public:
|
||||
// Creates an uninitialized JsonVariant
|
||||
FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||
|
||||
// Create a JsonVariant containing a boolean value.
|
||||
// It will be serialized as "true" or "false" in JSON.
|
||||
FORCE_INLINE JsonVariant(bool value);
|
||||
|
||||
// Create a JsonVariant containing a floating point value.
|
||||
// The second argument specifies the number of decimal digits to write in
|
||||
// the JSON string.
|
||||
FORCE_INLINE JsonVariant(float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE JsonVariant(double value, uint8_t decimals = 2);
|
||||
|
||||
// Create a JsonVariant containing an integer value.
|
||||
FORCE_INLINE JsonVariant(signed char value);
|
||||
FORCE_INLINE JsonVariant(signed long value);
|
||||
FORCE_INLINE JsonVariant(signed int value);
|
||||
FORCE_INLINE JsonVariant(signed short value);
|
||||
FORCE_INLINE JsonVariant(unsigned char value);
|
||||
FORCE_INLINE JsonVariant(unsigned long value);
|
||||
FORCE_INLINE JsonVariant(unsigned int value);
|
||||
FORCE_INLINE JsonVariant(unsigned short value);
|
||||
|
||||
// Create a JsonVariant containing a string.
|
||||
FORCE_INLINE JsonVariant(const char *value);
|
||||
|
||||
// Create a JsonVariant containing an unparsed string
|
||||
FORCE_INLINE JsonVariant(Internals::Unparsed value);
|
||||
|
||||
// Create a JsonVariant containing a reference to an array.
|
||||
FORCE_INLINE JsonVariant(JsonArray &array);
|
||||
|
||||
// Create a JsonVariant containing a reference to an object.
|
||||
FORCE_INLINE JsonVariant(JsonObject &object);
|
||||
|
||||
// Get the variant as the specified type.
|
||||
// See cast operators for details.
|
||||
template <typename T>
|
||||
T as() const;
|
||||
|
||||
// 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;
|
||||
|
||||
// Serialize the variant to a JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
// TODO: rename
|
||||
template <typename T>
|
||||
static T invalid();
|
||||
|
||||
private:
|
||||
// The current type of the variant
|
||||
Internals::JsonVariantType _type;
|
||||
|
||||
// The various alternatives for the value of the variant.
|
||||
Internals::JsonVariantContent _content;
|
||||
};
|
||||
|
||||
inline JsonVariant float_with_n_digits(float value, uint8_t digits) {
|
||||
return JsonVariant(value, digits);
|
||||
}
|
||||
|
||||
inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
|
||||
return JsonVariant(value, digits);
|
||||
}
|
||||
}
|
||||
|
||||
// Include inline implementations
|
||||
#include "JsonVariant.ipp"
|
@ -1,239 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonVariant::JsonVariant(bool value) {
|
||||
_type = Internals::JSON_BOOLEAN;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(const char *value) {
|
||||
_type = Internals::JSON_STRING;
|
||||
_content.asString = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(Internals::Unparsed value) {
|
||||
_type = Internals::JSON_UNPARSED;
|
||||
_content.asString = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(double value, uint8_t decimals) {
|
||||
_type = static_cast<Internals::JsonVariantType>(
|
||||
Internals::JSON_DOUBLE_0_DECIMALS + decimals);
|
||||
_content.asDouble = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(float value, uint8_t decimals) {
|
||||
_type = static_cast<Internals::JsonVariantType>(
|
||||
Internals::JSON_DOUBLE_0_DECIMALS + decimals);
|
||||
_content.asDouble = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(JsonArray &array) {
|
||||
_type = Internals::JSON_ARRAY;
|
||||
_content.asArray = &array;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(JsonObject &object) {
|
||||
_type = Internals::JSON_OBJECT;
|
||||
_content.asObject = &object;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(signed char value) {
|
||||
_type = Internals::JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(signed int value) {
|
||||
_type = Internals::JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(signed long value) {
|
||||
_type = Internals::JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(signed short value) {
|
||||
_type = Internals::JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(unsigned char value) {
|
||||
_type = Internals::JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(unsigned int value) {
|
||||
_type = Internals::JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(unsigned long value) {
|
||||
_type = Internals::JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(unsigned short value) {
|
||||
_type = Internals::JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
template <>
|
||||
double JsonVariant::as<double>() const;
|
||||
|
||||
template <>
|
||||
long JsonVariant::as<long>() const;
|
||||
|
||||
template <>
|
||||
String JsonVariant::as<String>() const;
|
||||
|
||||
template <>
|
||||
const char *JsonVariant::as<const char *>() const;
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::as<bool>() const {
|
||||
return as<long>() != 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline signed char JsonVariant::as<signed char>() const {
|
||||
return static_cast<signed char>(as<long>());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned char JsonVariant::as<unsigned char>() const {
|
||||
return static_cast<unsigned char>(as<long>());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline signed short JsonVariant::as<signed short>() const {
|
||||
return static_cast<signed short>(as<long>());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned short JsonVariant::as<unsigned short>() const {
|
||||
return static_cast<unsigned short>(as<long>());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline signed int JsonVariant::as<signed int>() const {
|
||||
return static_cast<signed int>(as<long>());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned int JsonVariant::as<unsigned int>() const {
|
||||
return static_cast<unsigned int>(as<long>());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned long JsonVariant::as<unsigned long>() const {
|
||||
return static_cast<unsigned long>(as<long>());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline float JsonVariant::as<float>() const {
|
||||
return static_cast<float>(as<double>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonVariant::invalid() {
|
||||
return T();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool JsonVariant::is() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <> // in .cpp
|
||||
bool JsonVariant::is<signed long>() const;
|
||||
|
||||
template <> // in .cpp
|
||||
bool JsonVariant::is<double>() const;
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<bool>() const {
|
||||
return _type == Internals::JSON_BOOLEAN;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<char const *>() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<float>() const {
|
||||
return is<double>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonArray &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonArray const &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonObject &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonObject const &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<signed char>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<signed int>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<signed short>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<unsigned char>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<unsigned int>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<unsigned long>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<unsigned short>() const {
|
||||
return is<signed long>();
|
||||
}
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
@ -1,151 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Internals/ForceInline.hpp"
|
||||
#include "JsonObjectKey.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArraySubscript;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||
public:
|
||||
// Gets the variant as a boolean value.
|
||||
// Returns false if the variant is not a boolean value.
|
||||
FORCE_INLINE operator bool() const { return as<bool>(); }
|
||||
|
||||
// Gets the variant as a floating-point value.
|
||||
// Returns 0.0 if the variant is not a floating-point value
|
||||
FORCE_INLINE operator double() const { return as<double>(); }
|
||||
FORCE_INLINE operator float() const { return as<float>(); }
|
||||
|
||||
// Gets the variant as an integer value.
|
||||
// Returns 0 if the variant is not an integer value.
|
||||
FORCE_INLINE operator signed long() const { return as<signed long>(); }
|
||||
FORCE_INLINE operator signed char() const { return as<signed char>(); }
|
||||
FORCE_INLINE operator signed int() const { return as<signed int>(); }
|
||||
FORCE_INLINE operator signed short() const { return as<signed short>(); }
|
||||
FORCE_INLINE operator unsigned char() const { return as<unsigned char>(); }
|
||||
FORCE_INLINE operator unsigned int() const { return as<unsigned int>(); }
|
||||
FORCE_INLINE operator unsigned long() const { return as<unsigned long>(); }
|
||||
FORCE_INLINE operator unsigned short() const { return as<unsigned short>(); }
|
||||
|
||||
// Gets the variant as a string.
|
||||
// Returns NULL if variant is not a string.
|
||||
FORCE_INLINE operator const char *() const { return as<const char *>(); }
|
||||
FORCE_INLINE const char *asString() const { return as<const char *>(); }
|
||||
FORCE_INLINE operator String() const { return as<String>(); }
|
||||
|
||||
// Gets the variant as an array.
|
||||
// Returns a reference to the JsonArray or JsonArray::invalid() if the
|
||||
// variant
|
||||
// is not an array.
|
||||
FORCE_INLINE operator JsonArray &() const { return as<JsonArray &>(); }
|
||||
FORCE_INLINE JsonArray &asArray() const { return as<JsonArray &>(); }
|
||||
|
||||
// Gets the variant as an object.
|
||||
// Returns a reference to the JsonObject or JsonObject::invalid() if the
|
||||
// variant is not an object.
|
||||
FORCE_INLINE operator JsonObject &() const { return as<JsonObject &>(); }
|
||||
FORCE_INLINE JsonObject &asObject() const { return as<JsonObject &>(); }
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE const T as() const {
|
||||
return impl()->template as<T>();
|
||||
}
|
||||
|
||||
// Mimics an array or an object.
|
||||
// Returns the size of the array or object if the variant has that type.
|
||||
// Returns 0 if the variant is neither an array nor an object
|
||||
size_t size() const { return asArray().size() + asObject().size(); }
|
||||
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
// Returns JsonVariant::invalid() if the variant is not an array.
|
||||
FORCE_INLINE const JsonArraySubscript operator[](int index) const;
|
||||
|
||||
// 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.
|
||||
FORCE_INLINE const JsonObjectSubscript<const char *> operator[](
|
||||
const char *key) const;
|
||||
FORCE_INLINE const JsonObjectSubscript<const String &> operator[](
|
||||
const String &key) const;
|
||||
|
||||
// Serialize the variant to a JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
private:
|
||||
const TImpl *impl() const { return static_cast<const TImpl *>(this); }
|
||||
};
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator==(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() == right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator==(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left == right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator!=(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() != right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator!=(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left != right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<=(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() <= right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<=(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left <= right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>=(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() >= right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>=(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left >= right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() < right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator<(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left < right.template as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>(const JsonVariantBase<TImpl> &left, TComparand right) {
|
||||
return left.template as<TComparand>() > right;
|
||||
}
|
||||
|
||||
template <typename TImpl, typename TComparand>
|
||||
inline bool operator>(TComparand left, const JsonVariantBase<TImpl> &right) {
|
||||
return left > right.template as<TComparand>();
|
||||
}
|
||||
}
|
@ -1,35 +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; }
|
||||
|
||||
virtual void* alloc(size_t bytes) {
|
||||
if (_size + bytes > CAPACITY) return NULL;
|
||||
void* p = &_buffer[_size];
|
||||
_size += round_size_up(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
|
||||
|
21
library.json
21
library.json
@ -1,17 +1,22 @@
|
||||
{
|
||||
"name": "Json",
|
||||
"name": "ArduinoJson",
|
||||
"keywords": "json, rest, http, web",
|
||||
"description": "An elegant and efficient JSON library for embedded systems",
|
||||
"repository":
|
||||
{
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"authors":
|
||||
{
|
||||
"version": "5.10.0",
|
||||
"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": "*"
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
name=ArduinoJson
|
||||
version=5.0.2
|
||||
version=5.10.0
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
paragraph=Like this project? Please star it on GitHub!
|
||||
url=https://github.com/bblanchon/ArduinoJson
|
||||
category=Data Processing
|
||||
url=https://bblanchon.github.io/ArduinoJson/
|
||||
architectures=*
|
||||
|
@ -12,10 +12,9 @@ rm -f $OUTPUT
|
||||
7z a $OUTPUT \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/include \
|
||||
ArduinoJson/src \
|
||||
ArduinoJson/keywords.txt \
|
||||
ArduinoJson/library.properties \
|
||||
ArduinoJson/LICENSE.md \
|
||||
ArduinoJson/README.md \
|
||||
ArduinoJson/src \
|
||||
-x!ArduinoJson/src/CMakeLists.txt
|
||||
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$")
|
@ -21,9 +21,9 @@ if [[ $(uname) == MINGW* ]]
|
||||
then
|
||||
build-env "Make" "MinGW Makefiles"
|
||||
build-env "SublimeText" "Sublime Text 2 - Ninja"
|
||||
build-env "VisualStudio" "Visual Studio 12 2013"
|
||||
build-env "VisualStudio" "Visual Studio 14 2015"
|
||||
else
|
||||
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
|
@ -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
|
30
scripts/travis/cmake.sh
Executable file
30
scripts/travis/cmake.sh
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
if [ $(uname) = 'Darwin' ]; then
|
||||
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Darwin-x86_64.tar.gz
|
||||
CMAKE=/tmp/CMake.app/Contents/bin/cmake
|
||||
CTEST=/tmp/CMake.app/Contents/bin/ctest
|
||||
else
|
||||
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.tar.gz
|
||||
CMAKE=/tmp/bin/cmake
|
||||
CTEST=/tmp/bin/ctest
|
||||
fi
|
||||
curl -sS $URL | tar xz -C /tmp --strip 1
|
||||
|
||||
if [ -n "$GCC" ]; then
|
||||
export CC="gcc-$GCC"
|
||||
export CXX="g++-$GCC"
|
||||
fi
|
||||
|
||||
if [ -n "$CLANG" ]; then
|
||||
export CC="clang-$CLANG"
|
||||
export CXX="clang++-$CLANG"
|
||||
fi
|
||||
|
||||
if [ -n "$SANITIZE" ]; then
|
||||
export CXXFLAGS="-fsanitize=$SANITIZE"
|
||||
fi
|
||||
|
||||
$CMAKE .
|
||||
$CMAKE --build .
|
||||
$CTEST --output-on-failure .
|
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
|
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,65 +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()
|
||||
|
||||
// only for GCC 4.9+
|
||||
#if defined(__GNUC__) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))
|
||||
#pragma GCC diagnostic ignored "-Wfloat-conversion"
|
||||
#endif
|
||||
|
||||
// Visual Studo 2012 didn't have isnan, nor isinf
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
#include <float.h>
|
||||
#define isnan(x) _isnan(x)
|
||||
#define isinf(x) (!_finite(x))
|
||||
#endif
|
||||
|
||||
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
|
@ -1,25 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include "../../include/ArduinoJson/Arduino/String.hpp"
|
||||
|
||||
#include <stdio.h> // for sprintf()
|
||||
|
||||
String::String(double value, unsigned char digits) {
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%.*f", digits, value);
|
||||
*this = tmp;
|
||||
}
|
||||
|
||||
String::String(long value) {
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%ld", value);
|
||||
*this = tmp;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,13 +1,12 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
// About this file
|
||||
// ---------------
|
||||
// This file is here to please the Arduino IDE. It must be present in the src/
|
||||
// for the IDE to find it. Feel free to ignore this file if your working in
|
||||
// another environment
|
||||
#pragma once
|
||||
|
||||
#include "../include/ArduinoJson.h"
|
||||
#include "ArduinoJson.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
|
21
src/ArduinoJson.hpp
Normal file
21
src/ArduinoJson.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/JsonVariantComparisons.hpp"
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonBufferImpl.hpp"
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
|
148
src/ArduinoJson/Configuration.hpp
Normal file
148
src/ArduinoJson/Configuration.hpp
Normal file
@ -0,0 +1,148 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
// 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
|
||||
|
||||
#ifdef ARDUINO // assume this is an embedded platform
|
||||
|
||||
// store using float instead of double to reduce the memory usage (issue #134)
|
||||
#ifndef ARDUINOJSON_USE_DOUBLE
|
||||
#define ARDUINOJSON_USE_DOUBLE 0
|
||||
#endif
|
||||
|
||||
// store using a long because it usually match the size of a float.
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
|
||||
// Arduino has its own implementation of String to replace std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
|
||||
#endif
|
||||
|
||||
// On AVR archiecture, we can use PROGMEM
|
||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||
#ifdef PROGMEM
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 1
|
||||
#else
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Arduino doesn't have std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
#define ARDUINOJSON_ENABLE_STD_STRING 0
|
||||
#endif
|
||||
|
||||
// Arduino doesn't support STL stream
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM 0
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
// alignment isn't needed for 8-bit AVR
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
|
||||
#else
|
||||
// but must processor needs pointer to be align on word size
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// low value to prevent stack overflow
|
||||
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
|
||||
#endif
|
||||
|
||||
#else // assume this is a computer
|
||||
|
||||
// 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, there is no reason to beleive Arduino String is available
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
|
||||
#endif
|
||||
|
||||
// PROGMEM is only available on AVR architecture
|
||||
#ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||
#endif
|
||||
|
||||
// on a computer, we can assume that the STL is there
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#define ARDUINOJSON_ENABLE_STD_STREAM 1
|
||||
#endif
|
||||
|
||||
// on a computer, there is no reason to beleive Arduino Stream is available
|
||||
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
// even if not required, most cpu's are faster with aligned pointers
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
// on a computer, we should have a lot of space on the stack
|
||||
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
|
||||
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
|
||||
#endif
|
@ -1,13 +1,12 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
@ -15,7 +14,7 @@ class Encoding {
|
||||
public:
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char escapeChar(char c) {
|
||||
const char *p = _escapeTable;
|
||||
const char *p = escapeTable(false);
|
||||
while (p[0] && p[1] != c) {
|
||||
p += 2;
|
||||
}
|
||||
@ -24,7 +23,7 @@ class Encoding {
|
||||
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char unescapeChar(char c) {
|
||||
const char *p = _escapeTable + 4;
|
||||
const char *p = escapeTable(true);
|
||||
for (;;) {
|
||||
if (p[0] == '\0') return c;
|
||||
if (p[0] == c) return p[1];
|
||||
@ -32,8 +31,10 @@ class Encoding {
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static const char _escapeTable[];
|
||||
private:
|
||||
static const char *escapeTable(bool excludeIdenticals) {
|
||||
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -18,7 +19,7 @@ class JsonBufferAllocated {
|
||||
return jsonBuffer->alloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *, JsonBuffer *) throw() {}
|
||||
void operator delete(void *, JsonBuffer *)throw() {}
|
||||
};
|
||||
}
|
||||
}
|
21
src/ArduinoJson/Data/JsonFloat.hpp
Normal file
21
src/ArduinoJson/Data/JsonFloat.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
typedef double JsonFloat;
|
||||
#else
|
||||
typedef float JsonFloat;
|
||||
#endif
|
||||
}
|
||||
}
|
26
src/ArduinoJson/Data/JsonInteger.hpp
Normal file
26
src/ArduinoJson/Data/JsonInteger.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
45
src/ArduinoJson/Data/JsonVariantAs.hpp
Normal file
45
src/ArduinoJson/Data/JsonVariantAs.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#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;
|
||||
};
|
||||
}
|
||||
}
|
69
src/ArduinoJson/Data/JsonVariantComparer.hpp
Normal file
69
src/ArduinoJson/Data/JsonVariantComparer.hpp
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonVariantBase.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TComparand, typename Enable = void>
|
||||
struct JsonVariantComparer {};
|
||||
|
||||
template <typename TString>
|
||||
struct JsonVariantComparer<
|
||||
TString,
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsString<TString>::value>::type> {
|
||||
template <typename TVariant>
|
||||
static bool equals(const JsonVariantBase<TVariant> &variant,
|
||||
const TString &comparand) {
|
||||
const char *value = variant.template as<const char *>();
|
||||
return Internals::StringTraits<TString>::equals(comparand, value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TComparand>
|
||||
struct JsonVariantComparer<
|
||||
TComparand, typename TypeTraits::EnableIf<
|
||||
!TypeTraits::IsVariant<TComparand>::value &&
|
||||
!TypeTraits::IsString<TComparand>::value>::type> {
|
||||
template <typename TVariant>
|
||||
static bool equals(const JsonVariantBase<TVariant> &variant,
|
||||
const TComparand &comparand) {
|
||||
return variant.template as<TComparand>() == comparand;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TVariant2>
|
||||
struct JsonVariantComparer<TVariant2,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsVariant<TVariant2>::value>::type> {
|
||||
template <typename TVariant1>
|
||||
static bool equals(const JsonVariantBase<TVariant1> &left,
|
||||
const TVariant2 &right) {
|
||||
if (left.template is<bool>() && right.template is<bool>())
|
||||
return left.template as<bool>() == right.template as<bool>();
|
||||
if (left.template is<JsonInteger>() && right.template is<JsonInteger>())
|
||||
return left.template as<JsonInteger>() ==
|
||||
right.template as<JsonInteger>();
|
||||
if (left.template is<JsonFloat>() && right.template is<JsonFloat>())
|
||||
return left.template as<JsonFloat>() == right.template as<JsonFloat>();
|
||||
if (left.template is<JsonArray>() && right.template is<JsonArray>())
|
||||
return left.template as<JsonArray>() == right.template as<JsonArray>();
|
||||
if (left.template is<JsonObject>() && right.template is<JsonObject>())
|
||||
return left.template as<JsonObject>() == right.template as<JsonObject>();
|
||||
if (left.template is<char *>() && right.template is<char *>())
|
||||
return strcmp(left.template as<char *>(), right.template as<char *>()) ==
|
||||
0;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,11 +1,15 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
@ -13,12 +17,11 @@ 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 {
|
||||
double asDouble; // asDouble is also used for float
|
||||
long asLong; // asLong is also used for bool, 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
|
26
src/ArduinoJson/Data/JsonVariantDefault.hpp
Normal file
26
src/ArduinoJson/Data/JsonVariantDefault.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#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> {};
|
||||
}
|
||||
}
|
30
src/ArduinoJson/Data/JsonVariantType.hpp
Normal file
30
src/ArduinoJson/Data/JsonVariantType.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#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
|
||||
};
|
||||
}
|
||||
}
|
97
src/ArduinoJson/Data/List.hpp
Normal file
97
src/ArduinoJson/Data/List.hpp
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListIterator.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A singly linked list of T.
|
||||
// The linked list is composed of ListNode<T>.
|
||||
// It is derived by JsonArray and JsonObject
|
||||
template <typename T>
|
||||
class List {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ListNode<T> node_type;
|
||||
typedef ListIterator<T> iterator;
|
||||
typedef ListConstIterator<T> const_iterator;
|
||||
|
||||
// Creates an empty List<T> attached to a JsonBuffer.
|
||||
// The JsonBuffer allows to allocate new nodes.
|
||||
// When buffer is NULL, the List is not able to grow and success() returns
|
||||
// false. This is used to identify bad memory allocations and parsing
|
||||
// failures.
|
||||
explicit List(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {}
|
||||
|
||||
// Returns true if the object is valid
|
||||
// Would return false in the following situation:
|
||||
// - the memory allocation failed (StaticJsonBuffer was too small)
|
||||
// - the JSON parsing failed
|
||||
bool success() const {
|
||||
return _buffer != NULL;
|
||||
}
|
||||
|
||||
// Returns the numbers of elements in the list.
|
||||
// For a JsonObject, it would return the number of key-value pairs
|
||||
size_t size() const {
|
||||
size_t nodeCount = 0;
|
||||
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
iterator add() {
|
||||
node_type *newNode = new (_buffer) node_type();
|
||||
|
||||
if (_firstNode) {
|
||||
node_type *lastNode = _firstNode;
|
||||
while (lastNode->next) lastNode = lastNode->next;
|
||||
lastNode->next = newNode;
|
||||
} else {
|
||||
_firstNode = newNode;
|
||||
}
|
||||
|
||||
return iterator(newNode);
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return iterator(_firstNode);
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(NULL);
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return const_iterator(_firstNode);
|
||||
}
|
||||
const_iterator end() const {
|
||||
return const_iterator(NULL);
|
||||
}
|
||||
|
||||
void remove(iterator it) {
|
||||
node_type *nodeToRemove = it._node;
|
||||
if (!nodeToRemove) return;
|
||||
if (nodeToRemove == _firstNode) {
|
||||
_firstNode = nodeToRemove->next;
|
||||
} else {
|
||||
for (node_type *node = _firstNode; node; node = node->next)
|
||||
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonBuffer *_buffer;
|
||||
|
||||
private:
|
||||
node_type *_firstNode;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -17,8 +18,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,6 +38,14 @@ class ListConstIterator {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const ListNode<T> *_node;
|
||||
};
|
@ -1,25 +1,35 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#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,7 +44,17 @@ 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;
|
@ -1,8 +1,9 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
@ -1,8 +1,9 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -18,7 +19,9 @@ class ReferenceType {
|
||||
return this == &other;
|
||||
}
|
||||
|
||||
bool operator!=(const ReferenceType& other) const { return this != &other; }
|
||||
bool operator!=(const ReferenceType& other) const {
|
||||
return this != &other;
|
||||
}
|
||||
|
||||
protected:
|
||||
ReferenceType() {}
|
51
src/ArduinoJson/Data/ValueSetter.hpp
Normal file
51
src/ArduinoJson/Data/ValueSetter.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TSourceRef, typename Enable = void>
|
||||
struct ValueSetter {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TSourceRef>
|
||||
struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<StringTraits<
|
||||
TSourceRef>::should_duplicate>::type> {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer* buffer, TDestination& destination,
|
||||
TSourceRef source) {
|
||||
const char* copy = buffer->strdup(source);
|
||||
if (!copy) return false;
|
||||
destination = copy;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TSourceRef>
|
||||
struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<!StringTraits<
|
||||
TSourceRef>::should_duplicate>::type> {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
|
||||
// unsigned char* -> char*
|
||||
destination = reinterpret_cast<const char*>(source);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
64
src/ArduinoJson/Deserialization/Comments.hpp
Normal file
64
src/ArduinoJson/Deserialization/Comments.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TInput>
|
||||
void skipSpacesAndComments(TInput& input) {
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
input.move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
switch (input.next()) {
|
||||
// C-style block comment
|
||||
case '*':
|
||||
input.move(); // skip '/'
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
107
src/ArduinoJson/Deserialization/JsonParser.hpp
Normal file
107
src/ArduinoJson/Deserialization/JsonParser.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#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);
|
||||
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
|
||||
|
||||
inline bool parseArrayTo(JsonVariant *destination);
|
||||
inline bool parseObjectTo(JsonVariant *destination);
|
||||
inline bool parseStringTo(JsonVariant *destination);
|
||||
|
||||
static inline bool isInRange(char c, char min, char max) {
|
||||
return min <= c && c <= max;
|
||||
}
|
||||
|
||||
static inline bool isLetterOrNumber(char c) {
|
||||
return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
|
||||
isInRange(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 Internals::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 TypeTraits::EnableIf<!TypeTraits::IsConst<TChar>::value>::type> {
|
||||
typedef typename Internals::StringTraits<TChar *>::Reader TReader;
|
||||
typedef StringWriter<TChar> TWriter;
|
||||
typedef JsonParser<TReader, TWriter> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, 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);
|
||||
}
|
||||
}
|
||||
}
|
196
src/ArduinoJson/Deserialization/JsonParserImpl.hpp
Normal file
196
src/ArduinoJson/Deserialization/JsonParserImpl.hpp
Normal file
@ -0,0 +1,196 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#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) {
|
||||
if (_nestingLimit == 0) return false;
|
||||
_nestingLimit--;
|
||||
bool success = parseAnythingToUnsafe(destination);
|
||||
_nestingLimit++;
|
||||
return success;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingToUnsafe(
|
||||
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() {
|
||||
// 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:
|
||||
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() {
|
||||
// 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:
|
||||
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 TypeTraits::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 (!isLetterOrNumber(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;
|
||||
}
|
44
src/ArduinoJson/Deserialization/StringWriter.hpp
Normal file
44
src/ArduinoJson/Deserialization/StringWriter.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TChar>
|
||||
class StringWriter {
|
||||
public:
|
||||
class String {
|
||||
public:
|
||||
String(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
|
||||
|
||||
void append(TChar c) {
|
||||
*(*_writePtr)++ = 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;
|
||||
};
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user