forked from bblanchon/ArduinoJson
Compare commits
123 Commits
Author | SHA1 | Date | |
---|---|---|---|
6757f35a3a | |||
ffb9b6d1ba | |||
e401498e4a | |||
d30e940b3b | |||
05ea5e04c8 | |||
a7ef99d0fe | |||
f2a8b52c2c | |||
409ca7ee4e | |||
387b565705 | |||
96f486001d | |||
a498abc14a | |||
c64340a9bb | |||
79d80a5dbf | |||
7ebff5949f | |||
434080572c | |||
c87a0e97ab | |||
2dbd94951c | |||
1e044f50c7 | |||
a7aa98510c | |||
729ab56878 | |||
907b627e16 | |||
10fcca20f8 | |||
59cd1f1433 | |||
4a2c570270 | |||
8c7edbd9c3 | |||
0801e16327 | |||
0df2a365f5 | |||
c7d6d33e6c | |||
c705f3cfeb | |||
7fecb36aee | |||
657a2ea8d9 | |||
dd064f4c96 | |||
3bc05b97ea | |||
bbd515f6f6 | |||
9b3e3a3d9c | |||
a3a2ca4796 | |||
eab13dc565 | |||
bebd1c400c | |||
36d1bb2f52 | |||
ae32695c3e | |||
c5d19a4dbd | |||
78728c6547 | |||
a8032f81d9 | |||
a138791964 | |||
f9f002c8f7 | |||
f192d5c12e | |||
a6724bd03f | |||
c77c3f33ef | |||
623aeee9bf | |||
a241d53d28 | |||
11500d2ff5 | |||
85708bc94f | |||
ba6e8856f2 | |||
c8448b0abf | |||
e35248ffc4 | |||
b47a3b566a | |||
6ab23bd523 | |||
987afff0e9 | |||
564c62f3b3 | |||
8733f95e51 | |||
ce63e9c3c3 | |||
77b7124cf1 | |||
6a608d4b49 | |||
01924618bd | |||
666e2fd0ce | |||
0cfc25d751 | |||
b6d8e6c989 | |||
ab2502f7b8 | |||
c57e6f3bd8 | |||
b54f1ffc1d | |||
bd0ea42277 | |||
7ae43bc4f8 | |||
056682327b | |||
8b66a25f66 | |||
96245dd3b4 | |||
9cc49da68a | |||
224918b463 | |||
cbeefa2503 | |||
6d68806633 | |||
ba3617c22f | |||
b7d9bb2765 | |||
74b42e2251 | |||
c0cf9c3fcc | |||
9f3ce18f06 | |||
b9e3255c9e | |||
e657396f65 | |||
929f608f2f | |||
c6a4bfa886 | |||
d5e25b12b8 | |||
7cf6fe6d62 | |||
155dd653e7 | |||
b5c8cd1766 | |||
4967e389c5 | |||
ffbaebd198 | |||
04b8781c8d | |||
5a4d993f7d | |||
823a172681 | |||
a1943e21ed | |||
01c287bc89 | |||
0cf8249b14 | |||
a8265a799d | |||
18bb653f10 | |||
a003a31952 | |||
0a1c27f873 | |||
75f8e25aed | |||
39c506b419 | |||
ef2641b49b | |||
bce101578d | |||
10e466426a | |||
9b90aeffa5 | |||
601b51890f | |||
2524a00a96 | |||
e31d667bec | |||
c161f698fc | |||
92e687303d | |||
f5b83f9314 | |||
5e7b9ec688 | |||
78ae0b8aee | |||
283dffc035 | |||
0aded2a798 | |||
1b5be892b9 | |||
756c279cdc | |||
08d05df00e |
5
.clang-format
Normal file
5
.clang-format
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||||
|
|
||||||
|
BasedOnStyle: Google
|
||||||
|
Standard: Cpp03
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.sh text eol=lf
|
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://github.com/bblanchon/ArduinoJson/wiki/FAQ
|
||||||
|
https://github.com/bblanchon/ArduinoJson/wiki/Avoiding-pitfalls
|
||||||
|
|
||||||
|
Next, make sure you provide all the relevant information: platform, code snippet, and error messages.
|
||||||
|
|
||||||
|
Please be concise!
|
||||||
|
-->
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,3 +3,6 @@
|
|||||||
/build
|
/build
|
||||||
/bin
|
/bin
|
||||||
/lib
|
/lib
|
||||||
|
/sftp-config.json
|
||||||
|
.tags
|
||||||
|
.tags_sorted_by_file
|
||||||
|
5
.mbedignore
Normal file
5
.mbedignore
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.github/
|
||||||
|
examples/
|
||||||
|
scripts/
|
||||||
|
test/
|
||||||
|
third-party/
|
130
.travis.yml
130
.travis.yml
@ -1,12 +1,118 @@
|
|||||||
language: c++
|
sudo: false
|
||||||
compiler:
|
language: cpp
|
||||||
- gcc
|
matrix:
|
||||||
- clang
|
include:
|
||||||
before_install:
|
- compiler: gcc
|
||||||
- sudo pip install cpp-coveralls
|
addons:
|
||||||
before_script:
|
apt:
|
||||||
- cmake -DCOVERAGE=true .
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
script:
|
packages: ['g++-4.4']
|
||||||
- make && make test
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.4
|
||||||
after_success:
|
- compiler: gcc
|
||||||
- coveralls --exclude test --exclude third-party --gcov-options '\-lp'
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['g++-4.5']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.5
|
||||||
|
- compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['g++-4.6']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.6
|
||||||
|
- compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['g++-4.7']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.7
|
||||||
|
- compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['g++-4.8']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.8
|
||||||
|
- compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['g++-4.9']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-4.9
|
||||||
|
- compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['g++-5']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=g++-5
|
||||||
|
- compiler: clang
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++
|
||||||
|
- compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.5']
|
||||||
|
packages: ['clang-3.5']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.5
|
||||||
|
- compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.6']
|
||||||
|
packages: ['clang-3.6']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.6
|
||||||
|
- compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.7']
|
||||||
|
packages: ['clang-3.7']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.7
|
||||||
|
- compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
|
||||||
|
packages: ['clang-3.8']
|
||||||
|
env: SCRIPT=cmake CMAKE_CXX_COMPILER=clang++-3.8
|
||||||
|
- compiler: gcc
|
||||||
|
env: SCRIPT=coverage
|
||||||
|
- os: osx
|
||||||
|
osx_image: beta-xcode6.1
|
||||||
|
compiler: clang
|
||||||
|
env: SCRIPT=cmake-osx
|
||||||
|
- os: osx
|
||||||
|
osx_image: beta-xcode6.2
|
||||||
|
compiler: clang
|
||||||
|
env: SCRIPT=cmake-osx
|
||||||
|
- os: osx
|
||||||
|
osx_image: beta-xcode6.3
|
||||||
|
compiler: clang
|
||||||
|
env: SCRIPT=cmake-osx
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode6.4
|
||||||
|
compiler: clang
|
||||||
|
env: SCRIPT=cmake-osx
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode7
|
||||||
|
compiler: clang
|
||||||
|
env: SCRIPT=cmake-osx
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode7.1
|
||||||
|
compiler: clang
|
||||||
|
env: SCRIPT=cmake-osx
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode7.2
|
||||||
|
compiler: clang
|
||||||
|
env: SCRIPT=cmake-osx
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode7.3
|
||||||
|
compiler: clang
|
||||||
|
env: SCRIPT=cmake-osx
|
||||||
|
- env: SCRIPT=arduino VERSION=1.5.8 BOARD=arduino:avr:uno
|
||||||
|
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
|
||||||
|
- env: SCRIPT=arduino VERSION=1.6.8 BOARD=arduino:avr:uno
|
||||||
|
- env: SCRIPT=arduino VERSION=1.6.9 BOARD=arduino:avr:uno
|
||||||
|
- env: SCRIPT=platformio BOARD=uno
|
||||||
|
- env: SCRIPT=platformio BOARD=due
|
||||||
|
- env: SCRIPT=platformio BOARD=esp01
|
||||||
|
- env: SCRIPT=platformio BOARD=teensy31
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- "~/.platformio"
|
||||||
|
script: scripts/travis/$SCRIPT.sh
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#ifdef ARDUINO
|
|
||||||
|
|
||||||
// This file is here to help the Arduino IDE find the other files.
|
|
||||||
|
|
||||||
#include "src/Arduino/Print.cpp"
|
|
||||||
#include "src/DynamicJsonBuffer.cpp"
|
|
||||||
#include "src/Internals/IndentedPrint.cpp"
|
|
||||||
#include "src/Internals/JsonParser.cpp"
|
|
||||||
#include "src/Internals/List.cpp"
|
|
||||||
#include "src/Internals/Prettyfier.cpp"
|
|
||||||
#include "src/Internals/QuotedString.cpp"
|
|
||||||
#include "src/Internals/StringBuilder.cpp"
|
|
||||||
#include "src/JsonArray.cpp"
|
|
||||||
#include "src/JsonBuffer.cpp"
|
|
||||||
#include "src/JsonObject.cpp"
|
|
||||||
#include "src/JsonVariant.cpp"
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,13 +1,8 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
#ifdef ARDUINO
|
|
||||||
|
|
||||||
// This file is here to help the Arduino IDE find the other files.
|
|
||||||
|
|
||||||
#include "include/ArduinoJson.h"
|
#include "include/ArduinoJson.h"
|
||||||
|
|
||||||
#endif
|
|
||||||
|
188
CHANGELOG.md
188
CHANGELOG.md
@ -1,5 +1,189 @@
|
|||||||
Arduino JSON: change log
|
ArduinoJson: change log
|
||||||
========================
|
=======================
|
||||||
|
|
||||||
|
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**:
|
||||||
|
- `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"`
|
||||||
|
- `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"`
|
||||||
|
|
||||||
|
v5.0.6
|
||||||
|
------
|
||||||
|
|
||||||
|
* Added parameter to `DynamicJsonBuffer` constructor to set initial size (issue #152)
|
||||||
|
* Fixed warning about library category in Arduino 1.6.6 (issue #147)
|
||||||
|
* Examples: Added a loop to wait for serial port to be ready (issue #156)
|
||||||
|
|
||||||
|
v5.0.5
|
||||||
|
------
|
||||||
|
|
||||||
|
* Added overload `JsonObjectSuscript::set(value, decimals)` (issue #143)
|
||||||
|
* Use `float` instead of `double` to reduce the size of `JsonVariant` (issue #134)
|
||||||
|
|
||||||
|
v5.0.4
|
||||||
|
------
|
||||||
|
|
||||||
|
* Fixed ambiguous overload with `JsonArraySubscript` and `JsonObjectSubscript` (issue #122)
|
||||||
|
|
||||||
|
v5.0.3
|
||||||
|
------
|
||||||
|
|
||||||
|
* Fixed `printTo(String)` which wrote numbers instead of strings (issue #120)
|
||||||
|
* Fixed return type of `JsonArray::is<T>()` and some others (issue #121)
|
||||||
|
|
||||||
|
v5.0.2
|
||||||
|
------
|
||||||
|
|
||||||
|
* Fixed segmentation fault in `parseObject(String)` and `parseArray(String)`, when the
|
||||||
|
`StaticJsonBuffer` is too small to hold a copy of the string
|
||||||
|
* Fixed Clang warning "register specifier is deprecated" (issue #102)
|
||||||
|
* Fixed GCC warning "declaration shadows a member" (issue #103)
|
||||||
|
* Fixed memory alignment, which made ESP8266 crash (issue #104)
|
||||||
|
* Fixed compilation on Visual Studio 2010 and 2012 (issue #107)
|
||||||
|
|
||||||
|
v5.0.1
|
||||||
|
------
|
||||||
|
|
||||||
|
* Fixed compilation with Arduino 1.0.6 (issue #99)
|
||||||
|
|
||||||
|
v5.0.0
|
||||||
|
------
|
||||||
|
|
||||||
|
* Added support of `String` class (issues #55, #56, #70, #77)
|
||||||
|
* Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57)
|
||||||
|
* Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87)
|
||||||
|
* Added support of non standard JSON input (issue #44)
|
||||||
|
* Added support of comments in JSON input (issue #88)
|
||||||
|
* Added implicit cast between numerical types (issues #64, #69, #93)
|
||||||
|
* Added ability to read number values as string (issue #90)
|
||||||
|
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66)
|
||||||
|
* Switched to new the library layout (requires Arduino 1.0.6 or above)
|
||||||
|
|
||||||
|
**BREAKING CHANGES**:
|
||||||
|
- `JsonObject::add()` was renamed to `set()`
|
||||||
|
- `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
|
||||||
|
- Number of digits of floating point value are now set with `double_with_n_digits()`
|
||||||
|
|
||||||
|
**Personal note about the `String` class**:
|
||||||
|
Support of the `String` class has been added to the library because many people use it in their programs.
|
||||||
|
However, you should not see this as an invitation to use the `String` class.
|
||||||
|
The `String` class is **bad** because it uses dynamic memory allocation.
|
||||||
|
Compared to static allocation, it compiles to a bigger, slower program, and is less predictable.
|
||||||
|
You certainly don't want that in an embedded environment!
|
||||||
|
|
||||||
|
v4.6
|
||||||
|
----
|
||||||
|
|
||||||
|
* Fixed segmentation fault in `DynamicJsonBuffer` when memory allocation fails (issue #92)
|
||||||
|
|
||||||
|
v4.5
|
||||||
|
----
|
||||||
|
|
||||||
|
* Fixed buffer overflow when input contains a backslash followed by a terminator (issue #81)
|
||||||
|
|
||||||
|
**Upgrading is recommended** since previous versions contain a potential security risk.
|
||||||
|
|
||||||
|
Special thanks to [Giancarlo Canales Barreto](https://github.com/gcanalesb) for finding this nasty bug.
|
||||||
|
|
||||||
|
v4.4
|
||||||
|
----
|
||||||
|
|
||||||
|
* Added `JsonArray::measureLength()` and `JsonObject::measureLength()` (issue #75)
|
||||||
|
|
||||||
v4.3
|
v4.3
|
||||||
----
|
----
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.4)
|
# Copyright Benoit Blanchon 2014-2016
|
||||||
|
# MIT License
|
||||||
|
#
|
||||||
|
# Arduino JSON library
|
||||||
|
# https://github.com/bblanchon/ArduinoJson
|
||||||
|
# If you like this project, please add a star!
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
project(ArduinoJson)
|
project(ArduinoJson)
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
@ -7,14 +14,8 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
|||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -W4)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${COVERAGE})
|
if(${COVERAGE})
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -coverage")
|
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(src)
|
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
@ -1,7 +1,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
Copyright © 2014 Benoit BLANCHON
|
Copyright © 2014-2016 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:
|
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:
|
||||||
|
|
||||||
|
99
README.md
99
README.md
@ -1,55 +1,77 @@
|
|||||||
Arduino JSON library
|
Arduino JSON library
|
||||||
====================
|
====================
|
||||||
|
|
||||||
[](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.*
|
*An elegant and efficient JSON library for embedded systems.*
|
||||||
|
|
||||||
It's design to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
|
It's designed to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
|
||||||
|
|
||||||
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* JSON decoding
|
* JSON decoding (comments are supported)
|
||||||
* JSON encoding (with optional indentation)
|
* JSON encoding (with optional indentation)
|
||||||
* Elegant API, very easy to use
|
* Elegant API, very easy to use
|
||||||
* Fixed memory allocation (no malloc)
|
* Fixed memory allocation (zero malloc)
|
||||||
|
* No data duplication (zero copy)
|
||||||
|
* Portable (written in C++98)
|
||||||
|
* Self-contained (no external dependency)
|
||||||
* Small footprint
|
* Small footprint
|
||||||
|
* Header-only library
|
||||||
* MIT License
|
* MIT License
|
||||||
|
|
||||||
|
Works on
|
||||||
|
--------
|
||||||
|
|
||||||
|
* All Arduino boards (Uno, Due, Mini, Micro, Yun...)
|
||||||
|
* ESP8266
|
||||||
|
* Teensy
|
||||||
|
* Intel Edison and Galileo
|
||||||
|
* PlatformIO
|
||||||
|
* Energia
|
||||||
|
* RedBearLab boards (BLE Nano...)
|
||||||
|
* Computers (Windows, Linux, OSX...)
|
||||||
|
|
||||||
|
See [FAQ: Compatibility issues](https://github.com/bblanchon/ArduinoJson/wiki/Compatibility-issues)
|
||||||
|
|
||||||
Quick start
|
Quick start
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
#### Decoding / Parsing
|
#### 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"];
|
const char* sensor = root["sensor"];
|
||||||
long time = root["time"];
|
long time = root["time"];
|
||||||
double latitude = root["data"][0];
|
double latitude = root["data"][0];
|
||||||
double longitude = root["data"][1];
|
double longitude = root["data"][1];
|
||||||
|
```
|
||||||
|
|
||||||
#### Encoding / Generating
|
#### Encoding / Generating
|
||||||
|
|
||||||
StaticJsonBuffer<200> jsonBuffer;
|
```c++
|
||||||
|
StaticJsonBuffer<200> jsonBuffer;
|
||||||
|
|
||||||
JsonObject& root = jsonBuffer.createObject();
|
JsonObject& root = jsonBuffer.createObject();
|
||||||
root["sensor"] = "gps";
|
root["sensor"] = "gps";
|
||||||
root["time"] = 1351824120;
|
root["time"] = 1351824120;
|
||||||
|
|
||||||
JsonArray& data = root.createNestedArray("data");
|
JsonArray& data = root.createNestedArray("data");
|
||||||
data.add(48.756080, 6); // 6 is the number of decimals to print
|
data.add(48.756080, 6); // 6 is the number of decimals to print
|
||||||
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
||||||
|
|
||||||
root.printTo(Serial);
|
root.printTo(Serial);
|
||||||
// This prints:
|
// This prints:
|
||||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
@ -64,18 +86,43 @@ 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 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.
|
> I have no such problem so far with your library. It is working perfectly with my web services.
|
||||||
|
|
||||||
From Arduino's Forum user `gbathree`:
|
|
||||||
> Thanks so much - this is an awesome library! If you want to see what we're doing with it - the project is located at www.photosynq.org.
|
|
||||||
|
|
||||||
From StackOverflow user `thegreendroid`:
|
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.
|
> It has a really elegant, simple API and it works like a charm on embedded and Windows/Linux platforms. We recently started using this on an embedded project and I can vouch for its quality.
|
||||||
|
|
||||||
From GitHub user `zacsketches`:
|
From GitHub user `zacsketches`:
|
||||||
|
|
||||||
> Thanks for a great library!!!
|
> 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.
|
> 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!!
|
> ArduinoJson saved me a week's worth of time!!
|
||||||
|
|
||||||
|
[From Reddit user `erm_what_`](https://www.reddit.com/r/arduino/comments/3jj6ep/announcing_arduinojson_50/cusjk8c):
|
||||||
|
> This is a great library and I wouldn't be able to do the project I'm doing without it. I completely recommend it.
|
||||||
|
|
||||||
|
[From Reddit user `makerhacks`](https://www.reddit.com/r/arduino/comments/3jj6ep/announcing_arduinojson_50/cusqg7b):
|
||||||
|
> I am just starting an ESP8266 clock project and now I can output JSON from my server script and interpret it painlessly.
|
||||||
|
|
||||||
|
[From Twitter user `@hemalchevli`](https://twitter.com/hemalchevli/status/715788439397011456):
|
||||||
|
> ArduinoJson library should be used as a benchmark/reference for making libraries. Truly elegant.
|
||||||
|
|
||||||
|
Donators
|
||||||
|
--------
|
||||||
|
|
||||||
|
Special thanks to the following persons and companies who made generous donations to the library author:
|
||||||
|
|
||||||
|
* 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'>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Found this library useful? [Help me back with a donation!](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile:
|
Found this library useful? Please star this project or [help me back with a donation!](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile:
|
||||||
|
18
appveyor.yml
Normal file
18
appveyor.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
version: 5.6.6.{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 -V .
|
@ -1,7 +1,9 @@
|
|||||||
/*
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
* Arduino JSON library - IndentedPrint example
|
// MIT License
|
||||||
* Benoit Blanchon 2014 - MIT License
|
//
|
||||||
*/
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
@ -9,6 +11,9 @@ using namespace ArduinoJson::Internals;
|
|||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
while (!Serial) {
|
||||||
|
// wait serial port initialization
|
||||||
|
}
|
||||||
|
|
||||||
IndentedPrint serial(Serial);
|
IndentedPrint serial(Serial);
|
||||||
serial.setTabSize(4);
|
serial.setTabSize(4);
|
||||||
|
@ -1,23 +1,51 @@
|
|||||||
// Copyright Benoit Blanchon 2014
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(9600);
|
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<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();
|
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["sensor"] = "gps";
|
||||||
root["time"] = 1351824120;
|
root["time"] = 1351824120;
|
||||||
|
|
||||||
|
// Add a nested array.
|
||||||
|
//
|
||||||
|
// It's also possible to create the array separately and add it to the
|
||||||
|
// JsonObject but it's less efficient.
|
||||||
JsonArray& data = root.createNestedArray("data");
|
JsonArray& data = root.createNestedArray("data");
|
||||||
data.add(48.756080, 6); // 6 is the number of decimals to print
|
data.add(double_with_n_digits(48.756080, 6));
|
||||||
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
data.add(double_with_n_digits(2.302038, 6));
|
||||||
|
|
||||||
root.printTo(Serial);
|
root.printTo(Serial);
|
||||||
// This prints:
|
// This prints:
|
||||||
|
195
examples/JsonHttpClient/JsonHttpClient.ino
Normal file
195
examples/JsonHttpClient/JsonHttpClient.ino
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
// Sample Arduino Json Web Client
|
||||||
|
// Downloads and parse http://jsonplaceholder.typicode.com/users/1
|
||||||
|
//
|
||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Ethernet.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()) {
|
||||||
|
char response[MAX_CONTENT_SIZE];
|
||||||
|
readReponseContent(response, sizeof(response));
|
||||||
|
|
||||||
|
UserData userData;
|
||||||
|
if (parseUserData(response, &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.1");
|
||||||
|
client.print("Host: ");
|
||||||
|
client.println(server);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the body of the response from the HTTP server
|
||||||
|
void readReponseContent(char* content, size_t maxSize) {
|
||||||
|
size_t length = client.readBytes(content, maxSize);
|
||||||
|
content[length] = 0;
|
||||||
|
Serial.println(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 parseUserData(char* content, 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
|
||||||
|
|
||||||
|
// Allocate a temporary memory pool on the stack
|
||||||
|
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
|
||||||
|
// If the memory pool is too big for the stack, use this instead:
|
||||||
|
// DynamicJsonBuffer jsonBuffer;
|
||||||
|
|
||||||
|
JsonObject& root = jsonBuffer.parseObject(content);
|
||||||
|
|
||||||
|
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
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(9600);
|
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<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[] =
|
char json[] =
|
||||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
"{\"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);
|
JsonObject& root = jsonBuffer.parseObject(json);
|
||||||
|
|
||||||
|
// Test if parsing succeeds.
|
||||||
if (!root.success()) {
|
if (!root.success()) {
|
||||||
Serial.println("parseObject() failed");
|
Serial.println("parseObject() failed");
|
||||||
return;
|
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"];
|
const char* sensor = root["sensor"];
|
||||||
long time = root["time"];
|
long time = root["time"];
|
||||||
double latitude = root["data"][0];
|
double latitude = root["data"][0];
|
||||||
double longitude = root["data"][1];
|
double longitude = root["data"][1];
|
||||||
|
|
||||||
|
// Print values.
|
||||||
Serial.println(sensor);
|
Serial.println(sensor);
|
||||||
Serial.println(time);
|
Serial.println(time);
|
||||||
Serial.println(latitude, 6);
|
Serial.println(latitude, 6);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// You can easily test this program with netcat:
|
// You can easily test this program with netcat:
|
||||||
// $ nc -ulp 8888
|
// $ nc -ulp 8888
|
||||||
//
|
//
|
||||||
// by Benoit Blanchon, MIT License 2015
|
// by Benoit Blanchon, MIT License 2015-2016
|
||||||
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <Ethernet.h>
|
#include <Ethernet.h>
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#include "../include/ArduinoJson/DynamicJsonBuffer.hpp"
|
#include "ArduinoJson.hpp"
|
||||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
|
||||||
#include "../include/ArduinoJson/JsonObject.hpp"
|
|
||||||
#include "../include/ArduinoJson/StaticJsonBuffer.hpp"
|
|
||||||
|
|
||||||
using namespace ArduinoJson;
|
using namespace ArduinoJson;
|
||||||
|
21
include/ArduinoJson.hpp
Normal file
21
include/ArduinoJson.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/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/StaticJsonBuffer.hpp"
|
||||||
|
|
||||||
|
#include "ArduinoJson/Internals/JsonParser.ipp"
|
||||||
|
#include "ArduinoJson/JsonArray.ipp"
|
||||||
|
#include "ArduinoJson/JsonBuffer.ipp"
|
||||||
|
#include "ArduinoJson/JsonObject.ipp"
|
||||||
|
#include "ArduinoJson/JsonVariant.ipp"
|
||||||
|
|
||||||
|
using namespace ArduinoJson;
|
@ -1,31 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef ARDUINO
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// This class reproduces Arduino's Print
|
|
||||||
class Print {
|
|
||||||
public:
|
|
||||||
virtual ~Print() {}
|
|
||||||
|
|
||||||
virtual size_t write(uint8_t) = 0;
|
|
||||||
|
|
||||||
size_t print(const char[]);
|
|
||||||
size_t print(double, int = 2);
|
|
||||||
size_t print(long);
|
|
||||||
size_t println();
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <Print.h>
|
|
||||||
|
|
||||||
#endif
|
|
89
include/ArduinoJson/Configuration.hpp
Normal file
89
include/ArduinoJson/Configuration.hpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#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_USE_ARDUINO_STRING
|
||||||
|
#define ARDUINOJSON_USE_ARDUINO_STRING 1
|
||||||
|
#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
|
||||||
|
|
||||||
|
#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_USE_ARDUINO_STRING
|
||||||
|
#define ARDUINOJSON_USE_ARDUINO_STRING 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
|
||||||
|
|
||||||
|
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||||
|
// even if not required, most cpu's are faster with aligned pointers
|
||||||
|
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||||
|
#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,46 +1,18 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "JsonBuffer.hpp"
|
#include "Internals/BlockJsonBuffer.hpp"
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
|
||||||
// Forward declaration
|
|
||||||
namespace Internals {
|
|
||||||
struct DynamicJsonBufferBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements a JsonBuffer with dynamic memory allocation.
|
// Implements a JsonBuffer with dynamic memory allocation.
|
||||||
// You are strongly encouraged to consider using StaticJsonBuffer which is much
|
// You are strongly encouraged to consider using StaticJsonBuffer which is much
|
||||||
// more suitable for embedded systems.
|
// more suitable for embedded systems.
|
||||||
class DynamicJsonBuffer : public JsonBuffer {
|
typedef Internals::BlockJsonBuffer<Internals::DefaultAllocator>
|
||||||
public:
|
DynamicJsonBuffer;
|
||||||
DynamicJsonBuffer();
|
|
||||||
~DynamicJsonBuffer();
|
|
||||||
|
|
||||||
size_t size() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void* alloc(size_t bytes);
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef Internals::DynamicJsonBufferBlock Block;
|
|
||||||
|
|
||||||
static const size_t FIRST_BLOCK_CAPACITY = 32;
|
|
||||||
|
|
||||||
static Block* createBlock(size_t capacity);
|
|
||||||
|
|
||||||
inline bool canAllocInHead(size_t bytes) const;
|
|
||||||
inline void* allocInHead(size_t bytes);
|
|
||||||
inline void addNewBlock();
|
|
||||||
|
|
||||||
Block* _head;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
115
include/ArduinoJson/Internals/BlockJsonBuffer.hpp
Normal file
115
include/ArduinoJson/Internals/BlockJsonBuffer.hpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../JsonBuffer.hpp"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#endif
|
||||||
|
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
class DefaultAllocator {
|
||||||
|
public:
|
||||||
|
void* allocate(size_t size) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
void deallocate(void* pointer) {
|
||||||
|
free(pointer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TAllocator>
|
||||||
|
class BlockJsonBuffer : public JsonBuffer {
|
||||||
|
struct Block;
|
||||||
|
struct EmptyBlock {
|
||||||
|
Block* next;
|
||||||
|
size_t capacity;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
struct Block : EmptyBlock {
|
||||||
|
uint8_t data[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
BlockJsonBuffer(size_t initialSize = 256)
|
||||||
|
: _head(NULL), _nextBlockSize(initialSize) {}
|
||||||
|
|
||||||
|
~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;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* alloc(size_t bytes) {
|
||||||
|
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
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 = _nextBlockSize;
|
||||||
|
if (bytes > capacity) capacity = bytes;
|
||||||
|
if (!addNewBlock(capacity)) return NULL;
|
||||||
|
_nextBlockSize *= 2;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
TAllocator _allocator;
|
||||||
|
Block* _head;
|
||||||
|
size_t _nextBlockSize;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
#endif
|
56
include/ArduinoJson/Internals/Comments.hpp
Normal file
56
include/ArduinoJson/Internals/Comments.hpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
inline const char *skipCStyleComment(const char *ptr) {
|
||||||
|
ptr += 2;
|
||||||
|
for (;;) {
|
||||||
|
if (ptr[0] == '\0') return ptr;
|
||||||
|
if (ptr[0] == '*' && ptr[1] == '/') return ptr + 2;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *skipCppStyleComment(const char *ptr) {
|
||||||
|
ptr += 2;
|
||||||
|
for (;;) {
|
||||||
|
if (ptr[0] == '\0' || ptr[0] == '\n') return ptr;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *skipSpacesAndComments(const char *ptr) {
|
||||||
|
for (;;) {
|
||||||
|
switch (ptr[0]) {
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
ptr++;
|
||||||
|
continue;
|
||||||
|
case '/':
|
||||||
|
switch (ptr[1]) {
|
||||||
|
case '*':
|
||||||
|
ptr = skipCStyleComment(ptr);
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
ptr = skipCppStyleComment(ptr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
include/ArduinoJson/Internals/DummyPrint.hpp
Normal file
21
include/ArduinoJson/Internals/DummyPrint.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../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; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
33
include/ArduinoJson/Internals/DynamicStringBuilder.hpp
Normal file
33
include/ArduinoJson/Internals/DynamicStringBuilder.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Print.hpp"
|
||||||
|
#include "../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) {
|
||||||
|
// Need to cast to char, otherwise String will print a number (issue #120)
|
||||||
|
_str += static_cast<char>(c);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DynamicStringBuilder &operator=(const DynamicStringBuilder &);
|
||||||
|
|
||||||
|
String &_str;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
42
include/ArduinoJson/Internals/Encoding.hpp
Normal file
42
include/ArduinoJson/Internals/Encoding.hpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Print.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
|
||||||
|
class Encoding {
|
||||||
|
public:
|
||||||
|
// Optimized for code size on a 8-bit AVR
|
||||||
|
static char escapeChar(char c) {
|
||||||
|
const char *p = escapeTable(false);
|
||||||
|
while (p[0] && p[1] != c) {
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
return p[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimized for code size on a 8-bit AVR
|
||||||
|
static char unescapeChar(char c) {
|
||||||
|
const char *p = escapeTable(true);
|
||||||
|
for (;;) {
|
||||||
|
if (p[0] == '\0') return c;
|
||||||
|
if (p[0] == c) return p[1];
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const char *escapeTable(bool excludeIdenticals) {
|
||||||
|
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Arduino/Print.hpp"
|
#include "../Print.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
namespace Internals {
|
namespace Internals {
|
||||||
@ -22,7 +23,13 @@ class IndentedPrint : public Print {
|
|||||||
isNewLine = true;
|
isNewLine = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t write(uint8_t);
|
virtual size_t write(uint8_t c) {
|
||||||
|
size_t n = 0;
|
||||||
|
if (isNewLine) n += writeTabs();
|
||||||
|
n += sink->write(c);
|
||||||
|
isNewLine = c == '\n';
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
// Adds one level of indentation
|
// Adds one level of indentation
|
||||||
void indent() {
|
void indent() {
|
||||||
@ -45,7 +52,11 @@ class IndentedPrint : public Print {
|
|||||||
uint8_t tabSize : 3;
|
uint8_t tabSize : 3;
|
||||||
bool isNewLine : 1;
|
bool isNewLine : 1;
|
||||||
|
|
||||||
size_t writeTabs();
|
size_t writeTabs() {
|
||||||
|
size_t n = 0;
|
||||||
|
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
static const int MAX_LEVEL = 15; // because it's only 4 bits
|
static const int MAX_LEVEL = 15; // because it's only 4 bits
|
||||||
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
|
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ namespace Internals {
|
|||||||
class JsonBufferAllocated {
|
class JsonBufferAllocated {
|
||||||
public:
|
public:
|
||||||
void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() {
|
void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() {
|
||||||
|
if (!jsonBuffer) return NULL;
|
||||||
return jsonBuffer->alloc(n);
|
return jsonBuffer->alloc(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
include/ArduinoJson/Internals/JsonFloat.hpp
Normal file
21
include/ArduinoJson/Internals/JsonFloat.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/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
include/ArduinoJson/Internals/JsonInteger.hpp
Normal file
26
include/ArduinoJson/Internals/JsonInteger.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/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
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -18,24 +19,47 @@ namespace Internals {
|
|||||||
class JsonParser {
|
class JsonParser {
|
||||||
public:
|
public:
|
||||||
JsonParser(JsonBuffer *buffer, char *json, uint8_t nestingLimit)
|
JsonParser(JsonBuffer *buffer, char *json, uint8_t nestingLimit)
|
||||||
: _buffer(buffer), _ptr(json), _nestingLimit(nestingLimit) {}
|
: _buffer(buffer),
|
||||||
|
_readPtr(json ? json : ""),
|
||||||
|
_writePtr(json),
|
||||||
|
_nestingLimit(nestingLimit) {}
|
||||||
|
|
||||||
JsonArray &parseArray();
|
JsonArray &parseArray();
|
||||||
JsonObject &parseObject();
|
JsonObject &parseObject();
|
||||||
|
|
||||||
|
JsonVariant parseVariant() {
|
||||||
|
JsonVariant result;
|
||||||
|
parseAnythingTo(&result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool skip(char charToSkip);
|
bool skip(char charToSkip);
|
||||||
bool skip(const char *wordToSkip);
|
|
||||||
void skipSpaces();
|
|
||||||
|
|
||||||
void parseAnythingTo(JsonVariant &destination);
|
const char *parseString();
|
||||||
inline void parseBooleanTo(JsonVariant &destination);
|
bool parseAnythingTo(JsonVariant *destination);
|
||||||
inline void parseNullTo(JsonVariant &destination);
|
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
|
||||||
inline void parseNumberTo(JsonVariant &destination);
|
|
||||||
inline const char *parseString();
|
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 == '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool isQuote(char c) {
|
||||||
|
return c == '\'' || c == '\"';
|
||||||
|
}
|
||||||
|
|
||||||
JsonBuffer *_buffer;
|
JsonBuffer *_buffer;
|
||||||
char *_ptr;
|
const char *_readPtr;
|
||||||
|
char *_writePtr;
|
||||||
uint8_t _nestingLimit;
|
uint8_t _nestingLimit;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
191
include/ArduinoJson/Internals/JsonParser.ipp
Normal file
191
include/ArduinoJson/Internals/JsonParser.ipp
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Comments.hpp"
|
||||||
|
#include "JsonParser.hpp"
|
||||||
|
|
||||||
|
inline bool ArduinoJson::Internals::JsonParser::skip(char charToSkip) {
|
||||||
|
const char *ptr = skipSpacesAndComments(_readPtr);
|
||||||
|
if (*ptr != charToSkip) return false;
|
||||||
|
ptr++;
|
||||||
|
_readPtr = skipSpacesAndComments(ptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ArduinoJson::Internals::JsonParser::parseAnythingTo(
|
||||||
|
JsonVariant *destination) {
|
||||||
|
if (_nestingLimit == 0) return false;
|
||||||
|
_nestingLimit--;
|
||||||
|
bool success = parseAnythingToUnsafe(destination);
|
||||||
|
_nestingLimit++;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ArduinoJson::Internals::JsonParser::parseAnythingToUnsafe(
|
||||||
|
JsonVariant *destination) {
|
||||||
|
_readPtr = skipSpacesAndComments(_readPtr);
|
||||||
|
|
||||||
|
switch (*_readPtr) {
|
||||||
|
case '[':
|
||||||
|
return parseArrayTo(destination);
|
||||||
|
|
||||||
|
case '{':
|
||||||
|
return parseObjectTo(destination);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return parseStringTo(destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ArduinoJson::JsonArray &
|
||||||
|
ArduinoJson::Internals::JsonParser::parseArray() {
|
||||||
|
// Create an empty array
|
||||||
|
JsonArray &array = _buffer->createArray();
|
||||||
|
|
||||||
|
// Check opening braket
|
||||||
|
if (!skip('[')) goto ERROR_MISSING_BRACKET;
|
||||||
|
if (skip(']')) 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 (skip(']')) goto SUCCES_NON_EMPTY_ARRAY;
|
||||||
|
if (!skip(',')) 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ArduinoJson::Internals::JsonParser::parseArrayTo(
|
||||||
|
JsonVariant *destination) {
|
||||||
|
JsonArray &array = parseArray();
|
||||||
|
if (!array.success()) return false;
|
||||||
|
|
||||||
|
*destination = array;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ArduinoJson::JsonObject &
|
||||||
|
ArduinoJson::Internals::JsonParser::parseObject() {
|
||||||
|
// Create an empty object
|
||||||
|
JsonObject &object = _buffer->createObject();
|
||||||
|
|
||||||
|
// Check opening brace
|
||||||
|
if (!skip('{')) goto ERROR_MISSING_BRACE;
|
||||||
|
if (skip('}')) goto SUCCESS_EMPTY_OBJECT;
|
||||||
|
|
||||||
|
// Read each key value pair
|
||||||
|
for (;;) {
|
||||||
|
// 1 - Parse key
|
||||||
|
const char *key = parseString();
|
||||||
|
if (!key) goto ERROR_INVALID_KEY;
|
||||||
|
if (!skip(':')) 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 (skip('}')) goto SUCCESS_NON_EMPTY_OBJECT;
|
||||||
|
if (!skip(',')) 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ArduinoJson::Internals::JsonParser::parseObjectTo(
|
||||||
|
JsonVariant *destination) {
|
||||||
|
JsonObject &object = parseObject();
|
||||||
|
if (!object.success()) return false;
|
||||||
|
|
||||||
|
*destination = object;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *ArduinoJson::Internals::JsonParser::parseString() {
|
||||||
|
const char *readPtr = _readPtr;
|
||||||
|
char *writePtr = _writePtr;
|
||||||
|
|
||||||
|
char c = *readPtr;
|
||||||
|
|
||||||
|
if (isQuote(c)) { // quotes
|
||||||
|
char stopChar = c;
|
||||||
|
for (;;) {
|
||||||
|
c = *++readPtr;
|
||||||
|
if (c == '\0') break;
|
||||||
|
|
||||||
|
if (c == stopChar) {
|
||||||
|
readPtr++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '\\') {
|
||||||
|
// replace char
|
||||||
|
c = Encoding::unescapeChar(*++readPtr);
|
||||||
|
if (c == '\0') break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*writePtr++ = c;
|
||||||
|
}
|
||||||
|
} else { // no quotes
|
||||||
|
for (;;) {
|
||||||
|
if (!isLetterOrNumber(c)) break;
|
||||||
|
*writePtr++ = c;
|
||||||
|
c = *++readPtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// end the string here
|
||||||
|
*writePtr++ = '\0';
|
||||||
|
|
||||||
|
const char *startPtr = _writePtr;
|
||||||
|
|
||||||
|
// update end ptr
|
||||||
|
_readPtr = readPtr;
|
||||||
|
_writePtr = writePtr;
|
||||||
|
|
||||||
|
// return pointer to unquoted string
|
||||||
|
return startPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ArduinoJson::Internals::JsonParser::parseStringTo(
|
||||||
|
JsonVariant *destination) {
|
||||||
|
bool hasQuotes = isQuote(_readPtr[0]);
|
||||||
|
const char *value = parseString();
|
||||||
|
if (value == NULL) return false;
|
||||||
|
if (hasQuotes) {
|
||||||
|
*destination = value;
|
||||||
|
} else {
|
||||||
|
*destination = RawJson(value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
@ -1,15 +1,23 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Configuration.hpp"
|
||||||
|
#include "DummyPrint.hpp"
|
||||||
#include "IndentedPrint.hpp"
|
#include "IndentedPrint.hpp"
|
||||||
#include "JsonWriter.hpp"
|
#include "JsonWriter.hpp"
|
||||||
#include "Prettyfier.hpp"
|
#include "Prettyfier.hpp"
|
||||||
#include "StringBuilder.hpp"
|
#include "StaticStringBuilder.hpp"
|
||||||
|
#include "DynamicStringBuilder.hpp"
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
|
#include "StreamPrintAdapter.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
namespace Internals {
|
namespace Internals {
|
||||||
@ -27,8 +35,21 @@ class JsonPrintable {
|
|||||||
return writer.bytesWritten();
|
return writer.bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 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 {
|
size_t printTo(char *buffer, size_t bufferSize) const {
|
||||||
StringBuilder sb(buffer, bufferSize);
|
StaticStringBuilder sb(buffer, bufferSize);
|
||||||
|
return printTo(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t printTo(String &str) const {
|
||||||
|
DynamicStringBuilder sb(str);
|
||||||
return printTo(sb);
|
return printTo(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +59,7 @@ class JsonPrintable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t prettyPrintTo(char *buffer, size_t bufferSize) const {
|
size_t prettyPrintTo(char *buffer, size_t bufferSize) const {
|
||||||
StringBuilder sb(buffer, bufferSize);
|
StaticStringBuilder sb(buffer, bufferSize);
|
||||||
return prettyPrintTo(sb);
|
return prettyPrintTo(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +68,30 @@ class JsonPrintable {
|
|||||||
return prettyPrintTo(indentedPrint);
|
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:
|
private:
|
||||||
const T &downcast() const { return *static_cast<const T *>(this); }
|
const T &downcast() const { return *static_cast<const T *>(this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
|
template <typename T>
|
||||||
|
inline std::ostream &operator<<(std::ostream &os, const JsonPrintable<T> &v) {
|
||||||
|
return v.printTo(os);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
45
include/ArduinoJson/Internals/JsonVariantAs.hpp
Normal file
45
include/ArduinoJson/Internals/JsonVariantAs.hpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,15 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonFloat.hpp"
|
||||||
|
#include "JsonInteger.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
@ -13,13 +17,11 @@ class JsonArray;
|
|||||||
class JsonObject;
|
class JsonObject;
|
||||||
|
|
||||||
namespace Internals {
|
namespace Internals {
|
||||||
|
|
||||||
// A union that defines the actual content of a JsonVariant.
|
// A union that defines the actual content of a JsonVariant.
|
||||||
// The enum JsonVariantType determines which member is in use.
|
// The enum JsonVariantType determines which member is in use.
|
||||||
union JsonVariantContent {
|
union JsonVariantContent {
|
||||||
bool asBoolean;
|
JsonFloat asFloat; // used for double and float
|
||||||
double asDouble; // asDouble is also used for float
|
JsonUInt asInteger; // used for bool, char, short, int and longs
|
||||||
long asLong; // asLong is also used for char, short and int
|
|
||||||
const char* asString; // asString can be null
|
const char* asString; // asString can be null
|
||||||
JsonArray* asArray; // asArray cannot be null
|
JsonArray* asArray; // asArray cannot be null
|
||||||
JsonObject* asObject; // asObject cannot be null
|
JsonObject* asObject; // asObject cannot be null
|
||||||
|
@ -1,32 +1,38 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
class JsonArray;
|
||||||
|
class JsonObject;
|
||||||
|
|
||||||
namespace Internals {
|
namespace Internals {
|
||||||
|
|
||||||
// Enumerated type to know the current type of a JsonVariant.
|
// Enumerated type to know the current type of a JsonVariant.
|
||||||
// The value determines which member of JsonVariantContent is used.
|
// The value determines which member of JsonVariantContent is used.
|
||||||
enum JsonVariantType {
|
enum JsonVariantType {
|
||||||
JSON_INVALID, // a special state for JsonVariant::invalid()
|
JSON_UNDEFINED, // JsonVariant has not been initialized
|
||||||
JSON_UNDEFINED, // the JsonVariant has not been initialized
|
JSON_UNPARSED, // JsonVariant contains an unparsed string
|
||||||
JSON_ARRAY, // the JsonVariant stores a pointer to a JsonArray
|
JSON_STRING, // JsonVariant stores a const char*
|
||||||
JSON_OBJECT, // the JsonVariant stores a pointer to a JsonObject
|
JSON_BOOLEAN, // JsonVariant stores a bool
|
||||||
JSON_BOOLEAN, // the JsonVariant stores a bool
|
JSON_POSITIVE_INTEGER, // JsonVariant stores an unsigned long
|
||||||
JSON_STRING, // the JsonVariant stores a const char*
|
JSON_NEGATIVE_INTEGER, // JsonVariant stores an unsigned long that must be
|
||||||
JSON_LONG, // the JsonVariant stores a long
|
// negated
|
||||||
|
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray
|
||||||
|
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
|
||||||
|
|
||||||
// The following values are reserved for double values
|
// The following values are reserved for float values
|
||||||
// Multiple values are used for double, depending on the number of decimal
|
// Multiple values are used for double, depending on the number of decimal
|
||||||
// digits that must be printed in the JSON output.
|
// digits that must be printed in the JSON output.
|
||||||
// This little trick allow to save one extra member in JsonVariant
|
// This little trick allow to save one extra member in JsonVariant
|
||||||
JSON_DOUBLE_0_DECIMALS
|
JSON_FLOAT_0_DECIMALS
|
||||||
// JSON_DOUBLE_1_DECIMAL
|
// JSON_FLOAT_1_DECIMAL
|
||||||
// JSON_DOUBLE_2_DECIMALS
|
// JSON_FLOAT_2_DECIMALS
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Arduino/Print.hpp"
|
#include "../Polyfills/attributes.hpp"
|
||||||
#include "QuotedString.hpp"
|
#include "../Polyfills/math.hpp"
|
||||||
|
#include "../Polyfills/normalize.hpp"
|
||||||
|
#include "../Print.hpp"
|
||||||
|
#include "Encoding.hpp"
|
||||||
|
#include "JsonFloat.hpp"
|
||||||
|
#include "JsonInteger.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
namespace Internals {
|
namespace Internals {
|
||||||
@ -26,39 +32,153 @@ class JsonWriter {
|
|||||||
// Returns the number of bytes sent to the Print implementation.
|
// Returns the number of bytes sent to the Print implementation.
|
||||||
// This is very handy for implementations of printTo() that must return the
|
// This is very handy for implementations of printTo() that must return the
|
||||||
// number of bytes written.
|
// number of bytes written.
|
||||||
size_t bytesWritten() { return _length; }
|
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 writeString(const char *value) {
|
|
||||||
_length += QuotedString::printTo(value, _sink);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeLong(long value) { _length += _sink.print(value); }
|
void beginArray() {
|
||||||
|
writeRaw('[');
|
||||||
|
}
|
||||||
|
void endArray() {
|
||||||
|
writeRaw(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
void beginObject() {
|
||||||
|
writeRaw('{');
|
||||||
|
}
|
||||||
|
void endObject() {
|
||||||
|
writeRaw('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeColon() {
|
||||||
|
writeRaw(':');
|
||||||
|
}
|
||||||
|
void writeComma() {
|
||||||
|
writeRaw(',');
|
||||||
|
}
|
||||||
|
|
||||||
void writeBoolean(bool value) {
|
void writeBoolean(bool value) {
|
||||||
_length += _sink.print(value ? "true" : "false");
|
writeRaw(value ? "true" : "false");
|
||||||
}
|
}
|
||||||
void writeDouble(double value, uint8_t decimals) {
|
|
||||||
_length += _sink.print(value, decimals);
|
void writeString(const char *value) {
|
||||||
|
if (!value) {
|
||||||
|
writeRaw("null");
|
||||||
|
} else {
|
||||||
|
writeRaw('\"');
|
||||||
|
while (*value) writeChar(*value++);
|
||||||
|
writeRaw('\"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeChar(char c) {
|
||||||
|
char specialChar = Encoding::escapeChar(c);
|
||||||
|
if (specialChar) {
|
||||||
|
writeRaw('\\');
|
||||||
|
writeRaw(specialChar);
|
||||||
|
} else {
|
||||||
|
writeRaw(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeFloat(JsonFloat value, uint8_t digits = 2) {
|
||||||
|
if (Polyfills::isNaN(value)) return writeRaw("NaN");
|
||||||
|
|
||||||
|
if (value < 0.0) {
|
||||||
|
writeRaw('-');
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Polyfills::isInfinity(value)) return writeRaw("Infinity");
|
||||||
|
|
||||||
|
short powersOf10;
|
||||||
|
if (value > 1000 || value < 0.001) {
|
||||||
|
powersOf10 = Polyfills::normalize(value);
|
||||||
|
} else {
|
||||||
|
powersOf10 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round up last digit (so that print(1.999, 2) prints as "2.00")
|
||||||
|
value += getRoundingBias(digits);
|
||||||
|
|
||||||
|
// Extract the integer part of the value and print it
|
||||||
|
JsonUInt int_part = static_cast<JsonUInt>(value);
|
||||||
|
JsonFloat remainder = value - static_cast<JsonFloat>(int_part);
|
||||||
|
writeInteger(int_part);
|
||||||
|
|
||||||
|
// Print the decimal point, but only if there are digits beyond
|
||||||
|
if (digits > 0) {
|
||||||
|
writeRaw('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract digits from the remainder one at a time
|
||||||
|
while (digits-- > 0) {
|
||||||
|
// Extract digit
|
||||||
|
remainder *= 10.0;
|
||||||
|
char currentDigit = char(remainder);
|
||||||
|
remainder -= static_cast<JsonFloat>(currentDigit);
|
||||||
|
|
||||||
|
// Print
|
||||||
|
writeRaw(char('0' + currentDigit));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (powersOf10 < 0) {
|
||||||
|
writeRaw("e-");
|
||||||
|
writeInteger(-powersOf10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (powersOf10 > 0) {
|
||||||
|
writeRaw('e');
|
||||||
|
writeInteger(powersOf10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeInteger(JsonUInt value) {
|
||||||
|
char buffer[22];
|
||||||
|
char *ptr = buffer + sizeof(buffer) - 1;
|
||||||
|
|
||||||
|
*ptr = 0;
|
||||||
|
do {
|
||||||
|
*--ptr = static_cast<char>(value % 10 + '0');
|
||||||
|
value /= 10;
|
||||||
|
} while (value);
|
||||||
|
|
||||||
|
writeRaw(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeRaw(const char *s) {
|
||||||
|
_length += _sink.print(s);
|
||||||
|
}
|
||||||
|
void writeRaw(char c) {
|
||||||
|
_length += _sink.write(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void write(char c) { _length += _sink.write(c); }
|
|
||||||
void write(const char *s) { _length += _sink.print(s); }
|
|
||||||
|
|
||||||
Print &_sink;
|
Print &_sink;
|
||||||
size_t _length;
|
size_t _length;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||||
|
|
||||||
|
static JsonFloat getLastDigit(uint8_t digits) {
|
||||||
|
// Designed as a compromise between code size and speed
|
||||||
|
switch (digits) {
|
||||||
|
case 0:
|
||||||
|
return 1e-0;
|
||||||
|
case 1:
|
||||||
|
return 1e-1;
|
||||||
|
case 2:
|
||||||
|
return 1e-2;
|
||||||
|
case 3:
|
||||||
|
return 1e-3;
|
||||||
|
default:
|
||||||
|
return getLastDigit(uint8_t(digits - 4)) * 1e-4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE static JsonFloat getRoundingBias(uint8_t digits) {
|
||||||
|
return 0.5 * getLastDigit(digits);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -35,35 +36,56 @@ class List {
|
|||||||
// Would return false in the following situation:
|
// Would return false in the following situation:
|
||||||
// - the memory allocation failed (StaticJsonBuffer was too small)
|
// - the memory allocation failed (StaticJsonBuffer was too small)
|
||||||
// - the JSON parsing failed
|
// - the JSON parsing failed
|
||||||
bool success() const { return _buffer != NULL; }
|
bool success() const {
|
||||||
|
return _buffer != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the numbers of elements in the list.
|
// Returns the numbers of elements in the list.
|
||||||
// For a JsonObject, it would return the number of key-value pairs
|
// For a JsonObject, it would return the number of key-value pairs
|
||||||
int size() const;
|
size_t size() const {
|
||||||
|
size_t nodeCount = 0;
|
||||||
iterator begin() { return iterator(_firstNode); }
|
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
|
||||||
iterator end() { return iterator(NULL); }
|
return nodeCount;
|
||||||
|
|
||||||
const_iterator begin() const { return const_iterator(_firstNode); }
|
|
||||||
const_iterator end() const { return const_iterator(NULL); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
node_type *createNode() {
|
|
||||||
if (!_buffer) return NULL;
|
|
||||||
return new (_buffer) node_type();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addNode(node_type *nodeToAdd) {
|
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() {
|
||||||
|
node_type *newNode = new (_buffer) node_type();
|
||||||
|
|
||||||
if (_firstNode) {
|
if (_firstNode) {
|
||||||
node_type *lastNode = _firstNode;
|
node_type *lastNode = _firstNode;
|
||||||
while (lastNode->next) lastNode = lastNode->next;
|
while (lastNode->next) lastNode = lastNode->next;
|
||||||
lastNode->next = nodeToAdd;
|
lastNode->next = newNode;
|
||||||
} else {
|
} else {
|
||||||
_firstNode = nodeToAdd;
|
_firstNode = newNode;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeNode(node_type *nodeToRemove);
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeNode(node_type *nodeToRemove) {
|
||||||
|
if (!nodeToRemove) return;
|
||||||
|
if (nodeToRemove == _firstNode) {
|
||||||
|
_firstNode = nodeToRemove->next;
|
||||||
|
} else {
|
||||||
|
for (node_type *node = _firstNode; node; node = node->next)
|
||||||
|
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonBuffer *_buffer;
|
JsonBuffer *_buffer;
|
||||||
node_type *_firstNode;
|
node_type *_firstNode;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
66
include/ArduinoJson/Internals/Parse.hpp
Normal file
66
include/ArduinoJson/Internals/Parse.hpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
template <typename TFloat>
|
||||||
|
TFloat parse(const char *);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline float parse<float>(const char *s) {
|
||||||
|
return static_cast<float>(strtod(s, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline double parse<double>(const char *s) {
|
||||||
|
return strtod(s, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline long parse<long>(const char *s) {
|
||||||
|
return strtol(s, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline unsigned long parse<unsigned long>(const char *s) {
|
||||||
|
return strtoul(s, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline int parse<int>(const char *s) {
|
||||||
|
return atoi(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
|
template <>
|
||||||
|
inline long long parse<long long>(const char *s) {
|
||||||
|
return strtoll(s, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline unsigned long long parse<unsigned long long>(const char *s) {
|
||||||
|
return strtoull(s, NULL, 10);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_USE_INT64
|
||||||
|
template <>
|
||||||
|
inline __int64 parse<__int64>(const char *s) {
|
||||||
|
return _strtoi64(s, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline unsigned __int64 parse<unsigned __int64>(const char *s) {
|
||||||
|
return _strtoui64(s, NULL, 10);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -19,24 +20,89 @@ class Prettyfier : public Print {
|
|||||||
_inString = false;
|
_inString = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t write(uint8_t);
|
virtual size_t write(uint8_t c) {
|
||||||
|
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c);
|
||||||
|
_previousChar = c;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
|
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
|
||||||
|
|
||||||
bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; }
|
bool inEmptyBlock() {
|
||||||
|
return _previousChar == '{' || _previousChar == '[';
|
||||||
|
}
|
||||||
|
|
||||||
size_t handleStringChar(uint8_t);
|
size_t handleStringChar(uint8_t c) {
|
||||||
size_t handleMarkupChar(uint8_t);
|
bool isQuote = c == '"' && _previousChar != '\\';
|
||||||
|
|
||||||
size_t handleBlockClose(uint8_t);
|
if (isQuote) _inString = false;
|
||||||
size_t handleBlockOpen(uint8_t);
|
|
||||||
size_t handleColumn();
|
return _sink.write(c);
|
||||||
size_t handleComma();
|
}
|
||||||
size_t handleQuoteOpen();
|
|
||||||
size_t handleNormalChar(uint8_t);
|
size_t handleMarkupChar(uint8_t c) {
|
||||||
size_t indentIfNeeded();
|
switch (c) {
|
||||||
size_t unindentIfNeeded();
|
case '{':
|
||||||
|
case '[':
|
||||||
|
return writeBlockOpen(c);
|
||||||
|
|
||||||
|
case '}':
|
||||||
|
case ']':
|
||||||
|
return writeBlockClose(c);
|
||||||
|
|
||||||
|
case ':':
|
||||||
|
return writeColon();
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
return writeComma();
|
||||||
|
|
||||||
|
case '"':
|
||||||
|
return writeQuoteOpen();
|
||||||
|
|
||||||
|
default:
|
||||||
|
return writeNormalChar(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t writeBlockClose(uint8_t c) {
|
||||||
|
return unindentIfNeeded() + _sink.write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t writeBlockOpen(uint8_t c) {
|
||||||
|
return indentIfNeeded() + _sink.write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t writeColon() {
|
||||||
|
return _sink.write(':') + _sink.write(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t writeComma() {
|
||||||
|
return _sink.write(',') + _sink.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t writeQuoteOpen() {
|
||||||
|
_inString = true;
|
||||||
|
return indentIfNeeded() + _sink.write('"');
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t writeNormalChar(uint8_t c) {
|
||||||
|
return indentIfNeeded() + _sink.write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t indentIfNeeded() {
|
||||||
|
if (!inEmptyBlock()) return 0;
|
||||||
|
|
||||||
|
_sink.indent();
|
||||||
|
return _sink.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t unindentIfNeeded() {
|
||||||
|
if (inEmptyBlock()) return 0;
|
||||||
|
|
||||||
|
_sink.unindent();
|
||||||
|
return _sink.println();
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t _previousChar;
|
uint8_t _previousChar;
|
||||||
IndentedPrint& _sink;
|
IndentedPrint& _sink;
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../Arduino/Print.hpp"
|
|
||||||
|
|
||||||
namespace ArduinoJson {
|
|
||||||
namespace Internals {
|
|
||||||
|
|
||||||
// An helper class to print and extract doubly-quoted strings
|
|
||||||
class QuotedString {
|
|
||||||
public:
|
|
||||||
// Writes a doubly-quote string to a Print implementation.
|
|
||||||
// It adds the double quotes (") at the beginning and the end of the string.
|
|
||||||
// It escapes the special characters as required by the JSON specifications.
|
|
||||||
static size_t printTo(const char *, Print &);
|
|
||||||
|
|
||||||
// Reads a doubly-quoted string from a buffer.
|
|
||||||
// It removes the double quotes (").
|
|
||||||
// It unescapes the special character as required by the JSON specification,
|
|
||||||
// with the exception of the Unicode characters (\u0000).
|
|
||||||
static char *extractFrom(char *input, char **end);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
37
include/ArduinoJson/Internals/StaticStringBuilder.hpp
Normal file
37
include/ArduinoJson/Internals/StaticStringBuilder.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Print.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Internals {
|
||||||
|
|
||||||
|
// A Print implementation that allows to write in a char[]
|
||||||
|
class StaticStringBuilder : public Print {
|
||||||
|
public:
|
||||||
|
StaticStringBuilder(char *buf, size_t size)
|
||||||
|
: buffer(buf), capacity(size - 1), length(0) {
|
||||||
|
buffer[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t write(uint8_t c) {
|
||||||
|
if (length >= capacity) return 0;
|
||||||
|
|
||||||
|
buffer[length++] = c;
|
||||||
|
buffer[length] = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char *buffer;
|
||||||
|
size_t capacity;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
39
include/ArduinoJson/Internals/StreamPrintAdapter.hpp
Normal file
39
include/ArduinoJson/Internals/StreamPrintAdapter.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Configuration.hpp"
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
|
|
||||||
|
#include "../Print.hpp"
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
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,30 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../Arduino/Print.hpp"
|
|
||||||
|
|
||||||
namespace ArduinoJson {
|
|
||||||
namespace Internals {
|
|
||||||
|
|
||||||
// A Print implementation that allows to write in a char[]
|
|
||||||
class StringBuilder : public Print {
|
|
||||||
public:
|
|
||||||
StringBuilder(char *buf, int size)
|
|
||||||
: buffer(buf), capacity(size - 1), length(0) {
|
|
||||||
buffer[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual size_t write(uint8_t c);
|
|
||||||
|
|
||||||
private:
|
|
||||||
char *buffer;
|
|
||||||
int capacity;
|
|
||||||
int length;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -11,6 +12,10 @@
|
|||||||
#include "Internals/List.hpp"
|
#include "Internals/List.hpp"
|
||||||
#include "Internals/ReferenceType.hpp"
|
#include "Internals/ReferenceType.hpp"
|
||||||
#include "JsonVariant.hpp"
|
#include "JsonVariant.hpp"
|
||||||
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
|
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||||
|
#include "TypeTraits/IsReference.hpp"
|
||||||
|
#include "TypeTraits/IsSame.hpp"
|
||||||
|
|
||||||
// Returns the size (in bytes) of an array with n elements.
|
// Returns the size (in bytes) of an array with n elements.
|
||||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||||
@ -22,6 +27,7 @@ namespace ArduinoJson {
|
|||||||
// Forward declarations
|
// Forward declarations
|
||||||
class JsonObject;
|
class JsonObject;
|
||||||
class JsonBuffer;
|
class JsonBuffer;
|
||||||
|
class JsonArraySubscript;
|
||||||
|
|
||||||
// An array of JsonVariant.
|
// An array of JsonVariant.
|
||||||
//
|
//
|
||||||
@ -33,35 +39,115 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
public Internals::ReferenceType,
|
public Internals::ReferenceType,
|
||||||
public Internals::List<JsonVariant>,
|
public Internals::List<JsonVariant>,
|
||||||
public Internals::JsonBufferAllocated {
|
public Internals::JsonBufferAllocated {
|
||||||
// JsonBuffer is a friend because it needs to call the private constructor.
|
|
||||||
friend class JsonBuffer;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Returns the JsonVariant at the specified index (synonym for operator[])
|
// A meta-function that returns true if type T can be used in
|
||||||
JsonVariant &at(int index) const;
|
// JsonArray::set()
|
||||||
|
|
||||||
// Returns the JsonVariant at the specified index (synonym for at())
|
|
||||||
JsonVariant &operator[](int index) const { return at(index); }
|
|
||||||
|
|
||||||
// Adds an uninitialized JsonVariant at the end of the array.
|
|
||||||
// Return a reference or JsonVariant::invalid() if allocation fails.
|
|
||||||
JsonVariant &add();
|
|
||||||
|
|
||||||
// Adds the specified value at the end of the array.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void add(T value) {
|
struct CanSet {
|
||||||
add().set(value);
|
static const bool value = JsonVariant::IsConstructibleFrom<T>::value ||
|
||||||
|
TypeTraits::IsSame<T, String &>::value ||
|
||||||
|
TypeTraits::IsSame<T, const String &>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
JsonVariant operator[](size_t index) const {
|
||||||
|
return get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds the specified double value at the end of the array.
|
// Gets or sets the value at specified index
|
||||||
// The value will be printed with the specified number of decimal digits.
|
JsonArraySubscript operator[](size_t index);
|
||||||
void add(double value, uint8_t decimals) { add().set(value, decimals); }
|
|
||||||
|
|
||||||
// Adds a reference to the specified JsonArray at the end of the array.
|
// Adds the specified value at the end of the array.
|
||||||
void add(JsonArray &array) { add().set(array); }
|
//
|
||||||
|
// bool add(bool);
|
||||||
|
// bool add(char);
|
||||||
|
// bool add(long);
|
||||||
|
// bool add(int);
|
||||||
|
// bool add(short);
|
||||||
|
// bool add(float value);
|
||||||
|
// bool add(double value);
|
||||||
|
// bool add(const char*);
|
||||||
|
template <typename T>
|
||||||
|
bool add(
|
||||||
|
T value,
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) {
|
||||||
|
return addNode<T>(value);
|
||||||
|
}
|
||||||
|
// bool add(const String&)
|
||||||
|
// bool add(const JsonVariant&);
|
||||||
|
// bool add(JsonArray&);
|
||||||
|
// bool add(JsonObject&);
|
||||||
|
template <typename T>
|
||||||
|
bool add(const T &value,
|
||||||
|
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
|
||||||
|
return addNode<T &>(const_cast<T &>(value));
|
||||||
|
}
|
||||||
|
// bool add(float value, uint8_t decimals);
|
||||||
|
// bool add(double value, uint8_t decimals);
|
||||||
|
template <typename T>
|
||||||
|
bool add(T value, uint8_t decimals,
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
||||||
|
return addNode<JsonVariant>(JsonVariant(value, decimals));
|
||||||
|
}
|
||||||
|
|
||||||
// Adds a reference to the specified JsonObject at the end of the array.
|
// Sets the value at specified index.
|
||||||
void add(JsonObject &obejct) { add().set(obejct); }
|
//
|
||||||
|
// bool set(size_t index, bool value);
|
||||||
|
// bool set(size_t index, long value);
|
||||||
|
// bool set(size_t index, int value);
|
||||||
|
// bool set(size_t index, short value);
|
||||||
|
template <typename T>
|
||||||
|
bool set(
|
||||||
|
size_t index, T value,
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type * = 0) {
|
||||||
|
return setNodeAt<T>(index, value);
|
||||||
|
}
|
||||||
|
// bool set(size_t index, const String&)
|
||||||
|
// bool set(size_t index, const JsonVariant&);
|
||||||
|
// bool set(size_t index, JsonArray&);
|
||||||
|
// bool set(size_t index, JsonObject&);
|
||||||
|
template <typename T>
|
||||||
|
bool set(size_t index, const T &value,
|
||||||
|
typename TypeTraits::EnableIf<CanSet<T &>::value>::type * = 0) {
|
||||||
|
return setNodeAt<T &>(index, const_cast<T &>(value));
|
||||||
|
}
|
||||||
|
// bool set(size_t index, float value, uint8_t decimals = 2);
|
||||||
|
// bool set(size_t index, double value, uint8_t decimals = 2);
|
||||||
|
template <typename T>
|
||||||
|
bool set(size_t index, T value, uint8_t decimals,
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
||||||
|
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the value at the specified index.
|
||||||
|
JsonVariant get(size_t index) const {
|
||||||
|
node_type *node = getNodeAt(index);
|
||||||
|
return node ? node->content : JsonVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the value at the specified index.
|
||||||
|
template <typename T>
|
||||||
|
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
|
||||||
|
node_type *node = getNodeAt(index);
|
||||||
|
return node ? node->content.as<T>() : JsonVariant::defaultValue<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the type of the value at specified index.
|
||||||
|
template <typename T>
|
||||||
|
bool is(size_t index) const {
|
||||||
|
node_type *node = getNodeAt(index);
|
||||||
|
return node ? node->content.is<T>() : false;
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a JsonArray and adds a reference at the end of the array.
|
// Creates a JsonArray and adds a reference at the end of the array.
|
||||||
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
|
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
|
||||||
@ -72,24 +158,111 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
|||||||
JsonObject &createNestedObject();
|
JsonObject &createNestedObject();
|
||||||
|
|
||||||
// Removes element at specified index.
|
// Removes element at specified index.
|
||||||
void removeAt(int index);
|
void removeAt(size_t index) {
|
||||||
|
removeNode(getNodeAt(index));
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a reference an invalid JsonArray.
|
// Returns a reference an invalid JsonArray.
|
||||||
// This object is meant to replace a NULL pointer.
|
// This object is meant to replace a NULL pointer.
|
||||||
// This is used when memory allocation or JSON parsing fail.
|
// This is used when memory allocation or JSON parsing fail.
|
||||||
static JsonArray &invalid() { return _invalid; }
|
static JsonArray &invalid() {
|
||||||
|
static JsonArray instance(NULL);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
// Serialize the array to the specified JsonWriter.
|
// Serialize the array to the specified JsonWriter.
|
||||||
void writeTo(Internals::JsonWriter &writer) const;
|
void writeTo(Internals::JsonWriter &writer) const {
|
||||||
|
writer.beginArray();
|
||||||
|
|
||||||
|
const node_type *child = _firstNode;
|
||||||
|
while (child) {
|
||||||
|
child->content.writeTo(writer);
|
||||||
|
|
||||||
|
child = child->next;
|
||||||
|
if (!child) break;
|
||||||
|
|
||||||
|
writer.writeComma();
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imports a 1D array
|
||||||
|
template <typename T, size_t N>
|
||||||
|
bool copyFrom(T(&array)[N]) {
|
||||||
|
return copyFrom(array, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imports a 1D array
|
||||||
|
template <typename T>
|
||||||
|
bool copyFrom(T *array, size_t len) {
|
||||||
|
bool ok = true;
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
ok &= add(array[i]);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imports a 2D array
|
||||||
|
template <typename T, size_t N1, size_t N2>
|
||||||
|
bool copyFrom(T(&array)[N1][N2]) {
|
||||||
|
bool ok = true;
|
||||||
|
for (size_t i = 0; i < N1; i++) {
|
||||||
|
JsonArray &nestedArray = createNestedArray();
|
||||||
|
for (size_t j = 0; j < N2; j++) {
|
||||||
|
ok &= nestedArray.add(array[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exports a 1D array
|
||||||
|
template <typename T, size_t N>
|
||||||
|
size_t copyTo(T(&array)[N]) const {
|
||||||
|
return copyTo(array, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exports a 1D array
|
||||||
|
template <typename T>
|
||||||
|
size_t copyTo(T *array, size_t len) const {
|
||||||
|
size_t i = 0;
|
||||||
|
for (const_iterator it = begin(); it != end() && i < len; ++it)
|
||||||
|
array[i++] = *it;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exports a 2D array
|
||||||
|
template <typename T, size_t N1, size_t N2>
|
||||||
|
void copyTo(T(&array)[N1][N2]) const {
|
||||||
|
size_t i = 0;
|
||||||
|
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
|
||||||
|
it->asArray().copyTo(array[i++]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
node_type *getNodeAt(size_t index) const {
|
||||||
explicit JsonArray(JsonBuffer *buffer)
|
node_type *node = _firstNode;
|
||||||
: Internals::List<JsonVariant>(buffer) {}
|
while (node && index--) node = node->next;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
node_type *getNodeAt(int index) const;
|
template <typename TValue>
|
||||||
|
bool setNodeAt(size_t index, TValue value) {
|
||||||
|
node_type *node = getNodeAt(index);
|
||||||
|
return node != NULL && setNodeValue<TValue>(node, value);
|
||||||
|
}
|
||||||
|
|
||||||
// The instance returned by JsonArray::invalid()
|
template <typename TValue>
|
||||||
static JsonArray _invalid;
|
bool addNode(TValue value) {
|
||||||
|
node_type *node = addNewNode();
|
||||||
|
return node != NULL && setNodeValue<TValue>(node, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool setNodeValue(node_type *node, T value) {
|
||||||
|
node->content = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
80
include/ArduinoJson/JsonArray.ipp
Normal file
80
include/ArduinoJson/JsonArray.ipp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonArray.hpp"
|
||||||
|
#include "JsonArraySubscript.hpp"
|
||||||
|
#include "JsonObject.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
inline JsonVariant::JsonVariant(JsonArray &array) {
|
||||||
|
if (array.success()) {
|
||||||
|
_type = Internals::JSON_ARRAY;
|
||||||
|
_content.asArray = &array;
|
||||||
|
} else {
|
||||||
|
_type = Internals::JSON_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JsonVariant::JsonVariant(JsonObject &object) {
|
||||||
|
if (object.success()) {
|
||||||
|
_type = Internals::JSON_OBJECT;
|
||||||
|
_content.asObject = &object;
|
||||||
|
} else {
|
||||||
|
_type = Internals::JSON_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool JsonArray::setNodeValue(node_type *node, String &value) {
|
||||||
|
const char *copy = _buffer->strdup(value);
|
||||||
|
if (!copy) return false;
|
||||||
|
node->content = copy;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline JsonArray &JsonVariant::defaultValue<JsonArray>() {
|
||||||
|
return JsonArray::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline JsonArray &JsonVariant::defaultValue<JsonArray &>() {
|
||||||
|
return JsonArray::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline const JsonArray &JsonVariant::defaultValue<const JsonArray>() {
|
||||||
|
return JsonArray::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline const JsonArray &JsonVariant::defaultValue<const JsonArray &>() {
|
||||||
|
return JsonArray::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JsonArray &JsonVariant::asArray() const {
|
||||||
|
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
|
||||||
|
return JsonArray::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JsonArray &JsonArray::createNestedArray() {
|
||||||
|
if (!_buffer) return JsonArray::invalid();
|
||||||
|
JsonArray &array = _buffer->createArray();
|
||||||
|
add(array);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JsonArray &JsonObject::createNestedArray(JsonObjectKey key) {
|
||||||
|
if (!_buffer) return JsonArray::invalid();
|
||||||
|
JsonArray &array = _buffer->createArray();
|
||||||
|
setNodeAt<const JsonVariant &>(key, array);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
98
include/ArduinoJson/JsonArraySubscript.hpp
Normal file
98
include/ArduinoJson/JsonArraySubscript.hpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Configuration.hpp"
|
||||||
|
#include "JsonVariantBase.hpp"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4522)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||||
|
public:
|
||||||
|
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
|
||||||
|
: _array(array), _index(index) {}
|
||||||
|
|
||||||
|
JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
||||||
|
_array.set<const JsonVariant&>(_index, src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<JsonArray::CanSet<T&>::value,
|
||||||
|
JsonArraySubscript>::type&
|
||||||
|
operator=(const T& src) {
|
||||||
|
_array.set<T&>(_index, const_cast<T&>(src));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<JsonArray::CanSet<T>::value,
|
||||||
|
JsonArraySubscript>::type&
|
||||||
|
operator=(T src) {
|
||||||
|
_array.set<T>(_index, src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE bool success() const {
|
||||||
|
return _index < _array.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE operator JsonVariant() const {
|
||||||
|
return _array.get(_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
FORCE_INLINE typename Internals::JsonVariantAs<T>::type as() const {
|
||||||
|
return _array.get<T>(_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
FORCE_INLINE bool 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
|
inline std::ostream& operator<<(std::ostream& os,
|
||||||
|
const JsonArraySubscript& source) {
|
||||||
|
return source.printTo(os);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||||
|
return JsonArraySubscript(*this, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TImplem>
|
||||||
|
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
|
||||||
|
int index) const {
|
||||||
|
return asArray()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ArduinoJson
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
@ -1,17 +1,26 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h> // for size_t
|
#include <stddef.h> // for size_t
|
||||||
#include <stdint.h> // for uint8_t
|
#include <stdint.h> // for uint8_t
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "JsonVariant.hpp"
|
||||||
|
#include "String.hpp"
|
||||||
|
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#endif
|
||||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -55,6 +64,17 @@ class JsonBuffer {
|
|||||||
// allocation fails.
|
// allocation fails.
|
||||||
JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
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.
|
// Allocates and populate a JsonObject from a JSON string.
|
||||||
//
|
//
|
||||||
// The First argument is a pointer to the JSON string, the memory must be
|
// The First argument is a pointer to the JSON string, the memory must be
|
||||||
@ -67,21 +87,77 @@ class JsonBuffer {
|
|||||||
// allocation fails.
|
// allocation fails.
|
||||||
JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generalized version of parseArray() and parseObject(), also works for
|
||||||
|
// integral types.
|
||||||
|
JsonVariant parse(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
||||||
|
|
||||||
|
// Same with a const char*.
|
||||||
|
// With this overload, the JsonBuffer will make a copy of the string
|
||||||
|
JsonVariant parse(const char *json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||||
|
return parse(strdup(json), nesting);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as above with a String class
|
||||||
|
JsonVariant parse(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||||
|
return parse(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.
|
// Allocates n bytes in the JsonBuffer.
|
||||||
// Return a pointer to the allocated memory or NULL if allocation fails.
|
// Return a pointer to the allocated memory or NULL if allocation fails.
|
||||||
virtual void *alloc(size_t size) = 0;
|
virtual void *alloc(size_t size) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Preserve aligment if nessary
|
||||||
|
static FORCE_INLINE size_t round_size_up(size_t bytes) {
|
||||||
|
#if ARDUINOJSON_ENABLE_ALIGNMENT
|
||||||
|
const size_t x = sizeof(void *) - 1;
|
||||||
|
return (bytes + x) & ~x;
|
||||||
|
#else
|
||||||
|
return bytes;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char *strdup(const char *, size_t);
|
||||||
|
|
||||||
// Default value of nesting limit of parseArray() and parseObject().
|
// Default value of nesting limit of parseArray() and parseObject().
|
||||||
//
|
//
|
||||||
// The nesting limit is a contain on the level of nesting allowed in the JSON
|
// The nesting limit is a contain on the level of nesting allowed in the
|
||||||
|
// JSON
|
||||||
// string.
|
// string.
|
||||||
// If set to 0, only a flat array or objects can be parsed.
|
// 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
|
// If set to 1, the object can contain nested arrays or objects but only 1
|
||||||
// level deep.
|
// level deep.
|
||||||
// And bigger values will allow more level of nesting.
|
// And bigger values will allow more level of nesting.
|
||||||
//
|
//
|
||||||
// The purpose of this feature is to prevent stack overflow that could lead to
|
// The purpose of this feature is to prevent stack overflow that could
|
||||||
|
// lead to
|
||||||
// a security risk.
|
// a security risk.
|
||||||
static const uint8_t DEFAULT_LIMIT = 10;
|
static const uint8_t DEFAULT_LIMIT = 10;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
46
include/ArduinoJson/JsonBuffer.ipp
Normal file
46
include/ArduinoJson/JsonBuffer.ipp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Internals/JsonParser.hpp"
|
||||||
|
|
||||||
|
inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::createArray() {
|
||||||
|
JsonArray *ptr = new (this) JsonArray(this);
|
||||||
|
return ptr ? *ptr : JsonArray::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::createObject() {
|
||||||
|
JsonObject *ptr = new (this) JsonObject(this);
|
||||||
|
return ptr ? *ptr : JsonObject::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::parseArray(
|
||||||
|
char *json, uint8_t nestingLimit) {
|
||||||
|
Internals::JsonParser parser(this, json, nestingLimit);
|
||||||
|
return parser.parseArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::parseObject(
|
||||||
|
char *json, uint8_t nestingLimit) {
|
||||||
|
Internals::JsonParser parser(this, json, nestingLimit);
|
||||||
|
return parser.parseObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ArduinoJson::JsonVariant ArduinoJson::JsonBuffer::parse(
|
||||||
|
char *json, uint8_t nestingLimit) {
|
||||||
|
Internals::JsonParser parser(this, json, nestingLimit);
|
||||||
|
return parser.parseVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline char *ArduinoJson::JsonBuffer::strdup(const char *source,
|
||||||
|
size_t length) {
|
||||||
|
size_t size = length + 1;
|
||||||
|
char *dest = static_cast<char *>(alloc(size));
|
||||||
|
if (dest != NULL) memcpy(dest, source, size);
|
||||||
|
return dest;
|
||||||
|
}
|
@ -1,16 +1,22 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "String.hpp"
|
||||||
#include "Internals/JsonBufferAllocated.hpp"
|
#include "Internals/JsonBufferAllocated.hpp"
|
||||||
#include "Internals/JsonPrintable.hpp"
|
#include "Internals/JsonPrintable.hpp"
|
||||||
#include "Internals/List.hpp"
|
#include "Internals/List.hpp"
|
||||||
#include "Internals/ReferenceType.hpp"
|
#include "Internals/ReferenceType.hpp"
|
||||||
#include "JsonPair.hpp"
|
#include "JsonPair.hpp"
|
||||||
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
|
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||||
|
#include "TypeTraits/IsReference.hpp"
|
||||||
|
#include "TypeTraits/IsSame.hpp"
|
||||||
|
|
||||||
// Returns the size (in bytes) of an object with n elements.
|
// Returns the size (in bytes) of an object with n elements.
|
||||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||||
@ -33,75 +39,163 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
|||||||
public Internals::ReferenceType,
|
public Internals::ReferenceType,
|
||||||
public Internals::List<JsonPair>,
|
public Internals::List<JsonPair>,
|
||||||
public Internals::JsonBufferAllocated {
|
public Internals::JsonBufferAllocated {
|
||||||
// JsonBuffer is a friend because it needs to call the private constructor.
|
|
||||||
friend class JsonBuffer;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef const char *key_type;
|
// A meta-function that returns true if type T can be used in
|
||||||
typedef JsonPair value_type;
|
// JsonObject::set()
|
||||||
|
|
||||||
// Gets the JsonVariant associated with the specified key.
|
|
||||||
// Returns a reference or JsonVariant::invalid() if not found.
|
|
||||||
JsonVariant &at(key_type key);
|
|
||||||
|
|
||||||
// Gets the JsonVariant associated with the specified key.
|
|
||||||
// Returns a constant reference or JsonVariant::invalid() if not found.
|
|
||||||
const JsonVariant &at(key_type key) const;
|
|
||||||
|
|
||||||
// Gets or create the JsonVariant associated with the specified key.
|
|
||||||
// Returns a reference or JsonVariant::invalid() if allocation failed.
|
|
||||||
JsonVariant &operator[](key_type key);
|
|
||||||
|
|
||||||
// Gets the JsonVariant associated with the specified key.
|
|
||||||
// Returns a constant reference or JsonVariant::invalid() if not found.
|
|
||||||
const JsonVariant &operator[](key_type key) const { return at(key); }
|
|
||||||
|
|
||||||
// Adds an uninitialized JsonVariant associated with the specified key.
|
|
||||||
// Return a reference or JsonVariant::invalid() if allocation fails.
|
|
||||||
JsonVariant &add(key_type key) { return (*this)[key]; }
|
|
||||||
|
|
||||||
// Adds the specified key with the specified value.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void add(key_type key, T value) {
|
struct CanSet {
|
||||||
add(key).set(value);
|
static const bool value = JsonVariant::IsConstructibleFrom<T>::value ||
|
||||||
|
TypeTraits::IsSame<T, String&>::value ||
|
||||||
|
TypeTraits::IsSame<T, const String&>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||||
|
// You should not use this constructor directly.
|
||||||
|
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
|
||||||
|
explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {}
|
||||||
|
|
||||||
|
// Gets or sets the value associated with the specified key.
|
||||||
|
JsonObjectSubscript<const char*> operator[](const char* key);
|
||||||
|
JsonObjectSubscript<const String&> operator[](const String& key);
|
||||||
|
|
||||||
|
// Gets the value associated with the specified key.
|
||||||
|
JsonVariant operator[](JsonObjectKey key) const {
|
||||||
|
return get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds the specified key with a reference to the specified JsonArray.
|
// Sets the specified key with the specified value.
|
||||||
void add(key_type key, JsonArray &array) { add(key).set(array); }
|
// bool set(TKey key, bool value);
|
||||||
|
// bool set(TKey key, char value);
|
||||||
|
// bool set(TKey key, long value);
|
||||||
|
// bool set(TKey key, int value);
|
||||||
|
// bool set(TKey key, short value);
|
||||||
|
// bool set(TKey key, float value);
|
||||||
|
// bool set(TKey key, double value);
|
||||||
|
// bool set(TKey key, const char* value);
|
||||||
|
// bool set(TKey key, RawJson value);
|
||||||
|
template <typename T>
|
||||||
|
bool set(
|
||||||
|
JsonObjectKey key, T value,
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) {
|
||||||
|
return setNodeAt<T>(key, value);
|
||||||
|
}
|
||||||
|
// bool set(Key, String&);
|
||||||
|
// bool set(Key, JsonArray&);
|
||||||
|
// bool set(Key, JsonObject&);
|
||||||
|
// bool set(Key, JsonVariant&);
|
||||||
|
template <typename T>
|
||||||
|
bool set(JsonObjectKey key, const T& value,
|
||||||
|
typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) {
|
||||||
|
return setNodeAt<T&>(key, const_cast<T&>(value));
|
||||||
|
}
|
||||||
|
// bool set(Key, float value, uint8_t decimals);
|
||||||
|
// bool set(Key, double value, uint8_t decimals);
|
||||||
|
template <typename TValue>
|
||||||
|
bool set(JsonObjectKey key, TValue value, uint8_t decimals,
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) {
|
||||||
|
return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals));
|
||||||
|
}
|
||||||
|
|
||||||
// Adds the specified key with a reference to the specified JsonObject.
|
// Gets the value associated with the specified key.
|
||||||
void add(key_type key, JsonObject &object) { add(key).set(object); }
|
JsonVariant get(JsonObjectKey key) const {
|
||||||
|
node_type* node = getNodeAt(key.c_str());
|
||||||
|
return node ? node->content.value : JsonVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the value associated with the specified key.
|
||||||
|
template <typename T>
|
||||||
|
typename Internals::JsonVariantAs<T>::type get(JsonObjectKey key) const {
|
||||||
|
node_type* node = getNodeAt(key.c_str());
|
||||||
|
return node ? node->content.value.as<T>() : JsonVariant::defaultValue<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks the type of the value associated with the specified key.
|
||||||
|
template <typename T>
|
||||||
|
bool is(JsonObjectKey key) const {
|
||||||
|
node_type* node = getNodeAt(key.c_str());
|
||||||
|
return node ? node->content.value.is<T>() : false;
|
||||||
|
}
|
||||||
|
|
||||||
// Creates and adds a JsonArray.
|
// Creates and adds a JsonArray.
|
||||||
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
||||||
JsonArray &createNestedArray(key_type key);
|
JsonArray& createNestedArray(JsonObjectKey key);
|
||||||
|
|
||||||
// Creates and adds a JsonObject.
|
// Creates and adds a JsonObject.
|
||||||
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
||||||
JsonObject &createNestedObject(key_type key);
|
JsonObject& createNestedObject(JsonObjectKey key);
|
||||||
|
|
||||||
// Tells weither the specified key is present and associated with a value.
|
// Tells weither the specified key is present and associated with a value.
|
||||||
bool containsKey(key_type key) const { return at(key).success(); }
|
bool containsKey(JsonObjectKey key) const {
|
||||||
|
return getNodeAt(key.c_str()) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Removes the specified key and the associated value.
|
// Removes the specified key and the associated value.
|
||||||
void remove(key_type key);
|
void remove(JsonObjectKey key) {
|
||||||
|
removeNode(getNodeAt(key.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a reference an invalid JsonObject.
|
// Returns a reference an invalid JsonObject.
|
||||||
// This object is meant to replace a NULL pointer.
|
// This object is meant to replace a NULL pointer.
|
||||||
// This is used when memory allocation or JSON parsing fail.
|
// This is used when memory allocation or JSON parsing fail.
|
||||||
static JsonObject &invalid() { return _invalid; }
|
static JsonObject& invalid() {
|
||||||
|
static JsonObject instance(NULL);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
// Serialize the object to the specified JsonWriter
|
// Serialize the object to the specified JsonWriter
|
||||||
void writeTo(Internals::JsonWriter &writer) const;
|
void writeTo(Internals::JsonWriter& writer) const {
|
||||||
|
writer.beginObject();
|
||||||
|
|
||||||
|
const node_type* node = _firstNode;
|
||||||
|
while (node) {
|
||||||
|
writer.writeString(node->content.key);
|
||||||
|
writer.writeColon();
|
||||||
|
node->content.value.writeTo(writer);
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
if (!node) break;
|
||||||
|
|
||||||
|
writer.writeComma();
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
|
||||||
explicit JsonObject(JsonBuffer *buffer) : Internals::List<JsonPair>(buffer) {}
|
|
||||||
|
|
||||||
// Returns the list node that matches the specified key.
|
// Returns the list node that matches the specified key.
|
||||||
node_type *getNodeAt(key_type key) const;
|
node_type* getNodeAt(const char* key) const {
|
||||||
|
for (node_type* node = _firstNode; node; node = node->next) {
|
||||||
|
if (!strcmp(node->content.key, key)) return node;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// The instance returned by JsonObject::invalid()
|
template <typename T>
|
||||||
static JsonObject _invalid;
|
bool setNodeAt(JsonObjectKey key, T value) {
|
||||||
|
node_type* node = getNodeAt(key.c_str());
|
||||||
|
if (!node) {
|
||||||
|
node = addNewNode();
|
||||||
|
if (!node || !setNodeKey(node, key)) return false;
|
||||||
|
}
|
||||||
|
return setNodeValue<T>(node, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setNodeKey(node_type* node, JsonObjectKey key) {
|
||||||
|
if (key.needs_copy()) {
|
||||||
|
node->content.key = _buffer->strdup(key.c_str());
|
||||||
|
if (node->content.key == NULL) return false;
|
||||||
|
} else {
|
||||||
|
node->content.key = key.c_str();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool setNodeValue(node_type* node, T value) {
|
||||||
|
node->content.value = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
66
include/ArduinoJson/JsonObject.ipp
Normal file
66
include/ArduinoJson/JsonObject.ipp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonArray.hpp"
|
||||||
|
#include "JsonObject.hpp"
|
||||||
|
#include "JsonObjectSubscript.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool JsonObject::setNodeValue(node_type *node, String &value) {
|
||||||
|
node->content.value = _buffer->strdup(value);
|
||||||
|
return node->content.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool JsonObject::setNodeValue(node_type *node, const String &value) {
|
||||||
|
node->content.value = _buffer->strdup(value);
|
||||||
|
return node->content.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline const JsonObject &JsonVariant::defaultValue<const JsonObject &>() {
|
||||||
|
return JsonObject::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline const JsonObject &JsonVariant::defaultValue<const JsonObject>() {
|
||||||
|
return JsonObject::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline JsonObject &JsonVariant::defaultValue<JsonObject &>() {
|
||||||
|
return JsonObject::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline JsonObject &JsonVariant::defaultValue<JsonObject>() {
|
||||||
|
return JsonObject::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JsonObject &JsonVariant::asObject() const {
|
||||||
|
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
|
||||||
|
return JsonObject::invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JsonObject &JsonObject::createNestedObject(JsonObjectKey key) {
|
||||||
|
if (!_buffer) return JsonObject::invalid();
|
||||||
|
JsonObject &array = _buffer->createObject();
|
||||||
|
setNodeAt<const JsonVariant &>(key, array);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JsonObject &JsonArray::createNestedObject() {
|
||||||
|
if (!_buffer) return JsonObject::invalid();
|
||||||
|
JsonObject &object = _buffer->createObject();
|
||||||
|
add(object);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
27
include/ArduinoJson/JsonObjectKey.hpp
Normal file
27
include/ArduinoJson/JsonObjectKey.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "String.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
// Represents a key in a JsonObject
|
||||||
|
class JsonObjectKey {
|
||||||
|
public:
|
||||||
|
JsonObjectKey(const char* key) : _value(key), _needs_copy(false) {}
|
||||||
|
JsonObjectKey(const String& key) : _value(key.c_str()), _needs_copy(true) {}
|
||||||
|
|
||||||
|
const char* c_str() const { return _value; }
|
||||||
|
bool needs_copy() const { return _needs_copy; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* _value;
|
||||||
|
bool _needs_copy;
|
||||||
|
};
|
||||||
|
}
|
127
include/ArduinoJson/JsonObjectSubscript.hpp
Normal file
127
include/ArduinoJson/JsonObjectSubscript.hpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Configuration.hpp"
|
||||||
|
#include "JsonVariantBase.hpp"
|
||||||
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4522)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript<TKey> > {
|
||||||
|
public:
|
||||||
|
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key)
|
||||||
|
: _object(object), _key(key) {}
|
||||||
|
|
||||||
|
JsonObjectSubscript<TKey>& operator=(const JsonObjectSubscript<TKey>& src) {
|
||||||
|
_object.set<const JsonVariant&>(_key, src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<JsonObject::CanSet<T&>::value,
|
||||||
|
JsonObjectSubscript<TKey> >::type&
|
||||||
|
operator=(const T& src) {
|
||||||
|
_object.set<T&>(_key, const_cast<T&>(src));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<JsonObject::CanSet<T>::value,
|
||||||
|
JsonObjectSubscript<TKey> >::type&
|
||||||
|
operator=(T src) {
|
||||||
|
_object.set<T>(_key, src);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE bool success() const {
|
||||||
|
return _object.containsKey(_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE operator JsonVariant() const {
|
||||||
|
return _object.get(_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TValue>
|
||||||
|
FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type as() const {
|
||||||
|
return _object.get<TValue>(_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TValue>
|
||||||
|
FORCE_INLINE bool is() const {
|
||||||
|
return _object.is<TValue>(_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TValue>
|
||||||
|
FORCE_INLINE bool set(TValue value) {
|
||||||
|
return _object.set<TValue>(_key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TValue>
|
||||||
|
FORCE_INLINE bool set(TValue value, uint8_t decimals) {
|
||||||
|
return _object.set(_key, value, decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE JsonVariant get() {
|
||||||
|
return _object.get(_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeTo(Internals::JsonWriter& writer) const {
|
||||||
|
_object.get(_key).writeTo(writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JsonObject& _object;
|
||||||
|
TKey _key;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 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
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ArduinoJson
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
@ -1,11 +1,13 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonObjectKey.hpp"
|
||||||
#include "JsonVariant.hpp"
|
#include "JsonVariant.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -12,6 +13,14 @@
|
|||||||
#include "Internals/JsonPrintable.hpp"
|
#include "Internals/JsonPrintable.hpp"
|
||||||
#include "Internals/JsonVariantContent.hpp"
|
#include "Internals/JsonVariantContent.hpp"
|
||||||
#include "Internals/JsonVariantType.hpp"
|
#include "Internals/JsonVariantType.hpp"
|
||||||
|
#include "JsonVariantBase.hpp"
|
||||||
|
#include "RawJson.hpp"
|
||||||
|
#include "TypeTraits/EnableIf.hpp"
|
||||||
|
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||||
|
#include "TypeTraits/IsIntegral.hpp"
|
||||||
|
#include "TypeTraits/IsSame.hpp"
|
||||||
|
#include "TypeTraits/RemoveConst.hpp"
|
||||||
|
#include "TypeTraits/RemoveReference.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
|
||||||
@ -26,152 +35,297 @@ class JsonObject;
|
|||||||
// - a char, short, int or a long (signed or unsigned)
|
// - a char, short, int or a long (signed or unsigned)
|
||||||
// - a string (const char*)
|
// - a string (const char*)
|
||||||
// - a reference to a JsonArray or JsonObject
|
// - a reference to a JsonArray or JsonObject
|
||||||
class JsonVariant : public Internals::JsonPrintable<JsonVariant> {
|
class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||||
public:
|
public:
|
||||||
|
template <typename T>
|
||||||
|
struct IsConstructibleFrom;
|
||||||
|
|
||||||
// Creates an uninitialized JsonVariant
|
// Creates an uninitialized JsonVariant
|
||||||
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||||
|
|
||||||
// Initializes a JsonVariant with the specified value.
|
// Create a JsonVariant containing a boolean value.
|
||||||
template <typename T>
|
|
||||||
explicit JsonVariant(T value) {
|
|
||||||
set(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tells weither the variant is valid.
|
|
||||||
bool success() const {
|
|
||||||
return _type != Internals::JSON_INVALID &&
|
|
||||||
_type != Internals::JSON_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the variant to a boolean value.
|
|
||||||
// It will be serialized as "true" or "false" in JSON.
|
// It will be serialized as "true" or "false" in JSON.
|
||||||
void set(bool value);
|
JsonVariant(bool value) {
|
||||||
|
using namespace Internals;
|
||||||
|
_type = JSON_BOOLEAN;
|
||||||
|
_content.asInteger = static_cast<JsonInteger>(value);
|
||||||
|
}
|
||||||
|
|
||||||
// Sets the variant to a floating point value.
|
// Create a JsonVariant containing a floating point value.
|
||||||
// The second argument specifies the number of decimal digits to write in
|
// The second argument specifies the number of decimal digits to write in
|
||||||
// the JSON string.
|
// the JSON string.
|
||||||
void set(double value, uint8_t decimals = 2);
|
// JsonVariant(double value, uint8_t decimals);
|
||||||
|
// JsonVariant(float value, uint8_t decimals);
|
||||||
// Sets the variant to be an integer value.
|
|
||||||
void set(signed long value);
|
|
||||||
void set(signed char value) { set(static_cast<long>(value)); }
|
|
||||||
void set(signed int value) { set(static_cast<long>(value)); }
|
|
||||||
void set(signed short value) { set(static_cast<long>(value)); }
|
|
||||||
void set(unsigned char value) { set(static_cast<long>(value)); }
|
|
||||||
void set(unsigned int value) { set(static_cast<long>(value)); }
|
|
||||||
void set(unsigned long value) { set(static_cast<long>(value)); }
|
|
||||||
void set(unsigned short value) { set(static_cast<long>(value)); }
|
|
||||||
|
|
||||||
// Sets the variant to be a string.
|
|
||||||
void set(const char *value);
|
|
||||||
|
|
||||||
// Sets the variant to be a reference to an array.
|
|
||||||
void set(JsonArray &array);
|
|
||||||
|
|
||||||
// Sets the variant to be a reference to an object.
|
|
||||||
void set(JsonObject &object);
|
|
||||||
|
|
||||||
// Sets the variant to the specified value.
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
JsonVariant &operator=(T value) {
|
JsonVariant(T value, uint8_t decimals = 2,
|
||||||
set(value);
|
typename TypeTraits::EnableIf<
|
||||||
return *this;
|
TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
|
||||||
|
using namespace Internals;
|
||||||
|
_type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals);
|
||||||
|
_content.asFloat = static_cast<JsonFloat>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the variant to be a reference to an array.
|
// Create a JsonVariant containing an integer value.
|
||||||
JsonVariant &operator=(JsonArray &array) {
|
// JsonVariant(signed short)
|
||||||
set(array);
|
// JsonVariant(signed int)
|
||||||
return *this;
|
// JsonVariant(signed long)
|
||||||
|
template <typename T>
|
||||||
|
JsonVariant(T value,
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsSignedIntegral<T>::value>::type * = 0) {
|
||||||
|
using namespace Internals;
|
||||||
|
if (value >= 0) {
|
||||||
|
_type = JSON_POSITIVE_INTEGER;
|
||||||
|
_content.asInteger = static_cast<JsonUInt>(value);
|
||||||
|
} else {
|
||||||
|
_type = JSON_NEGATIVE_INTEGER;
|
||||||
|
_content.asInteger = static_cast<JsonUInt>(-value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// JsonVariant(unsigned short)
|
||||||
|
// JsonVariant(unsigned int)
|
||||||
|
// JsonVariant(unsigned long)
|
||||||
|
template <typename T>
|
||||||
|
JsonVariant(T value,
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsUnsignedIntegral<T>::value>::type * = 0) {
|
||||||
|
using namespace Internals;
|
||||||
|
_type = JSON_POSITIVE_INTEGER;
|
||||||
|
_content.asInteger = static_cast<JsonUInt>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the variant to be a reference to an object.
|
// Create a JsonVariant containing a string.
|
||||||
JsonVariant &operator=(JsonObject &object) {
|
JsonVariant(const char *value) {
|
||||||
set(object);
|
_type = Internals::JSON_STRING;
|
||||||
return *this;
|
_content.asString = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the variant as a boolean value.
|
// Create a JsonVariant containing an unparsed string
|
||||||
// Returns false if the variant is not a boolean value.
|
JsonVariant(RawJson value) {
|
||||||
operator bool() const;
|
_type = Internals::JSON_UNPARSED;
|
||||||
|
_content.asString = value;
|
||||||
|
}
|
||||||
|
|
||||||
// Gets the variant as a floating-point value.
|
// Create a JsonVariant containing a reference to an array.
|
||||||
// Returns 0.0 if the variant is not a floating-point value
|
JsonVariant(JsonArray &array);
|
||||||
operator double() const;
|
|
||||||
operator float() const { return static_cast<float>(as<double>()); }
|
|
||||||
|
|
||||||
// Gets the variant as an integer value.
|
// Create a JsonVariant containing a reference to an object.
|
||||||
// Returns 0 if the variant is not an integer value.
|
JsonVariant(JsonObject &object);
|
||||||
operator signed long() const;
|
|
||||||
operator signed char() const { return cast_long_to<signed char>(); }
|
|
||||||
operator signed int() const { return cast_long_to<signed int>(); }
|
|
||||||
operator signed short() const { return cast_long_to<signed short>(); }
|
|
||||||
operator unsigned char() const { return cast_long_to<unsigned char>(); }
|
|
||||||
operator unsigned int() const { return cast_long_to<unsigned int>(); }
|
|
||||||
operator unsigned long() const { return cast_long_to<unsigned long>(); }
|
|
||||||
operator unsigned short() const { return cast_long_to<unsigned short>(); }
|
|
||||||
|
|
||||||
// Gets the variant as a string.
|
|
||||||
// Returns NULL if variant is not a string.
|
|
||||||
operator const char *() const;
|
|
||||||
const char *asString() const { return as<const char *>(); }
|
|
||||||
|
|
||||||
// Gets the variant as an array.
|
|
||||||
// Returns a reference to the JsonArray or JsonArray::invalid() if the variant
|
|
||||||
// is not an array.
|
|
||||||
operator JsonArray &() const;
|
|
||||||
JsonArray &asArray() const { return as<JsonArray &>(); }
|
|
||||||
|
|
||||||
// Gets the variant as an object.
|
|
||||||
// Returns a reference to the JsonObject or JsonObject::invalid() if the
|
|
||||||
// variant is not an object.
|
|
||||||
operator JsonObject &() const;
|
|
||||||
JsonObject &asObject() const { return as<JsonObject &>(); }
|
|
||||||
|
|
||||||
// Get the variant as the specified type.
|
// Get the variant as the specified type.
|
||||||
// See cast operators for details.
|
//
|
||||||
|
// short as<signed short>() const;
|
||||||
|
// int as<signed int>() const;
|
||||||
|
// long as<signed long>() const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T as() const {
|
const typename TypeTraits::EnableIf<TypeTraits::IsSignedIntegral<T>::value,
|
||||||
return static_cast<T>(*this);
|
T>::type
|
||||||
|
as() const {
|
||||||
|
return static_cast<T>(asInteger());
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// short as<unsigned short>() const;
|
||||||
|
// int as<unsigned int>() const;
|
||||||
|
// long as<unsigned long>() const;
|
||||||
|
template <typename T>
|
||||||
|
const typename TypeTraits::EnableIf<TypeTraits::IsUnsignedIntegral<T>::value,
|
||||||
|
T>::type
|
||||||
|
as() const {
|
||||||
|
return static_cast<T>(asUnsignedInteger());
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// double as<double>() const;
|
||||||
|
// float as<float>() const;
|
||||||
|
template <typename T>
|
||||||
|
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||||
|
T>::type
|
||||||
|
as() const {
|
||||||
|
return static_cast<T>(asFloat());
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// const String as<String>() const;
|
||||||
|
template <typename T>
|
||||||
|
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, String>::value,
|
||||||
|
T>::type
|
||||||
|
as() const {
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// const char* as<const char*>() const;
|
||||||
|
// const char* as<char*>() const;
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value ||
|
||||||
|
TypeTraits::IsSame<T, char *>::value,
|
||||||
|
const char *>::type
|
||||||
|
as() const {
|
||||||
|
return asString();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// const bool as<bool>() const
|
||||||
|
template <typename T>
|
||||||
|
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
||||||
|
T>::type
|
||||||
|
as() const {
|
||||||
|
return asInteger() != 0;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// JsonArray& as<JsonArray> const;
|
||||||
|
// JsonArray& as<JsonArray&> const;
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
|
||||||
|
JsonArray>::value,
|
||||||
|
JsonArray &>::type
|
||||||
|
as() const {
|
||||||
|
return asArray();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// const JsonArray& as<const JsonArray&> const;
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
|
||||||
|
const JsonArray>::value,
|
||||||
|
const JsonArray &>::type
|
||||||
|
as() const {
|
||||||
|
return asArray();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// JsonObject& as<JsonObject> const;
|
||||||
|
// JsonObject& as<JsonObject&> const;
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
|
||||||
|
JsonObject>::value,
|
||||||
|
JsonObject &>::type
|
||||||
|
as() const {
|
||||||
|
return asObject();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// JsonObject& as<const JsonObject> const;
|
||||||
|
// JsonObject& as<const JsonObject&> const;
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
|
||||||
|
const JsonObject>::value,
|
||||||
|
const JsonObject &>::type
|
||||||
|
as() const {
|
||||||
|
return asObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tells weither the variant has the specified type.
|
// Tells weither the variant has the specified type.
|
||||||
// Returns true if the variant has type type T, false otherwise.
|
// Returns true if the variant has type type T, false otherwise.
|
||||||
|
//
|
||||||
|
// short as<short>() const;
|
||||||
|
// int as<int>() const;
|
||||||
|
// long as<long>() const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool is() const {
|
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value,
|
||||||
return false;
|
bool>::type
|
||||||
|
is() const {
|
||||||
|
return isInteger();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// double is<double>() const;
|
||||||
|
// float is<float>() const;
|
||||||
|
template <typename T>
|
||||||
|
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||||
|
bool>::type
|
||||||
|
is() const {
|
||||||
|
return isFloat();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// const bool is<bool>() const
|
||||||
|
template <typename T>
|
||||||
|
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
||||||
|
bool>::type
|
||||||
|
is() const {
|
||||||
|
return isBoolean();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// bool is<const char*>() const;
|
||||||
|
// bool is<char*>() const;
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value ||
|
||||||
|
TypeTraits::IsSame<T, char *>::value,
|
||||||
|
bool>::type
|
||||||
|
is() const {
|
||||||
|
return isString();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// bool is<JsonArray> const;
|
||||||
|
// bool is<JsonArray&> const;
|
||||||
|
// bool is<const JsonArray&> const;
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsSame<
|
||||||
|
typename TypeTraits::RemoveConst<
|
||||||
|
typename TypeTraits::RemoveReference<T>::type>::type,
|
||||||
|
JsonArray>::value,
|
||||||
|
bool>::type
|
||||||
|
is() const {
|
||||||
|
return isArray();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// JsonObject& as<JsonObject> const;
|
||||||
|
// JsonObject& as<JsonObject&> const;
|
||||||
|
// JsonObject& as<const JsonObject&> const;
|
||||||
|
template <typename T>
|
||||||
|
typename TypeTraits::EnableIf<
|
||||||
|
TypeTraits::IsSame<
|
||||||
|
typename TypeTraits::RemoveConst<
|
||||||
|
typename TypeTraits::RemoveReference<T>::type>::type,
|
||||||
|
JsonObject>::value,
|
||||||
|
bool>::type
|
||||||
|
is() const {
|
||||||
|
return isObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an invalid variant.
|
// Returns true if the variant has a value
|
||||||
// This is meant to replace a NULL pointer.
|
bool success() const {
|
||||||
static JsonVariant &invalid() { return _invalid; }
|
return _type != Internals::JSON_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
// Serialize the variant to a JsonWriter
|
// Serialize the variant to a JsonWriter
|
||||||
void writeTo(Internals::JsonWriter &writer) const;
|
void writeTo(Internals::JsonWriter &writer) const;
|
||||||
|
|
||||||
// Mimics an array or an object.
|
// Value returned if the variant has an incompatible type
|
||||||
// Returns the size of the array or object if the variant has that type.
|
template <typename T>
|
||||||
// Returns 0 if the variant is neither an array nor an object
|
static typename Internals::JsonVariantAs<T>::type defaultValue() {
|
||||||
size_t size() const;
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
// Mimics an array.
|
// DEPRECATED: use as<char*>() instead
|
||||||
// Returns the element at specified index if the variant is an array.
|
const char *asString() const;
|
||||||
// Returns JsonVariant::invalid() if the variant is not an array.
|
|
||||||
JsonVariant &operator[](int index);
|
|
||||||
|
|
||||||
// Mimics an object.
|
// DEPRECATED: use as<JsonArray>() instead
|
||||||
// Returns the value associated with the specified key if the variant is an
|
JsonArray &asArray() const;
|
||||||
// object.
|
|
||||||
// Return JsonVariant::invalid() if the variant is not an object.
|
// DEPRECATED: use as<JsonObject>() instead
|
||||||
JsonVariant &operator[](const char *key);
|
JsonObject &asObject() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Special constructor used only to create _invalid.
|
// It's not allowed to store a char
|
||||||
explicit JsonVariant(Internals::JsonVariantType type) : _type(type) {}
|
|
||||||
|
|
||||||
// Helper for interger cast operators
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T cast_long_to() const {
|
JsonVariant(T value, typename TypeTraits::EnableIf<
|
||||||
return static_cast<T>(as<long>());
|
TypeTraits::IsSame<T, char>::value>::type * = 0);
|
||||||
|
|
||||||
|
String toString() const;
|
||||||
|
Internals::JsonFloat asFloat() const;
|
||||||
|
Internals::JsonInteger asInteger() const;
|
||||||
|
Internals::JsonUInt asUnsignedInteger() const;
|
||||||
|
bool isBoolean() const;
|
||||||
|
bool isFloat() const;
|
||||||
|
bool isInteger() const;
|
||||||
|
bool isArray() const {
|
||||||
|
return _type == Internals::JSON_ARRAY;
|
||||||
|
}
|
||||||
|
bool isObject() const {
|
||||||
|
return _type == Internals::JSON_OBJECT;
|
||||||
|
}
|
||||||
|
bool isString() const {
|
||||||
|
return _type == Internals::JSON_STRING ||
|
||||||
|
(_type == Internals::JSON_UNPARSED && _content.asString &&
|
||||||
|
!strcmp("null", _content.asString));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The current type of the variant
|
// The current type of the variant
|
||||||
@ -179,108 +333,36 @@ class JsonVariant : public Internals::JsonPrintable<JsonVariant> {
|
|||||||
|
|
||||||
// The various alternatives for the value of the variant.
|
// The various alternatives for the value of the variant.
|
||||||
Internals::JsonVariantContent _content;
|
Internals::JsonVariantContent _content;
|
||||||
|
|
||||||
// The instance returned by JsonVariant::invalid()
|
|
||||||
static JsonVariant _invalid;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
inline JsonVariant float_with_n_digits(float value, uint8_t digits) {
|
||||||
inline bool JsonVariant::is<long>() const {
|
return JsonVariant(value, digits);
|
||||||
return _type == Internals::JSON_LONG;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
|
||||||
inline bool JsonVariant::is<double>() const {
|
return JsonVariant(value, digits);
|
||||||
return _type >= Internals::JSON_DOUBLE_0_DECIMALS;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool JsonVariant::is<bool>() const {
|
|
||||||
return _type == Internals::JSON_BOOLEAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool JsonVariant::is<const char *>() const {
|
|
||||||
return _type == Internals::JSON_STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool JsonVariant::is<JsonArray &>() const {
|
|
||||||
return _type == Internals::JSON_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool JsonVariant::is<const JsonArray &>() const {
|
|
||||||
return _type == Internals::JSON_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool JsonVariant::is<JsonObject &>() const {
|
|
||||||
return _type == Internals::JSON_OBJECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline bool JsonVariant::is<const JsonObject &>() const {
|
|
||||||
return _type == Internals::JSON_OBJECT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool operator==(const JsonVariant &left, T right) {
|
struct JsonVariant::IsConstructibleFrom {
|
||||||
return left.as<T>() == right;
|
static const bool value =
|
||||||
}
|
TypeTraits::IsIntegral<T>::value ||
|
||||||
|
TypeTraits::IsFloatingPoint<T>::value ||
|
||||||
template <typename T>
|
TypeTraits::IsSame<T, bool>::value ||
|
||||||
inline bool operator==(T left, const JsonVariant &right) {
|
TypeTraits::IsSame<T, char *>::value ||
|
||||||
return left == right.as<T>();
|
TypeTraits::IsSame<T, const char *>::value ||
|
||||||
}
|
TypeTraits::IsSame<T, RawJson>::value ||
|
||||||
|
TypeTraits::IsSame<T, JsonArray &>::value ||
|
||||||
template <typename T>
|
TypeTraits::IsSame<T, const JsonArray &>::value ||
|
||||||
inline bool operator!=(const JsonVariant &left, T right) {
|
TypeTraits::IsSame<T, JsonArraySubscript &>::value ||
|
||||||
return left.as<T>() != right;
|
TypeTraits::IsSame<T, const JsonArraySubscript &>::value ||
|
||||||
}
|
TypeTraits::IsSame<T, JsonObject &>::value ||
|
||||||
|
TypeTraits::IsSame<T, const JsonObject &>::value ||
|
||||||
template <typename T>
|
TypeTraits::IsSame<T, JsonObjectSubscript<const char *> &>::value ||
|
||||||
inline bool operator!=(T left, const JsonVariant &right) {
|
TypeTraits::IsSame<T, const JsonObjectSubscript<const char *> &>::value ||
|
||||||
return left != right.as<T>();
|
TypeTraits::IsSame<T, JsonObjectSubscript<String> &>::value ||
|
||||||
}
|
TypeTraits::IsSame<T, const JsonObjectSubscript<String> &>::value ||
|
||||||
|
TypeTraits::IsSame<T, JsonVariant &>::value ||
|
||||||
template <typename T>
|
TypeTraits::IsSame<T, const JsonVariant &>::value;
|
||||||
inline bool operator<=(const JsonVariant &left, T right) {
|
};
|
||||||
return left.as<T>() <= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator<=(T left, const JsonVariant &right) {
|
|
||||||
return left <= right.as<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator>=(const JsonVariant &left, T right) {
|
|
||||||
return left.as<T>() >= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator>=(T left, const JsonVariant &right) {
|
|
||||||
return left >= right.as<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator<(const JsonVariant &left, T right) {
|
|
||||||
return left.as<T>() < right;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator<(T left, const JsonVariant &right) {
|
|
||||||
return left < right.as<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator>(const JsonVariant &left, T right) {
|
|
||||||
return left.as<T>() > right;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool operator>(T left, const JsonVariant &right) {
|
|
||||||
return left > right.as<T>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
180
include/ArduinoJson/JsonVariant.ipp
Normal file
180
include/ArduinoJson/JsonVariant.ipp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Configuration.hpp"
|
||||||
|
#include "JsonVariant.hpp"
|
||||||
|
#include "Internals/Parse.hpp"
|
||||||
|
#include "JsonArray.hpp"
|
||||||
|
#include "JsonObject.hpp"
|
||||||
|
|
||||||
|
#include <string.h> // for strcmp
|
||||||
|
#include <errno.h> // for errno
|
||||||
|
#include <stdlib.h> // for strtol, strtod
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
inline Internals::JsonInteger JsonVariant::asInteger() const {
|
||||||
|
using namespace Internals;
|
||||||
|
switch (_type) {
|
||||||
|
case JSON_UNDEFINED:
|
||||||
|
return 0;
|
||||||
|
case JSON_POSITIVE_INTEGER:
|
||||||
|
case JSON_BOOLEAN:
|
||||||
|
return _content.asInteger;
|
||||||
|
case JSON_NEGATIVE_INTEGER:
|
||||||
|
return -static_cast<Internals::JsonInteger>(_content.asInteger);
|
||||||
|
case JSON_STRING:
|
||||||
|
case JSON_UNPARSED:
|
||||||
|
if (!_content.asString) return 0;
|
||||||
|
if (!strcmp("true", _content.asString)) return 1;
|
||||||
|
return parse<Internals::JsonInteger>(_content.asString);
|
||||||
|
default:
|
||||||
|
return static_cast<Internals::JsonInteger>(_content.asFloat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Internals::JsonUInt JsonVariant::asUnsignedInteger() const {
|
||||||
|
using namespace Internals;
|
||||||
|
switch (_type) {
|
||||||
|
case JSON_UNDEFINED:
|
||||||
|
return 0;
|
||||||
|
case JSON_POSITIVE_INTEGER:
|
||||||
|
case JSON_BOOLEAN:
|
||||||
|
case JSON_NEGATIVE_INTEGER:
|
||||||
|
return _content.asInteger;
|
||||||
|
case JSON_STRING:
|
||||||
|
case JSON_UNPARSED:
|
||||||
|
if (!_content.asString) return 0;
|
||||||
|
if (!strcmp("true", _content.asString)) return 1;
|
||||||
|
return parse<Internals::JsonUInt>(_content.asString);
|
||||||
|
default:
|
||||||
|
return static_cast<Internals::JsonUInt>(_content.asFloat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *JsonVariant::asString() const {
|
||||||
|
using namespace Internals;
|
||||||
|
if (_type == JSON_UNPARSED && _content.asString &&
|
||||||
|
!strcmp("null", _content.asString))
|
||||||
|
return NULL;
|
||||||
|
if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Internals::JsonFloat JsonVariant::asFloat() const {
|
||||||
|
using namespace Internals;
|
||||||
|
switch (_type) {
|
||||||
|
case JSON_UNDEFINED:
|
||||||
|
return 0;
|
||||||
|
case JSON_POSITIVE_INTEGER:
|
||||||
|
case JSON_BOOLEAN:
|
||||||
|
return static_cast<JsonFloat>(_content.asInteger);
|
||||||
|
case JSON_NEGATIVE_INTEGER:
|
||||||
|
return -static_cast<JsonFloat>(_content.asInteger);
|
||||||
|
case JSON_STRING:
|
||||||
|
case JSON_UNPARSED:
|
||||||
|
return _content.asString ? parse<JsonFloat>(_content.asString) : 0;
|
||||||
|
default:
|
||||||
|
return _content.asFloat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline String JsonVariant::toString() const {
|
||||||
|
using namespace Internals;
|
||||||
|
String s;
|
||||||
|
if ((_type == JSON_STRING || _type == JSON_UNPARSED) &&
|
||||||
|
_content.asString != NULL)
|
||||||
|
s = _content.asString;
|
||||||
|
else
|
||||||
|
printTo(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool JsonVariant::isBoolean() const {
|
||||||
|
using namespace Internals;
|
||||||
|
if (_type == JSON_BOOLEAN) return true;
|
||||||
|
|
||||||
|
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
||||||
|
|
||||||
|
return !strcmp(_content.asString, "true") ||
|
||||||
|
!strcmp(_content.asString, "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool JsonVariant::isInteger() const {
|
||||||
|
using namespace Internals;
|
||||||
|
if (_type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
||||||
|
|
||||||
|
char *end;
|
||||||
|
errno = 0;
|
||||||
|
strtol(_content.asString, &end, 10);
|
||||||
|
|
||||||
|
return *end == '\0' && errno == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool JsonVariant::isFloat() const {
|
||||||
|
using namespace Internals;
|
||||||
|
if (_type >= JSON_FLOAT_0_DECIMALS) return true;
|
||||||
|
|
||||||
|
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
||||||
|
|
||||||
|
char *end;
|
||||||
|
errno = 0;
|
||||||
|
strtod(_content.asString, &end);
|
||||||
|
|
||||||
|
return *end == '\0' && errno == 0 && !is<long>();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void JsonVariant::writeTo(Internals::JsonWriter &writer) const {
|
||||||
|
using namespace Internals;
|
||||||
|
switch (_type) {
|
||||||
|
case JSON_UNDEFINED:
|
||||||
|
return;
|
||||||
|
|
||||||
|
case JSON_ARRAY:
|
||||||
|
_content.asArray->writeTo(writer);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case JSON_OBJECT:
|
||||||
|
_content.asObject->writeTo(writer);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case JSON_STRING:
|
||||||
|
writer.writeString(_content.asString);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case JSON_UNPARSED:
|
||||||
|
writer.writeRaw(_content.asString);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case JSON_NEGATIVE_INTEGER:
|
||||||
|
writer.writeRaw('-');
|
||||||
|
case JSON_POSITIVE_INTEGER:
|
||||||
|
writer.writeInteger(_content.asInteger);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case JSON_BOOLEAN:
|
||||||
|
writer.writeBoolean(_content.asInteger != 0);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS);
|
||||||
|
writer.writeFloat(_content.asFloat, decimals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
|
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
|
||||||
|
return source.printTo(os);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace ArduinoJson
|
153
include/ArduinoJson/JsonVariantBase.hpp
Normal file
153
include/ArduinoJson/JsonVariantBase.hpp
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Internals/JsonVariantAs.hpp"
|
||||||
|
#include "JsonObjectKey.hpp"
|
||||||
|
#include "Polyfills/attributes.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
// Forward declarations.
|
||||||
|
class JsonArraySubscript;
|
||||||
|
template <typename TKey>
|
||||||
|
class JsonObjectSubscript;
|
||||||
|
|
||||||
|
template <typename TImpl>
|
||||||
|
class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||||
|
public:
|
||||||
|
// DEPRECATED: use as<char*>() instead
|
||||||
|
FORCE_INLINE const char *asString() const {
|
||||||
|
return as<const char *>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the variant as an array.
|
||||||
|
// Returns a reference to the JsonArray or JsonArray::invalid() if the
|
||||||
|
// variant
|
||||||
|
// is not an array.
|
||||||
|
FORCE_INLINE operator JsonArray &() const {
|
||||||
|
return as<JsonArray &>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEPRECATED: use as<JsonArray>() instead
|
||||||
|
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 &>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEPRECATED: use as<JsonObject>() instead
|
||||||
|
FORCE_INLINE JsonObject &asObject() const {
|
||||||
|
return as<JsonObject &>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
FORCE_INLINE operator T() const {
|
||||||
|
return as<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
FORCE_INLINE const typename Internals::JsonVariantAs<T>::type 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>();
|
||||||
|
}
|
||||||
|
}
|
16
include/ArduinoJson/Polyfills/attributes.hpp
Normal file
16
include/ArduinoJson/Polyfills/attributes.hpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define FORCE_INLINE __forceinline
|
||||||
|
#define NO_INLINE __declspec(noinline)
|
||||||
|
#else
|
||||||
|
#define FORCE_INLINE __attribute__((always_inline))
|
||||||
|
#define NO_INLINE __attribute__((noinline))
|
||||||
|
#endif
|
111
include/ArduinoJson/Polyfills/math.hpp
Normal file
111
include/ArduinoJson/Polyfills/math.hpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// If Visual Studo <= 2012
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Polyfills {
|
||||||
|
template <typename T>
|
||||||
|
bool isNaN(T x) {
|
||||||
|
return _isnan(x) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool isInfinity(T x) {
|
||||||
|
return !_finite(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
// GCC warning: "conversion to 'float' from 'double' may alter its value"
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#endif
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
#pragma GCC diagnostic ignored "-Wfloat-conversion"
|
||||||
|
#else
|
||||||
|
#pragma GCC diagnostic ignored "-Wconversion"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Workaround for libs that #undef isnan or isinf
|
||||||
|
// https://github.com/bblanchon/ArduinoJson/issues/284
|
||||||
|
#if !defined(isnan) || !defined(isinf)
|
||||||
|
namespace std {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Polyfills {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool isNaN(T x) {
|
||||||
|
// Workaround for libs that #undef isnan
|
||||||
|
// https://github.com/bblanchon/ArduinoJson/issues/284
|
||||||
|
#ifndef isnan
|
||||||
|
using namespace std;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return isnan(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_GLIBCXX_HAVE_ISNANL) && _GLIBCXX_HAVE_ISNANL
|
||||||
|
template <>
|
||||||
|
inline bool isNaN<double>(double x) {
|
||||||
|
return isnanl(x);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_GLIBCXX_HAVE_ISNANF) && _GLIBCXX_HAVE_ISNANF
|
||||||
|
template <>
|
||||||
|
inline bool isNaN<float>(float x) {
|
||||||
|
return isnanf(x);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool isInfinity(T x) {
|
||||||
|
// Workaround for libs that #undef isinf
|
||||||
|
// https://github.com/bblanchon/ArduinoJson/issues/284
|
||||||
|
#ifndef isinf
|
||||||
|
using namespace std;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return isinf(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_GLIBCXX_HAVE_ISINFL) && _GLIBCXX_HAVE_ISINFL
|
||||||
|
template <>
|
||||||
|
inline bool isInfinity<double>(double x) {
|
||||||
|
return isinfl(x);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_GLIBCXX_HAVE_ISINFF) && _GLIBCXX_HAVE_ISINFF
|
||||||
|
template <>
|
||||||
|
inline bool isInfinity<float>(float x) {
|
||||||
|
return isinff(x);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
47
include/ArduinoJson/Polyfills/normalize.hpp
Normal file
47
include/ArduinoJson/Polyfills/normalize.hpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace Polyfills {
|
||||||
|
|
||||||
|
#ifdef ARDUINO
|
||||||
|
|
||||||
|
// on embedded platform, favor code size over speed
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
short normalize(T& value) {
|
||||||
|
short powersOf10 = 0;
|
||||||
|
while (value && value < 1) {
|
||||||
|
powersOf10--;
|
||||||
|
value *= 10;
|
||||||
|
}
|
||||||
|
while (value > 10) {
|
||||||
|
powersOf10++;
|
||||||
|
value /= 10;
|
||||||
|
}
|
||||||
|
return powersOf10;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// on non-embedded platform, favor speed over code size
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
short normalize(T& value) {
|
||||||
|
if (value == 0.0) return 0;
|
||||||
|
|
||||||
|
short powersOf10 = static_cast<short>(floor(log10(value)));
|
||||||
|
value /= pow(T(10), powersOf10);
|
||||||
|
|
||||||
|
return powersOf10;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
39
include/ArduinoJson/Print.hpp
Normal file
39
include/ArduinoJson/Print.hpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef ARDUINO
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
// This class reproduces Arduino's Print class
|
||||||
|
class Print {
|
||||||
|
public:
|
||||||
|
virtual ~Print() {}
|
||||||
|
|
||||||
|
virtual size_t write(uint8_t) = 0;
|
||||||
|
|
||||||
|
size_t print(const char* s) {
|
||||||
|
size_t n = 0;
|
||||||
|
while (*s) {
|
||||||
|
n += write(*s++);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t println() { return write('\r') + write('\n'); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <Print.h>
|
||||||
|
|
||||||
|
#endif
|
21
include/ArduinoJson/RawJson.hpp
Normal file
21
include/ArduinoJson/RawJson.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
|
||||||
|
// A special type of data that can be used to insert pregenerated JSON portions.
|
||||||
|
class RawJson {
|
||||||
|
public:
|
||||||
|
explicit RawJson(const char* str) : _str(str) {}
|
||||||
|
operator const char*() const { return _str; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* _str;
|
||||||
|
};
|
||||||
|
}
|
@ -1,13 +1,24 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// Arduino JSON library
|
// Arduino JSON library
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "JsonBuffer.hpp"
|
#include "JsonBuffer.hpp"
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#endif
|
||||||
|
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
|
|
||||||
// Implements a JsonBuffer with fixed memory allocation.
|
// Implements a JsonBuffer with fixed memory allocation.
|
||||||
@ -18,14 +29,17 @@ class StaticJsonBuffer : public JsonBuffer {
|
|||||||
public:
|
public:
|
||||||
explicit StaticJsonBuffer() : _size(0) {}
|
explicit StaticJsonBuffer() : _size(0) {}
|
||||||
|
|
||||||
size_t capacity() const { return CAPACITY; }
|
size_t capacity() const {
|
||||||
size_t size() const { return _size; }
|
return CAPACITY;
|
||||||
|
}
|
||||||
|
size_t size() const {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void* alloc(size_t bytes) {
|
virtual void* alloc(size_t bytes) {
|
||||||
if (_size + bytes > CAPACITY) return NULL;
|
if (_size + bytes > CAPACITY) return NULL;
|
||||||
void* p = &_buffer[_size];
|
void* p = &_buffer[_size];
|
||||||
_size += bytes;
|
_size += round_size_up(bytes);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,3 +48,11 @@ class StaticJsonBuffer : public JsonBuffer {
|
|||||||
size_t _size;
|
size_t _size;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
24
include/ArduinoJson/String.hpp
Normal file
24
include/ArduinoJson/String.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Configuration.hpp"
|
||||||
|
|
||||||
|
#if ARDUINOJSON_USE_ARDUINO_STRING
|
||||||
|
|
||||||
|
#include <WString.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
typedef std::string String;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
22
include/ArduinoJson/TypeTraits/EnableIf.hpp
Normal file
22
include/ArduinoJson/TypeTraits/EnableIf.hpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that return the type T if Condition is true.
|
||||||
|
template <bool Condition, typename T = void>
|
||||||
|
struct EnableIf {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct EnableIf<true, T> {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
21
include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp
Normal file
21
include/ArduinoJson/TypeTraits/IsFloatingPoint.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IsSame.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that returns true if T is a floating point type
|
||||||
|
template <typename T>
|
||||||
|
struct IsFloatingPoint {
|
||||||
|
static const bool value = IsSame<T, float>::value || IsSame<T, double>::value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
26
include/ArduinoJson/TypeTraits/IsIntegral.hpp
Normal file
26
include/ArduinoJson/TypeTraits/IsIntegral.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Configuration.hpp"
|
||||||
|
#include "IsSame.hpp"
|
||||||
|
#include "IsSignedIntegral.hpp"
|
||||||
|
#include "IsUnsignedIntegral.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that returns true if T is an integral type.
|
||||||
|
template <typename T>
|
||||||
|
struct IsIntegral {
|
||||||
|
static const bool value = TypeTraits::IsSignedIntegral<T>::value ||
|
||||||
|
TypeTraits::IsUnsignedIntegral<T>::value ||
|
||||||
|
TypeTraits::IsSame<T, char>::value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
24
include/ArduinoJson/TypeTraits/IsReference.hpp
Normal file
24
include/ArduinoJson/TypeTraits/IsReference.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that returns true if T is a reference
|
||||||
|
template <typename T>
|
||||||
|
struct IsReference {
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct IsReference<T&> {
|
||||||
|
static const bool value = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
24
include/ArduinoJson/TypeTraits/IsSame.hpp
Normal file
24
include/ArduinoJson/TypeTraits/IsSame.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that returns true if types T and U are the same.
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct IsSame {
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct IsSame<T, T> {
|
||||||
|
static const bool value = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
33
include/ArduinoJson/TypeTraits/IsSignedIntegral.hpp
Normal file
33
include/ArduinoJson/TypeTraits/IsSignedIntegral.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Configuration.hpp"
|
||||||
|
#include "IsSame.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that returns true if T is an integral type.
|
||||||
|
template <typename T>
|
||||||
|
struct IsSignedIntegral {
|
||||||
|
static const bool value = TypeTraits::IsSame<T, signed char>::value ||
|
||||||
|
TypeTraits::IsSame<T, signed short>::value ||
|
||||||
|
TypeTraits::IsSame<T, signed int>::value ||
|
||||||
|
TypeTraits::IsSame<T, signed long>::value ||
|
||||||
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
|
TypeTraits::IsSame<T, signed long long>::value ||
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_USE_INT64
|
||||||
|
TypeTraits::IsSame<T, signed __int64>::value ||
|
||||||
|
#endif
|
||||||
|
false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
33
include/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp
Normal file
33
include/ArduinoJson/TypeTraits/IsUnsignedIntegral.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Configuration.hpp"
|
||||||
|
#include "IsSame.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that returns true if T is an integral type.
|
||||||
|
template <typename T>
|
||||||
|
struct IsUnsignedIntegral {
|
||||||
|
static const bool value = TypeTraits::IsSame<T, unsigned char>::value ||
|
||||||
|
TypeTraits::IsSame<T, unsigned short>::value ||
|
||||||
|
TypeTraits::IsSame<T, unsigned int>::value ||
|
||||||
|
TypeTraits::IsSame<T, unsigned long>::value ||
|
||||||
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
|
TypeTraits::IsSame<T, unsigned long long>::value ||
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARDUINOJSON_USE_INT64
|
||||||
|
TypeTraits::IsSame<T, unsigned __int64>::value ||
|
||||||
|
#endif
|
||||||
|
false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
23
include/ArduinoJson/TypeTraits/RemoveConst.hpp
Normal file
23
include/ArduinoJson/TypeTraits/RemoveConst.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that return the type T without the const modifier
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveConst {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveConst<const T> {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
23
include/ArduinoJson/TypeTraits/RemoveReference.hpp
Normal file
23
include/ArduinoJson/TypeTraits/RemoveReference.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright Benoit Blanchon 2014-2016
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Arduino JSON library
|
||||||
|
// https://github.com/bblanchon/ArduinoJson
|
||||||
|
// If you like this project, please add a star!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
namespace TypeTraits {
|
||||||
|
|
||||||
|
// A meta-function that return the type T without the reference modifier.
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveReference {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
struct RemoveReference<T&> {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
17
library.json
17
library.json
@ -1,17 +1,22 @@
|
|||||||
{
|
{
|
||||||
"name": "Json",
|
"name": "ArduinoJson",
|
||||||
"keywords": "json, rest, http, web",
|
"keywords": "json, rest, http, web",
|
||||||
"description": "An elegant and efficient JSON library for embedded systems",
|
"description": "An elegant and efficient JSON library for embedded systems",
|
||||||
"repository":
|
"repository": {
|
||||||
{
|
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||||
},
|
},
|
||||||
"authors":
|
"version": "5.6.6",
|
||||||
{
|
"authors": {
|
||||||
"name": "Benoit Blanchon",
|
"name": "Benoit Blanchon",
|
||||||
"url": "http://blog.benoitblanchon.fr"
|
"url": "http://blog.benoitblanchon.fr"
|
||||||
},
|
},
|
||||||
|
"exclude": [
|
||||||
|
"scripts",
|
||||||
|
"src/ArduinoJson.h",
|
||||||
|
"test",
|
||||||
|
"third-party"
|
||||||
|
],
|
||||||
"frameworks": "arduino",
|
"frameworks": "arduino",
|
||||||
"platforms": "atmelavr"
|
"platforms": "*"
|
||||||
}
|
}
|
9
library.properties
Normal file
9
library.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name=ArduinoJson
|
||||||
|
version=5.6.6
|
||||||
|
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!
|
||||||
|
category=Data Processing
|
||||||
|
url=https://github.com/bblanchon/ArduinoJson
|
||||||
|
architectures=*
|
108
scripts/buffer-size-calculator.html
Normal file
108
scripts/buffer-size-calculator.html
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>ArduinoJson - JsonBuffer size calculator</title>
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1>JsonBuffer size calculator</h1>
|
||||||
|
</div>
|
||||||
|
<div id='error' class="alert alert-danger" role="alert">
|
||||||
|
Please paste your JSON in the "input" box
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h2>Input</h2>
|
||||||
|
<textarea class="form-control" rows=30 id='input'></textarea><br>
|
||||||
|
</div>
|
||||||
|
<div id='results' class="col-md-6" style='display:none'>
|
||||||
|
<h2>Result</h2>
|
||||||
|
<h3>Expression</h3>
|
||||||
|
<p><code id='resultexpr'></code></p>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<th>Platform</th>
|
||||||
|
<th>Size (in bytes)</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>AVR 8-bit</td>
|
||||||
|
<td id='sizeavr8'></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ESP8266</td>
|
||||||
|
<td id='sizeesp8266'></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>x86</td>
|
||||||
|
<td id='sizex86'></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>x64</td>
|
||||||
|
<td id='sizex64'></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function getExpression(obj) {
|
||||||
|
var elements = [];
|
||||||
|
if (obj instanceof Array) {
|
||||||
|
elements.push("JSON_ARRAY_SIZE(" + obj.length + ")");
|
||||||
|
for (var i = 0; i<obj.length; i++) {
|
||||||
|
elements.push(getExpression(obj[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (obj instanceof Object) {
|
||||||
|
elements.push("JSON_OBJECT_SIZE(" + Object.keys(obj).length + ")");
|
||||||
|
for (var key in obj) {
|
||||||
|
elements.push(getExpression(obj[key]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return elements.filter(function(x){return x.length > 0}).join(" + ");
|
||||||
|
}
|
||||||
|
|
||||||
|
input.oninput = function(e) {
|
||||||
|
results.style.display = 'none';
|
||||||
|
error.style.visibility = 'hidden';
|
||||||
|
|
||||||
|
try {
|
||||||
|
var obj = JSON.parse(input.value);
|
||||||
|
var expression = getExpression(obj);
|
||||||
|
|
||||||
|
resultexpr.innerText = expression;
|
||||||
|
sizeavr8.innerText = eval(
|
||||||
|
"function JSON_ARRAY_SIZE(n) { return 4 + 8*n }" +
|
||||||
|
"function JSON_OBJECT_SIZE(n) { return 4 + 10*n }" +
|
||||||
|
expression
|
||||||
|
);
|
||||||
|
sizeesp8266.innerText = eval(
|
||||||
|
"function JSON_ARRAY_SIZE(n) { return 8 + 12*n }" +
|
||||||
|
"function JSON_OBJECT_SIZE(n) { return 8 + 16*n }" +
|
||||||
|
expression
|
||||||
|
);
|
||||||
|
sizex86.innerText = eval(
|
||||||
|
"function JSON_ARRAY_SIZE(n) { return 12 + 24*n }" +
|
||||||
|
"function JSON_OBJECT_SIZE(n) { return 12 + 32*n }" +
|
||||||
|
expression
|
||||||
|
);
|
||||||
|
sizex64.innerText = eval(
|
||||||
|
"function JSON_ARRAY_SIZE(n) { return 24 + 24*n }" +
|
||||||
|
"function JSON_OBJECT_SIZE(n) { return 24 + 32*n }" +
|
||||||
|
expression
|
||||||
|
);
|
||||||
|
results.style.display = 'block';
|
||||||
|
}
|
||||||
|
catch (ex) {
|
||||||
|
error.innerText = "ERROR: " + ex.message;
|
||||||
|
error.style.visibility = 'visible';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</html>
|
@ -1,23 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
ZIP="C:\Program Files\7-Zip\7z.exe"
|
|
||||||
TAG=$(git describe)
|
TAG=$(git describe)
|
||||||
OUTPUT="ArduinoJson-$TAG.zip"
|
OUTPUT="ArduinoJson-$TAG.zip"
|
||||||
|
|
||||||
cd ../..
|
cd $(dirname $0)/../..
|
||||||
|
|
||||||
# remove existing file
|
# remove existing file
|
||||||
rm -f $OUTPUT
|
rm -f $OUTPUT
|
||||||
|
|
||||||
# create zip
|
# create zip
|
||||||
"$ZIP" a $OUTPUT \
|
7z a $OUTPUT \
|
||||||
ArduinoJson/CHANGELOG.md \
|
ArduinoJson/CHANGELOG.md \
|
||||||
ArduinoJson/examples \
|
ArduinoJson/examples \
|
||||||
ArduinoJson/include \
|
ArduinoJson/include \
|
||||||
ArduinoJson/keywords.txt \
|
ArduinoJson/keywords.txt \
|
||||||
|
ArduinoJson/library.properties \
|
||||||
ArduinoJson/LICENSE.md \
|
ArduinoJson/LICENSE.md \
|
||||||
ArduinoJson/README.md \
|
ArduinoJson/README.md \
|
||||||
ArduinoJson/src \
|
ArduinoJson/ArduinoJson.h
|
||||||
ArduinoJson/ArduinoJson.h \
|
|
||||||
ArduinoJson/ArduinoJson.cpp \
|
|
||||||
-x!ArduinoJson/src/CMakeLists.txt
|
|
||||||
|
@ -20,10 +20,10 @@ build-env()
|
|||||||
if [[ $(uname) == MINGW* ]]
|
if [[ $(uname) == MINGW* ]]
|
||||||
then
|
then
|
||||||
build-env "Make" "MinGW Makefiles"
|
build-env "Make" "MinGW Makefiles"
|
||||||
build-env "SublimeText" "Sublime Text 2 - MinGW Makefiles"
|
build-env "SublimeText" "Sublime Text 2 - Ninja"
|
||||||
build-env "VisualStudio" "Visual Studio 12 2013"
|
build-env "VisualStudio" "Visual Studio 14 2015"
|
||||||
else
|
else
|
||||||
build-env "SublimeText" "Sublime Text 2 - Unix Makefiles"
|
build-env "SublimeText" "Sublime Text 2 - Ninja"
|
||||||
build-env "Make" "Unix Makefiles"
|
build-env "Make" "Unix Makefiles"
|
||||||
build-env "Xcode" "Xcode"
|
build-env "Xcode" "Xcode"
|
||||||
fi
|
fi
|
42
scripts/create-size-graph.sh
Executable file
42
scripts/create-size-graph.sh
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
OUTPUT="$(pwd)/sizes.csv"
|
||||||
|
|
||||||
|
echo "Tag;Date;Parser;Generator" > $OUTPUT
|
||||||
|
|
||||||
|
cd $(dirname $(dirname $0))
|
||||||
|
|
||||||
|
git tag | while read TAG
|
||||||
|
do
|
||||||
|
|
||||||
|
git checkout -q tags/$TAG
|
||||||
|
|
||||||
|
DATE=$(git log -1 --date=short --pretty=format:%cd)
|
||||||
|
PARSER_SIZE=$(arduino --verify examples/JsonParserExample/JsonParserExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||||
|
|
||||||
|
if [ -e 'examples/JsonGeneratorExample/JsonGeneratorExample.ino' ]; then
|
||||||
|
GENERATOR_SIZE=$(arduino --verify examples/JsonGeneratorExample/JsonGeneratorExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||||
|
else
|
||||||
|
GENERATOR_SIZE=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $TAG
|
||||||
|
if [ ! -z "$PARSER_SIZE" ]
|
||||||
|
then
|
||||||
|
echo "JsonParserExample = $PARSER_SIZE bytes"
|
||||||
|
else
|
||||||
|
echo "JsonParserExample compilation failed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -z "$GENERATOR_SIZE" ]
|
||||||
|
then
|
||||||
|
echo "JsonGeneratorExample = $GENERATOR_SIZE bytes"
|
||||||
|
else
|
||||||
|
echo "JsonGeneratorExample compilation failed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$TAG;$DATE;$PARSER_SIZE;$GENERATOR_SIZE" >> $OUTPUT
|
||||||
|
|
||||||
|
done
|
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
|
9
scripts/travis/cmake-osx.sh
Executable file
9
scripts/travis/cmake-osx.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh -eux
|
||||||
|
|
||||||
|
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Darwin-x86_64.tar.gz
|
||||||
|
|
||||||
|
curl -sS $URL | tar xz -C /tmp --strip 1
|
||||||
|
|
||||||
|
/tmp/CMake.app/Contents/bin/cmake .
|
||||||
|
make
|
||||||
|
make test
|
9
scripts/travis/cmake.sh
Executable file
9
scripts/travis/cmake.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh -eux
|
||||||
|
|
||||||
|
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Linux-x86_64.tar.gz
|
||||||
|
|
||||||
|
curl -sS $URL | tar xz -C /tmp --strip 1
|
||||||
|
|
||||||
|
/tmp/bin/cmake -DCMAKE_CXX_COMPILER=$CMAKE_CXX_COMPILER .
|
||||||
|
make
|
||||||
|
make test
|
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
|
||||||
|
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 JsonParserExample JsonGeneratorExample
|
||||||
|
do
|
||||||
|
platformio ci examples/$EXAMPLE/$EXAMPLE.ino -l '.' -b $BOARD
|
||||||
|
done
|
@ -1,52 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#ifndef ARDUINO
|
|
||||||
|
|
||||||
#include "../../include/ArduinoJson/Arduino/Print.hpp"
|
|
||||||
|
|
||||||
#include <math.h> // for isnan() and isinf()
|
|
||||||
#include <stdio.h> // for sprintf()
|
|
||||||
|
|
||||||
size_t Print::print(const char s[]) {
|
|
||||||
size_t n = 0;
|
|
||||||
while (*s) {
|
|
||||||
n += write(*s++);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Print::print(double value, int digits) {
|
|
||||||
// https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L218
|
|
||||||
if (isnan(value)) return print("nan");
|
|
||||||
if (isinf(value)) return print("inf");
|
|
||||||
|
|
||||||
char tmp[32];
|
|
||||||
|
|
||||||
// https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L220
|
|
||||||
bool isBigDouble = value > 4294967040.0 || value < -4294967040.0;
|
|
||||||
|
|
||||||
if (isBigDouble) {
|
|
||||||
// Arduino's implementation prints "ovf"
|
|
||||||
// We prefer trying to use scientific notation, since we have sprintf
|
|
||||||
sprintf(tmp, "%g", value);
|
|
||||||
} else {
|
|
||||||
// Here we have the exact same output as Arduino's implementation
|
|
||||||
sprintf(tmp, "%.*f", digits, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return print(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Print::print(long value) {
|
|
||||||
char tmp[32];
|
|
||||||
sprintf(tmp, "%ld", value);
|
|
||||||
return print(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Print::println() { return write('\r') + write('\n'); }
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,48 +0,0 @@
|
|||||||
file(GLOB_RECURSE INC_FILES ../include/*.hpp)
|
|
||||||
file(GLOB_RECURSE SRC_FILES *.cpp)
|
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
|
||||||
add_definitions(
|
|
||||||
-fno-exceptions
|
|
||||||
-pedantic
|
|
||||||
-Wall
|
|
||||||
-Wcast-align
|
|
||||||
-Wcast-qual
|
|
||||||
-Wconversion
|
|
||||||
-Wctor-dtor-privacy
|
|
||||||
-Wdisabled-optimization
|
|
||||||
-Werror
|
|
||||||
-Wextra
|
|
||||||
-Wformat=2
|
|
||||||
-Winit-self
|
|
||||||
-Wmissing-include-dirs
|
|
||||||
-Wno-parentheses
|
|
||||||
-Wno-sign-conversion
|
|
||||||
-Wno-unused
|
|
||||||
-Wno-variadic-macros
|
|
||||||
-Wnon-virtual-dtor
|
|
||||||
-Wold-style-cast
|
|
||||||
-Woverloaded-virtual
|
|
||||||
-Wredundant-decls
|
|
||||||
-Wshadow
|
|
||||||
-Wsign-promo
|
|
||||||
-Wstrict-overflow=5
|
|
||||||
-Wundef
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU)")
|
|
||||||
add_definitions(
|
|
||||||
-Wlogical-op
|
|
||||||
-Wnoexcept
|
|
||||||
-Wstrict-null-sentinel
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|
||||||
add_definitions(
|
|
||||||
-Wc++11-compat
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(ArduinoJson ${SRC_FILES} ${INC_FILES})
|
|
@ -1,79 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#include "../include/ArduinoJson/DynamicJsonBuffer.hpp"
|
|
||||||
|
|
||||||
namespace ArduinoJson {
|
|
||||||
namespace Internals {
|
|
||||||
struct DynamicJsonBufferBlockWithoutData {
|
|
||||||
DynamicJsonBufferBlock* next;
|
|
||||||
size_t capacity;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct DynamicJsonBufferBlock : DynamicJsonBufferBlockWithoutData {
|
|
||||||
uint8_t data[1];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace ArduinoJson;
|
|
||||||
using namespace ArduinoJson::Internals;
|
|
||||||
|
|
||||||
DynamicJsonBuffer::DynamicJsonBuffer() {
|
|
||||||
_head = createBlock(FIRST_BLOCK_CAPACITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonBuffer::~DynamicJsonBuffer() {
|
|
||||||
Block* currentBlock = _head;
|
|
||||||
|
|
||||||
while (currentBlock != NULL) {
|
|
||||||
Block* nextBlock = currentBlock->next;
|
|
||||||
free(currentBlock);
|
|
||||||
currentBlock = nextBlock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t DynamicJsonBuffer::size() const {
|
|
||||||
size_t total = 0;
|
|
||||||
|
|
||||||
for (const Block* b = _head; b != NULL; b = b->next) {
|
|
||||||
total += b->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* DynamicJsonBuffer::alloc(size_t bytes) {
|
|
||||||
if (!canAllocInHead(bytes)) addNewBlock();
|
|
||||||
return allocInHead(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DynamicJsonBuffer::canAllocInHead(size_t bytes) const {
|
|
||||||
return _head->size + bytes <= _head->capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* DynamicJsonBuffer::allocInHead(size_t bytes) {
|
|
||||||
void* p = _head->data + _head->size;
|
|
||||||
_head->size += bytes;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DynamicJsonBuffer::addNewBlock() {
|
|
||||||
Block* block = createBlock(_head->capacity * 2);
|
|
||||||
block->next = _head;
|
|
||||||
_head = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonBuffer::Block* DynamicJsonBuffer::createBlock(size_t capacity) {
|
|
||||||
size_t blkSize = sizeof(DynamicJsonBufferBlockWithoutData) + capacity;
|
|
||||||
Block* block = static_cast<Block*>(malloc(blkSize));
|
|
||||||
block->capacity = capacity;
|
|
||||||
block->size = 0;
|
|
||||||
block->next = NULL;
|
|
||||||
return block;
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#include "../../include/ArduinoJson/Internals/IndentedPrint.hpp"
|
|
||||||
|
|
||||||
using namespace ArduinoJson::Internals;
|
|
||||||
|
|
||||||
size_t IndentedPrint::write(uint8_t c) {
|
|
||||||
size_t n = 0;
|
|
||||||
|
|
||||||
if (isNewLine) n += writeTabs();
|
|
||||||
|
|
||||||
n += sink->write(c);
|
|
||||||
|
|
||||||
isNewLine = c == '\n';
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t IndentedPrint::writeTabs() {
|
|
||||||
size_t n = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
@ -1,197 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#include "../../include/ArduinoJson/Internals/JsonParser.hpp"
|
|
||||||
|
|
||||||
#include <stdlib.h> // for strtol, strtod
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "../../include/ArduinoJson/Internals/QuotedString.hpp"
|
|
||||||
#include "../../include/ArduinoJson/JsonArray.hpp"
|
|
||||||
#include "../../include/ArduinoJson/JsonBuffer.hpp"
|
|
||||||
#include "../../include/ArduinoJson/JsonObject.hpp"
|
|
||||||
|
|
||||||
using namespace ArduinoJson;
|
|
||||||
using namespace ArduinoJson::Internals;
|
|
||||||
|
|
||||||
void JsonParser::skipSpaces() {
|
|
||||||
while (isspace(*_ptr)) _ptr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonParser::skip(char charToSkip) {
|
|
||||||
skipSpaces();
|
|
||||||
if (*_ptr != charToSkip) return false;
|
|
||||||
_ptr++;
|
|
||||||
skipSpaces();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonParser::skip(const char *wordToSkip) {
|
|
||||||
const char *charToSkip = wordToSkip;
|
|
||||||
while (*charToSkip && *_ptr == *charToSkip) {
|
|
||||||
charToSkip++;
|
|
||||||
_ptr++;
|
|
||||||
}
|
|
||||||
return *charToSkip == '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonParser::parseAnythingTo(JsonVariant &destination) {
|
|
||||||
if (_nestingLimit == 0) return;
|
|
||||||
_nestingLimit--;
|
|
||||||
|
|
||||||
skipSpaces();
|
|
||||||
|
|
||||||
switch (*_ptr) {
|
|
||||||
case '[':
|
|
||||||
destination = parseArray();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '{':
|
|
||||||
destination = parseObject();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 't':
|
|
||||||
case 'f':
|
|
||||||
parseBooleanTo(destination);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '-':
|
|
||||||
case '.':
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
parseNumberTo(destination);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
parseNullTo(destination);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\'':
|
|
||||||
case '\"':
|
|
||||||
destination = parseString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_nestingLimit++;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonArray &JsonParser::parseArray() {
|
|
||||||
// Create an empty array
|
|
||||||
JsonArray &array = _buffer->createArray();
|
|
||||||
|
|
||||||
// Check opening braket
|
|
||||||
if (!skip('[')) goto ERROR_MISSING_BRACKET;
|
|
||||||
if (skip(']')) goto SUCCESS_EMPTY_ARRAY;
|
|
||||||
|
|
||||||
// Read each value
|
|
||||||
for (;;) {
|
|
||||||
// 1 - Parse value
|
|
||||||
JsonVariant &value = array.add();
|
|
||||||
parseAnythingTo(value);
|
|
||||||
if (!value.success()) goto ERROR_INVALID_VALUE;
|
|
||||||
|
|
||||||
// 2 - More values?
|
|
||||||
if (skip(']')) goto SUCCES_NON_EMPTY_ARRAY;
|
|
||||||
if (!skip(',')) goto ERROR_MISSING_COMMA;
|
|
||||||
}
|
|
||||||
|
|
||||||
SUCCESS_EMPTY_ARRAY:
|
|
||||||
SUCCES_NON_EMPTY_ARRAY:
|
|
||||||
return array;
|
|
||||||
|
|
||||||
ERROR_INVALID_VALUE:
|
|
||||||
ERROR_MISSING_BRACKET:
|
|
||||||
ERROR_MISSING_COMMA:
|
|
||||||
return JsonArray::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonObject &JsonParser::parseObject() {
|
|
||||||
// Create an empty object
|
|
||||||
JsonObject &object = _buffer->createObject();
|
|
||||||
|
|
||||||
// Check opening brace
|
|
||||||
if (!skip('{')) goto ERROR_MISSING_BRACE;
|
|
||||||
if (skip('}')) goto SUCCESS_EMPTY_OBJECT;
|
|
||||||
|
|
||||||
// Read each key value pair
|
|
||||||
for (;;) {
|
|
||||||
// 1 - Parse key
|
|
||||||
const char *key = parseString();
|
|
||||||
if (!key) goto ERROR_INVALID_KEY;
|
|
||||||
if (!skip(':')) goto ERROR_MISSING_COLON;
|
|
||||||
|
|
||||||
// 2 - Parse value
|
|
||||||
JsonVariant &value = object.add(key);
|
|
||||||
parseAnythingTo(value);
|
|
||||||
if (!value.success()) goto ERROR_INVALID_VALUE;
|
|
||||||
|
|
||||||
// 3 - More keys/values?
|
|
||||||
if (skip('}')) goto SUCCESS_NON_EMPTY_OBJECT;
|
|
||||||
if (!skip(',')) 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:
|
|
||||||
return JsonObject::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonParser::parseBooleanTo(JsonVariant &destination) {
|
|
||||||
if (skip("true"))
|
|
||||||
destination = true;
|
|
||||||
else if (skip("false"))
|
|
||||||
destination = false;
|
|
||||||
else
|
|
||||||
destination = JsonVariant::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonParser::parseNumberTo(JsonVariant &destination) {
|
|
||||||
char *endOfLong;
|
|
||||||
long longValue = strtol(_ptr, &endOfLong, 10);
|
|
||||||
char stopChar = *endOfLong;
|
|
||||||
|
|
||||||
// Could it be a floating point value?
|
|
||||||
bool couldBeFloat = stopChar == '.' || stopChar == 'e' || stopChar == 'E';
|
|
||||||
|
|
||||||
if (couldBeFloat) {
|
|
||||||
// Yes => parse it as a double
|
|
||||||
double doubleValue = strtod(_ptr, &_ptr);
|
|
||||||
// Count the decimal digits
|
|
||||||
uint8_t decimals = static_cast<uint8_t>(_ptr - endOfLong - 1);
|
|
||||||
// Set the variant as a double
|
|
||||||
destination.set(doubleValue, decimals);
|
|
||||||
} else {
|
|
||||||
// No => set the variant as a long
|
|
||||||
_ptr = endOfLong;
|
|
||||||
destination = longValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonParser::parseNullTo(JsonVariant &destination) {
|
|
||||||
const char *NULL_STRING = NULL;
|
|
||||||
if (skip("null"))
|
|
||||||
destination = NULL_STRING;
|
|
||||||
else
|
|
||||||
destination = JsonVariant::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *JsonParser::parseString() {
|
|
||||||
return QuotedString::extractFrom(_ptr, &_ptr);
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#include "../../include/ArduinoJson/Internals/List.hpp"
|
|
||||||
|
|
||||||
#include "../../include/ArduinoJson/JsonPair.hpp"
|
|
||||||
#include "../../include/ArduinoJson/JsonVariant.hpp"
|
|
||||||
|
|
||||||
using namespace ArduinoJson;
|
|
||||||
using namespace ArduinoJson::Internals;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
int List<T>::size() const {
|
|
||||||
int nodeCount = 0;
|
|
||||||
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
|
|
||||||
return nodeCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void List<T>::removeNode(node_type *nodeToRemove) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template class ArduinoJson::Internals::List<JsonPair>;
|
|
||||||
template class ArduinoJson::Internals::List<JsonVariant>;
|
|
@ -1,86 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#include "../../include/ArduinoJson/Internals/Prettyfier.hpp"
|
|
||||||
|
|
||||||
using namespace ArduinoJson::Internals;
|
|
||||||
|
|
||||||
size_t Prettyfier::write(uint8_t c) {
|
|
||||||
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c);
|
|
||||||
_previousChar = c;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t Prettyfier::handleStringChar(uint8_t c) {
|
|
||||||
bool isQuote = c == '"' && _previousChar != '\\';
|
|
||||||
|
|
||||||
if (isQuote) _inString = false;
|
|
||||||
|
|
||||||
return _sink.write(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t Prettyfier::handleMarkupChar(uint8_t c) {
|
|
||||||
switch (c) {
|
|
||||||
case '{':
|
|
||||||
case '[':
|
|
||||||
return handleBlockOpen(c);
|
|
||||||
|
|
||||||
case '}':
|
|
||||||
case ']':
|
|
||||||
return handleBlockClose(c);
|
|
||||||
|
|
||||||
case ':':
|
|
||||||
return handleColumn();
|
|
||||||
|
|
||||||
case ',':
|
|
||||||
return handleComma();
|
|
||||||
|
|
||||||
case '"':
|
|
||||||
return handleQuoteOpen();
|
|
||||||
|
|
||||||
default:
|
|
||||||
return handleNormalChar(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t Prettyfier::handleBlockOpen(uint8_t c) {
|
|
||||||
return indentIfNeeded() + _sink.write(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t Prettyfier::handleBlockClose(uint8_t c) {
|
|
||||||
return unindentIfNeeded() + _sink.write(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t Prettyfier::handleColumn() {
|
|
||||||
return _sink.write(':') + _sink.write(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t Prettyfier::handleComma() {
|
|
||||||
return _sink.write(',') + _sink.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t Prettyfier::handleQuoteOpen() {
|
|
||||||
_inString = true;
|
|
||||||
return indentIfNeeded() + _sink.write('"');
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t Prettyfier::handleNormalChar(uint8_t c) {
|
|
||||||
return indentIfNeeded() + _sink.write(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Prettyfier::indentIfNeeded() {
|
|
||||||
if (!inEmptyBlock()) return 0;
|
|
||||||
|
|
||||||
_sink.indent();
|
|
||||||
return _sink.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Prettyfier::unindentIfNeeded() {
|
|
||||||
if (inEmptyBlock()) return 0;
|
|
||||||
|
|
||||||
_sink.unindent();
|
|
||||||
return _sink.println();
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#include "../../include/ArduinoJson/Internals/QuotedString.hpp"
|
|
||||||
|
|
||||||
using namespace ArduinoJson::Internals;
|
|
||||||
|
|
||||||
// How to escape special chars:
|
|
||||||
// specialChars[2*i+1] => the special char
|
|
||||||
// specialChars[2*i] => the char to use instead
|
|
||||||
static const char specialChars[] = "\"\"\\\\b\bf\fn\nr\rt\t";
|
|
||||||
|
|
||||||
static inline char getSpecialChar(char c) {
|
|
||||||
// Optimized for code size on a 8-bit AVR
|
|
||||||
|
|
||||||
const char *p = specialChars;
|
|
||||||
|
|
||||||
while (p[0] && p[1] != c) {
|
|
||||||
p += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return p[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t printCharTo(char c, Print &p) {
|
|
||||||
char specialChar = getSpecialChar(c);
|
|
||||||
|
|
||||||
return specialChar ? p.write('\\') + p.write(specialChar) : p.write(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t QuotedString::printTo(const char *s, Print &p) {
|
|
||||||
if (!s) return p.print("null");
|
|
||||||
|
|
||||||
size_t n = p.write('\"');
|
|
||||||
|
|
||||||
while (*s) {
|
|
||||||
n += printCharTo(*s++, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return n + p.write('\"');
|
|
||||||
}
|
|
||||||
|
|
||||||
static char unescapeChar(char c) {
|
|
||||||
// Optimized for code size on a 8-bit AVR
|
|
||||||
|
|
||||||
const char *p = specialChars + 4;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (p[0] == '\0') return c;
|
|
||||||
if (p[0] == c) return p[1];
|
|
||||||
p += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool isQuote(char c) { return c == '\"' || c == '\''; }
|
|
||||||
|
|
||||||
char *QuotedString::extractFrom(char *input, char **endPtr) {
|
|
||||||
char firstChar = *input;
|
|
||||||
|
|
||||||
if (!isQuote(firstChar)) {
|
|
||||||
// must start with a quote
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char stopChar = firstChar; // closing quote is the same as opening quote
|
|
||||||
|
|
||||||
char *startPtr = input + 1; // skip the quote
|
|
||||||
char *readPtr = startPtr;
|
|
||||||
char *writePtr = startPtr;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
c = *readPtr++;
|
|
||||||
|
|
||||||
if (c == '\0') {
|
|
||||||
// premature ending
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == stopChar) {
|
|
||||||
// closing quote
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '\\') {
|
|
||||||
// replace char
|
|
||||||
c = unescapeChar(*readPtr++);
|
|
||||||
}
|
|
||||||
|
|
||||||
*writePtr++ = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
// end the string here
|
|
||||||
*writePtr = '\0';
|
|
||||||
|
|
||||||
// update end ptr
|
|
||||||
*endPtr = readPtr;
|
|
||||||
|
|
||||||
return startPtr;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#include "../../include/ArduinoJson/Internals/StringBuilder.hpp"
|
|
||||||
|
|
||||||
using namespace ArduinoJson::Internals;
|
|
||||||
|
|
||||||
size_t StringBuilder::write(uint8_t c) {
|
|
||||||
if (length >= capacity) return 0;
|
|
||||||
|
|
||||||
buffer[length++] = c;
|
|
||||||
buffer[length] = '\0';
|
|
||||||
return 1;
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2015
|
|
||||||
// MIT License
|
|
||||||
//
|
|
||||||
// Arduino JSON library
|
|
||||||
// https://github.com/bblanchon/ArduinoJson
|
|
||||||
|
|
||||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
|
||||||
|
|
||||||
#include "../include/ArduinoJson/JsonBuffer.hpp"
|
|
||||||
#include "../include/ArduinoJson/JsonObject.hpp"
|
|
||||||
|
|
||||||
using namespace ArduinoJson;
|
|
||||||
using namespace ArduinoJson::Internals;
|
|
||||||
|
|
||||||
JsonArray JsonArray::_invalid(NULL);
|
|
||||||
|
|
||||||
JsonVariant &JsonArray::at(int index) const {
|
|
||||||
node_type *node = getNodeAt(index);
|
|
||||||
return node ? node->content : JsonVariant::invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonVariant &JsonArray::add() {
|
|
||||||
node_type *node = createNode();
|
|
||||||
if (!node) return JsonVariant::invalid();
|
|
||||||
|
|
||||||
addNode(node);
|
|
||||||
|
|
||||||
return node->content;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonArray &JsonArray::createNestedArray() {
|
|
||||||
if (!_buffer) return JsonArray::invalid();
|
|
||||||
JsonArray &array = _buffer->createArray();
|
|
||||||
add(array);
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonObject &JsonArray::createNestedObject() {
|
|
||||||
if (!_buffer) return JsonObject::invalid();
|
|
||||||
JsonObject &object = _buffer->createObject();
|
|
||||||
add(object);
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonArray::node_type *JsonArray::getNodeAt(int index) const {
|
|
||||||
node_type *node = _firstNode;
|
|
||||||
while (node && index--) node = node->next;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonArray::removeAt(int index) { removeNode(getNodeAt(index)); }
|
|
||||||
|
|
||||||
void JsonArray::writeTo(JsonWriter &writer) const {
|
|
||||||
writer.beginArray();
|
|
||||||
|
|
||||||
const node_type *child = _firstNode;
|
|
||||||
while (child) {
|
|
||||||
child->content.writeTo(writer);
|
|
||||||
|
|
||||||
child = child->next;
|
|
||||||
if (!child) break;
|
|
||||||
|
|
||||||
writer.writeComma();
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.endArray();
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user