forked from bblanchon/ArduinoJson
Compare commits
69 Commits
v6.2.0-bet
...
v6.7.0-bet
Author | SHA1 | Date | |
---|---|---|---|
a5cd1b1693 | |||
d8a1eec530 | |||
e20c47c57b | |||
b77b203935 | |||
1ad97ebf85 | |||
ef12c74771 | |||
0bc03e8071 | |||
04286f3228 | |||
1d942cdf41 | |||
aaf0d5c3c5 | |||
04e8acd844 | |||
8ff48dde73 | |||
41b2e629f7 | |||
a60162ba76 | |||
45f4e5ac20 | |||
637f7a5bfa | |||
399ccec645 | |||
2bd280df80 | |||
c832edbda3 | |||
b8d0041851 | |||
0a97d4c825 | |||
5eee947ffe | |||
720e6548c7 | |||
f375459d53 | |||
e842838a23 | |||
00aa038818 | |||
eb78077a0c | |||
d8d939660b | |||
ae089dcff7 | |||
1a4515c0b9 | |||
4eee8e8bdf | |||
9f1421e0a6 | |||
84f199f0dd | |||
8230f8fc9b | |||
02d809f3f4 | |||
b0560cbd99 | |||
d1003ff6c9 | |||
b11ad4077b | |||
5dc7dc1216 | |||
0d4a93018b | |||
3ca40db9f8 | |||
ce607196d1 | |||
0b3af166ae | |||
39e5660c4a | |||
6b985b2d1f | |||
527dc19794 | |||
29e71cbb16 | |||
2d54019f83 | |||
98c8e8e35a | |||
b106b1ed14 | |||
2998a55f0b | |||
e5c4778ff7 | |||
2ec9569b36 | |||
58303d0837 | |||
e3639918eb | |||
6d290bd001 | |||
7683667b3c | |||
9cbc891816 | |||
0454bd1ef6 | |||
f139100b23 | |||
3f666bd5f0 | |||
d53a93e0ae | |||
2059d610a8 | |||
9bbfbd0a6a | |||
6e4f1dc756 | |||
dc13882624 | |||
6bb17d5896 | |||
fa1a40ac6e | |||
954428e341 |
14
.travis.yml
14
.travis.yml
@ -97,11 +97,19 @@ matrix:
|
||||
- compiler: gcc
|
||||
env: SCRIPT=coverage
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode8.3
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- os: osx
|
||||
osx_image: xcode10
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake SANITIZE=address
|
||||
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
|
||||
@ -117,4 +125,6 @@ matrix:
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- "fuzzing/json_corpus"
|
||||
- "fuzzing/msgpack_corpus"
|
||||
script: scripts/travis/$SCRIPT.sh
|
||||
|
115
CHANGELOG.md
115
CHANGELOG.md
@ -1,10 +1,117 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v6.2.0-beta
|
||||
v6.7.0-beta (2018-12-07)
|
||||
-----------
|
||||
|
||||
* Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity.
|
||||
* Restored the monotonic allocator because the code was getting too big
|
||||
* Reduced the memory usage
|
||||
* Reduced the code size
|
||||
* Renamed `JsonKey` to `JsonString`
|
||||
* Removed spurious files in the Particle library
|
||||
|
||||
v6.6.0-beta (2018-11-13)
|
||||
-----------
|
||||
|
||||
* Removed `JsonArray::is<T>(i)` and `JsonArray::set(i,v)`
|
||||
* Removed `JsonObject::is<T>(k)` and `JsonObject::set(k,v)`
|
||||
* Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)`
|
||||
* Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)`
|
||||
* Added `JSON_STRING_SIZE()`
|
||||
* ~~Replacing or removing a value now releases the memory~~
|
||||
* Added `DeserializationError::code()` to be used in switch statements (issue #846)
|
||||
|
||||
v6.5.0-beta (2018-10-13)
|
||||
-----------
|
||||
|
||||
* Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant`
|
||||
* Allow mixed configuration in compilation units (issue #809)
|
||||
* Fixed object keys not being duplicated
|
||||
* `JsonPair::key()` now returns a `JsonKey`
|
||||
* Increased the default capacity of `DynamicJsonDocument`
|
||||
* Fixed `JsonVariant::is<String>()` (closes #763)
|
||||
* Added `JsonArrayConst`, `JsonObjectConst`, and `JsonVariantConst`
|
||||
* Added copy-constructor and copy-assignment-operator for `JsonDocument` (issue #827)
|
||||
|
||||
v6.4.0-beta (2018-09-11)
|
||||
-----------
|
||||
|
||||
* Copy `JsonArray` and `JsonObject`, instead of storing pointers (issue #780)
|
||||
* Added `JsonVariant::to<JsonArray>()` and `JsonVariant::to<JsonObject>()`
|
||||
|
||||
v6.3.0-beta (2018-08-31)
|
||||
-----------
|
||||
|
||||
* Implemented reference semantics for `JsonVariant`
|
||||
* Replaced `JsonPair`'s `key` and `value` with `key()` and `value()`
|
||||
* Fixed `serializeJson(obj[key], dst)` (issue #794)
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### JsonVariant
|
||||
>
|
||||
> `JsonVariant` now has a semantic similar to `JsonObject` and `JsonArray`.
|
||||
> It's a reference to a value stored in the `JsonDocument`.
|
||||
> As a consequence, a `JsonVariant` cannot be used as a standalone variable anymore.
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonVariant myValue = 42;
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> JsonVariant myValue = doc.to<JsonVariant>();
|
||||
> myValue.set(42);
|
||||
> ```
|
||||
>
|
||||
> #### JsonPair
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> for(JsonPair p : myObject) {
|
||||
> Serial.println(p.key);
|
||||
> Serial.println(p.value.as<int>());
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> for(JsonPair p : myObject) {
|
||||
> Serial.println(p.key());
|
||||
> Serial.println(p.value().as<int>());
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> CAUTION: the key is now read only!
|
||||
|
||||
v6.2.3-beta (2018-07-19)
|
||||
-----------
|
||||
|
||||
* Fixed exception when using Flash strings as object keys (issue #784)
|
||||
|
||||
v6.2.2-beta (2018-07-18)
|
||||
-----------
|
||||
|
||||
* Fixed `invalid application of 'sizeof' to incomplete type '__FlashStringHelper'` (issue #783)
|
||||
* Fixed `char[]` not duplicated when passed to `JsonVariant::operator[]`
|
||||
|
||||
v6.2.1-beta (2018-07-17)
|
||||
-----------
|
||||
|
||||
* Fixed `JsonObject` not inserting keys of type `String` (issue #782)
|
||||
|
||||
v6.2.0-beta (2018-07-12)
|
||||
-----------
|
||||
|
||||
* Disabled lazy number deserialization (issue #772)
|
||||
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
|
||||
* Improved float serialization when `-fsingle-precision-constant` is used
|
||||
* Renamed function `RawJson()` to `serialized()`
|
||||
* `serializeMsgPack()` now supports values marked with `serialized()`
|
||||
@ -30,7 +137,7 @@ v6.2.0-beta
|
||||
> object["values"] = serialized("[1,2,3,4]");
|
||||
> ```
|
||||
|
||||
v6.1.0-beta
|
||||
v6.1.0-beta (2018-07-02)
|
||||
-----------
|
||||
|
||||
* Return `JsonArray` and `JsonObject` by value instead of reference (issue #309)
|
||||
@ -60,12 +167,12 @@ v6.1.0-beta
|
||||
> }
|
||||
> ```
|
||||
|
||||
v6.0.1-beta
|
||||
v6.0.1-beta (2018-06-11)
|
||||
-----------
|
||||
|
||||
* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752)
|
||||
|
||||
v6.0.0-beta
|
||||
v6.0.0-beta (2018-06-07)
|
||||
-----------
|
||||
|
||||
* Added `DynamicJsonDocument` and `StaticJsonDocument`
|
||||
|
@ -7,10 +7,16 @@ project(ArduinoJson)
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_definitions(-DARDUINOJSON_DEBUG)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
add_compile_options(-g -O0)
|
||||
endif()
|
||||
|
||||
if(${COVERAGE})
|
||||
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
add_subdirectory(third-party/catch)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(fuzzing)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
---
|
||||
|
||||
[](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)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=6.x) [](https://github.com/bblanchon/ArduinoJson)
|
||||
|
||||
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 6.0.1.{build}
|
||||
version: 6.4.0.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
@ -19,9 +19,9 @@ void setup() {
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject doc(200);
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// JSON input string.
|
||||
//
|
||||
|
17
fuzzing/CMakeLists.txt
Normal file
17
fuzzing/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2018
|
||||
# MIT License
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
add_executable(msgpack_fuzzer
|
||||
msgpack_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
)
|
||||
|
||||
add_executable(json_fuzzer
|
||||
json_fuzzer.cpp
|
||||
fuzzer_main.cpp
|
||||
)
|
@ -1,6 +1,6 @@
|
||||
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
|
||||
|
||||
CXXFLAGS += -I../src
|
||||
CXXFLAGS += -I../src -DARDUINOJSON_DEBUG
|
||||
|
||||
all: \
|
||||
$(OUT)/json_fuzzer \
|
||||
|
50
fuzzing/fuzzer_main.cpp
Normal file
50
fuzzing/fuzzer_main.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
// This file is NOT use by Google's OSS fuzz
|
||||
// I only use it to reproduce the bugs found
|
||||
|
||||
#include <stdint.h> // size_t
|
||||
#include <stdio.h> // fopen et al.
|
||||
#include <stdlib.h> // exit
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
|
||||
|
||||
std::vector<uint8_t> read(const char* path) {
|
||||
FILE* f = fopen(path, "rb");
|
||||
if (!f) {
|
||||
std::cerr << "Failed to open " << path << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
std::vector<uint8_t> buffer(size);
|
||||
if (fread(buffer.data(), 1, size, f) != size) {
|
||||
fclose(f);
|
||||
std::cerr << "Failed to read " << path << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Usage: msgpack_fuzzer files" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
std::cout << "Loading " << argv[i] << std::endl;
|
||||
std::vector<uint8_t> buffer = read(argv[i]);
|
||||
LLVMFuzzerTestOneInput(buffer.data(), buffer.size());
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"version": "6.2.0-beta",
|
||||
"version": "6.7.0-beta",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "https://blog.benoitblanchon.fr"
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=ArduinoJson
|
||||
version=6.2.0-beta
|
||||
version=6.7.0-beta
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
|
@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
OUTPUT="$(pwd)/sizes.csv"
|
||||
|
||||
echo "Tag;Date;Parser;Generator" > $OUTPUT
|
||||
|
||||
cd $(dirname $(dirname $0))
|
||||
|
||||
git tag | while read TAG
|
||||
do
|
||||
|
||||
git checkout -q tags/$TAG
|
||||
|
||||
DATE=$(git log -1 --date=short --pretty=format:%cd)
|
||||
PARSER_SIZE=$(arduino --verify examples/JsonParserExample/JsonParserExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
|
||||
if [ -e 'examples/JsonGeneratorExample/JsonGeneratorExample.ino' ]; then
|
||||
GENERATOR_SIZE=$(arduino --verify examples/JsonGeneratorExample/JsonGeneratorExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
else
|
||||
GENERATOR_SIZE=""
|
||||
fi
|
||||
|
||||
echo $TAG
|
||||
if [ ! -z "$PARSER_SIZE" ]
|
||||
then
|
||||
echo "JsonParserExample = $PARSER_SIZE bytes"
|
||||
else
|
||||
echo "JsonParserExample compilation failed."
|
||||
fi
|
||||
|
||||
if [ ! -z "$GENERATOR_SIZE" ]
|
||||
then
|
||||
echo "JsonGeneratorExample = $GENERATOR_SIZE bytes"
|
||||
else
|
||||
echo "JsonGeneratorExample compilation failed."
|
||||
fi
|
||||
|
||||
echo "$TAG;$DATE;$PARSER_SIZE;$GENERATOR_SIZE" >> $OUTPUT
|
||||
|
||||
done
|
18
scripts/publish-particle-library.sh
Normal file
18
scripts/publish-particle-library.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
SOURCE_DIR="$(dirname "$0")/.."
|
||||
WORK_DIR=$(mktemp -d)
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
cp "$SOURCE_DIR/README.md" "$WORK_DIR/README.md"
|
||||
cp "$SOURCE_DIR/CHANGELOG.md" "$WORK_DIR/CHANGELOG.md"
|
||||
cp "$SOURCE_DIR/library.properties" "$WORK_DIR/library.properties"
|
||||
cp "$SOURCE_DIR/LICENSE.md" "$WORK_DIR/LICENSE.txt"
|
||||
cp -r "$SOURCE_DIR/src" "$WORK_DIR/"
|
||||
cp -r "$SOURCE_DIR/examples" "$WORK_DIR/"
|
||||
|
||||
cd "$WORK_DIR"
|
||||
particle library upload
|
||||
particle library publish
|
53
scripts/publish.sh
Normal file
53
scripts/publish.sh
Normal file
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
VERSION="$1"
|
||||
DATE=$(date +%F)
|
||||
TAG="v$VERSION"
|
||||
|
||||
update_version_in_source () {
|
||||
IFS=".-" read MAJOR MINOR REVISION EXTRA < <(echo "$VERSION")
|
||||
UNDERLINE=$(printf -- '-%.0s' $(seq 1 ${#TAG}))
|
||||
|
||||
sed -i~ -bE "4s/HEAD/$TAG ($DATE)/; 5s/-+/$UNDERLINE/" CHANGELOG.md
|
||||
rm CHANGELOG.md*~
|
||||
sed -i~ -bE "s/\"version\":.*$/\"version\": \"$VERSION\",/" library.json
|
||||
rm library.json*~
|
||||
|
||||
sed -i~ -bE "s/version=.*$/version=$VERSION/" library.properties
|
||||
rm library.properties*~
|
||||
|
||||
sed -i~ -bE \
|
||||
-e "s/ARDUINOJSON_VERSION .*$/ARDUINOJSON_VERSION \"$VERSION\"/" \
|
||||
-e "s/ARDUINOJSON_VERSION_MAJOR .*$/ARDUINOJSON_VERSION_MAJOR $MAJOR/" \
|
||||
-e "s/ARDUINOJSON_VERSION_MINOR .*$/ARDUINOJSON_VERSION_MINOR $MINOR/" \
|
||||
-e "s/ARDUINOJSON_VERSION_REVISION .*$/ARDUINOJSON_VERSION_REVISION $REVISION/" \
|
||||
src/ArduinoJson/version.hpp
|
||||
rm src/ArduinoJson/version.hpp*~
|
||||
}
|
||||
|
||||
commit_new_version () {
|
||||
git add src/ArduinoJson/version.hpp CHANGELOG.md library.json library.properties
|
||||
git commit -m "Set version to $VERSION"
|
||||
}
|
||||
|
||||
add_tag () {
|
||||
CHANGES=$(awk '/\* /{ FOUND=1; print; next } { if (FOUND) exit}' CHANGELOG.md)
|
||||
git tag -m "ArduinoJson $VERSION"$'\n'"$CHANGES" "$TAG"
|
||||
}
|
||||
|
||||
push () {
|
||||
git push --follow-tags
|
||||
}
|
||||
|
||||
update_version_in_source
|
||||
commit_new_version
|
||||
add_tag
|
||||
push
|
||||
|
||||
scripts/build-arduino-package.sh
|
||||
scripts/build-single-header.sh
|
||||
scripts/wandbox/publish.sh "../ArduinoJson-$TAG.h"
|
@ -16,7 +16,7 @@ fuzz() {
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30 -timeout=1
|
||||
|
||||
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER}.profdata
|
||||
llvm-cov-${CLANG} report ./${FUZZER} -instr-profile=${FUZZER}.profdata
|
||||
|
57
scripts/wandbox/JsonGeneratorExample.cpp
Normal file
57
scripts/wandbox/JsonGeneratorExample.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// The JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the RAM allocated to this document.
|
||||
// Don't forget to change this value to match your requirement.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// Make our document be an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
|
||||
// Add values in the object
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do root.set<long>("time", 1351824120);
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
// Add an array.
|
||||
//
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
serializeJson(root, std::cout);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
serializeJsonPretty(root, std::cout);
|
||||
// This prints:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [
|
||||
// 48.756080,
|
||||
// 2.302038
|
||||
// ]
|
||||
// }
|
||||
|
||||
return 0;
|
||||
}
|
59
scripts/wandbox/JsonParserExample.cpp
Normal file
59
scripts/wandbox/JsonParserExample.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// Root JSON object
|
||||
//
|
||||
// Inside the brackets, 300 is the size of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<300> doc;
|
||||
|
||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject doc(200);
|
||||
|
||||
// JSON input string.
|
||||
//
|
||||
// It's better to use a char[] as shown here.
|
||||
// If you use a const char* or a String, ArduinoJson will
|
||||
// have to make a copy of the input in the JsonBuffer.
|
||||
char json[] =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, json);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
std::cerr << "deserializeJson() failed: " << error.c_str() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
// Print values.
|
||||
std::cout << sensor << std::endl;
|
||||
std::cout << time << std::endl;
|
||||
std::cout << latitude << std::endl;
|
||||
std::cout << longitude << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
71
scripts/wandbox/MsgPackParserExample.cpp
Normal file
71
scripts/wandbox/MsgPackParserExample.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
|
||||
#include <iostream>
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
int main() {
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 300 is the size of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<300> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject doc(200);
|
||||
|
||||
// MessagePack input string.
|
||||
//
|
||||
// It's better to use a char[] as shown here.
|
||||
// If you use a const char* or a String, ArduinoJson will
|
||||
// have to make a copy of the input in the JsonBuffer.
|
||||
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
|
||||
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
|
||||
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
|
||||
112, 203, 64, 2, 106, 146, 230, 33, 49, 169};
|
||||
// This MessagePack document contains:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [48.75608, 2.302038]
|
||||
// }
|
||||
|
||||
// doc of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
DeserializationError error = deserializeMsgPack(doc, input);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
std::cerr << "deserializeMsgPack() failed: " << error.c_str() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
// Print values.
|
||||
std::cout << sensor << std::endl;
|
||||
std::cout << time << std::endl;
|
||||
std::cout << latitude << std::endl;
|
||||
std::cout << longitude << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
29
scripts/wandbox/publish.sh
Normal file
29
scripts/wandbox/publish.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
ARDUINOJSON_H="$1"
|
||||
|
||||
read_string() {
|
||||
jq --slurp --raw-input '.' "$1"
|
||||
}
|
||||
|
||||
compile() {
|
||||
FILE_PATH="$(dirname $0)/$1.cpp"
|
||||
cat >parameters.json <<END
|
||||
{
|
||||
"code":$(read_string "$FILE_PATH"),
|
||||
"codes": [{"file":"ArduinoJson.h","code":$(read_string "$ARDUINOJSON_H")}],
|
||||
"options": "warning",
|
||||
"compiler": "gcc-4.9.3",
|
||||
"save": true
|
||||
}
|
||||
END
|
||||
URL=$(curl -sS -H "Content-type: application/json" -d @parameters.json https://wandbox.org/api/compile.json | jq --raw-output .url)
|
||||
rm parameters.json
|
||||
echo " $1: $URL"
|
||||
}
|
||||
|
||||
compile "JsonGeneratorExample"
|
||||
compile "JsonParserExample"
|
||||
compile "MsgPackParserExample"
|
@ -4,23 +4,43 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/version.hpp"
|
||||
#include "ArduinoJson/Namespace.hpp"
|
||||
|
||||
#include "ArduinoJson/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/StaticJsonDocument.hpp"
|
||||
#include "ArduinoJson/Array/ArrayRef.hpp"
|
||||
#include "ArduinoJson/Object/ObjectRef.hpp"
|
||||
#include "ArduinoJson/Variant/VariantRef.hpp"
|
||||
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
|
||||
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonArraySubscript.hpp"
|
||||
#include "ArduinoJson/JsonObjectSubscript.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Array/ArrayImpl.hpp"
|
||||
#include "ArduinoJson/Array/ArraySubscript.hpp"
|
||||
#include "ArduinoJson/Collection/CollectionImpl.hpp"
|
||||
#include "ArduinoJson/Object/ObjectImpl.hpp"
|
||||
#include "ArduinoJson/Object/ObjectSubscript.hpp"
|
||||
#include "ArduinoJson/Variant/VariantAsImpl.hpp"
|
||||
#include "ArduinoJson/Variant/VariantImpl.hpp"
|
||||
|
||||
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
||||
#include "ArduinoJson/Json/JsonSerializer.hpp"
|
||||
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
|
||||
typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
|
||||
typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
|
||||
typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
|
||||
typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
|
||||
typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
|
||||
typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
|
||||
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
|
||||
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
|
||||
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
|
||||
typedef ARDUINOJSON_NAMESPACE::String JsonString;
|
||||
using ARDUINOJSON_NAMESPACE::DeserializationError;
|
||||
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
|
||||
using ARDUINOJSON_NAMESPACE::serialized;
|
||||
using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
|
||||
} // namespace ArduinoJson
|
||||
|
29
src/ArduinoJson/Array/ArrayFunctions.hpp
Normal file
29
src/ArduinoJson/Array/ArrayFunctions.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Collection/CollectionData.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) {
|
||||
return arr ? arr->add(pool) : 0;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
inline void arrayAccept(const CollectionData *arr, Visitor &visitor) {
|
||||
if (arr)
|
||||
visitor.visitArray(*arr);
|
||||
else
|
||||
visitor.visitNull();
|
||||
}
|
||||
|
||||
inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
|
||||
if (lhs == rhs) return true;
|
||||
if (!lhs || !rhs) return false;
|
||||
|
||||
return lhs->equalsArray(*rhs);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
19
src/ArduinoJson/Array/ArrayImpl.hpp
Normal file
19
src/ArduinoJson/Array/ArrayImpl.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Object/ObjectRef.hpp"
|
||||
#include "ArrayRef.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline ArrayRef ArrayRef::createNestedArray() const {
|
||||
return add().to<ArrayRef>();
|
||||
}
|
||||
|
||||
inline ObjectRef ArrayRef::createNestedObject() const {
|
||||
return add().to<ObjectRef>();
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
121
src/ArduinoJson/Array/ArrayIterator.hpp
Normal file
121
src/ArduinoJson/Array/ArrayIterator.hpp
Normal file
@ -0,0 +1,121 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Variant/SlotFunctions.hpp"
|
||||
#include "../Variant/VariantRef.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class VariantPtr {
|
||||
public:
|
||||
VariantPtr(MemoryPool *pool, VariantData *data) : _variant(pool, data) {}
|
||||
|
||||
VariantRef *operator->() {
|
||||
return &_variant;
|
||||
}
|
||||
|
||||
VariantRef &operator*() {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
private:
|
||||
VariantRef _variant;
|
||||
};
|
||||
|
||||
class ArrayIterator {
|
||||
public:
|
||||
ArrayIterator() : _slot(0) {}
|
||||
explicit ArrayIterator(MemoryPool *pool, VariantSlot *slot)
|
||||
: _pool(pool), _slot(slot) {}
|
||||
|
||||
VariantRef operator*() const {
|
||||
return VariantRef(_pool, _slot->data());
|
||||
}
|
||||
VariantPtr operator->() {
|
||||
return VariantPtr(_pool, _slot->data());
|
||||
}
|
||||
|
||||
bool operator==(const ArrayIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const ArrayIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
ArrayIterator &operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArrayIterator &operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
VariantSlot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool *_pool;
|
||||
VariantSlot *_slot;
|
||||
};
|
||||
|
||||
class VariantConstPtr {
|
||||
public:
|
||||
VariantConstPtr(const VariantData *data) : _variant(data) {}
|
||||
|
||||
VariantConstRef *operator->() {
|
||||
return &_variant;
|
||||
}
|
||||
|
||||
VariantConstRef &operator*() {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
private:
|
||||
VariantConstRef _variant;
|
||||
};
|
||||
|
||||
class ArrayConstRefIterator {
|
||||
public:
|
||||
ArrayConstRefIterator() : _slot(0) {}
|
||||
explicit ArrayConstRefIterator(const VariantSlot *slot) : _slot(slot) {}
|
||||
|
||||
VariantConstRef operator*() const {
|
||||
return VariantConstRef(_slot->data());
|
||||
}
|
||||
VariantConstPtr operator->() {
|
||||
return VariantConstPtr(_slot->data());
|
||||
}
|
||||
|
||||
bool operator==(const ArrayConstRefIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const ArrayConstRefIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
ArrayConstRefIterator &operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ArrayConstRefIterator &operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const VariantSlot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
const VariantSlot *_slot;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
211
src/ArduinoJson/Array/ArrayRef.hpp
Normal file
211
src/ArduinoJson/Array/ArrayRef.hpp
Normal file
@ -0,0 +1,211 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Variant/VariantData.hpp"
|
||||
#include "ArrayFunctions.hpp"
|
||||
#include "ArrayIterator.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
// Can be very handy to determine the size of a StaticMemoryPool.
|
||||
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class ObjectRef;
|
||||
class ArraySubscript;
|
||||
|
||||
template <typename TData>
|
||||
class ArrayRefBase {
|
||||
public:
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
arrayAccept(_data, visitor);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantConstRef operator[](size_t index) const {
|
||||
return VariantConstRef(_data ? _data->get(index) : 0);
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return _data ? _data->size() : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
ArrayRefBase(TData* data) : _data(data) {}
|
||||
TData* _data;
|
||||
};
|
||||
|
||||
class ArrayConstRef : public ArrayRefBase<const CollectionData>,
|
||||
public Visitable {
|
||||
friend class ArrayRef;
|
||||
typedef ArrayRefBase<const CollectionData> base_type;
|
||||
|
||||
public:
|
||||
typedef ArrayConstRefIterator iterator;
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_data->head());
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
FORCE_INLINE ArrayConstRef() : base_type(0) {}
|
||||
FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {}
|
||||
|
||||
FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
|
||||
return arrayEquals(_data, rhs._data);
|
||||
}
|
||||
};
|
||||
|
||||
class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
|
||||
typedef ArrayRefBase<CollectionData> base_type;
|
||||
|
||||
public:
|
||||
typedef ArrayIterator iterator;
|
||||
|
||||
FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {}
|
||||
FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data)
|
||||
: base_type(data), _pool(pool) {}
|
||||
|
||||
operator VariantRef() {
|
||||
return VariantRef(_pool, reinterpret_cast<VariantData*>(_data));
|
||||
}
|
||||
|
||||
operator ArrayConstRef() const {
|
||||
return ArrayConstRef(_data);
|
||||
}
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||
// std::string, String, ObjectRef
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(const T& value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
// Adds the specified value at the end of the array.
|
||||
FORCE_INLINE bool add(ArrayRef value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(T* value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
|
||||
VariantRef add() const {
|
||||
return VariantRef(_pool, arrayAdd(_data, _pool));
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_pool, _data->head());
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T, size_t N>
|
||||
FORCE_INLINE bool copyFrom(T (&array)[N]) const {
|
||||
return copyFrom(array, N);
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T>
|
||||
bool copyFrom(T* array, size_t len) const {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ok &= add(array[i]);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Imports a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
bool copyFrom(T (&array)[N1][N2]) const {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < N1; i++) {
|
||||
ArrayRef nestedArray = createNestedArray();
|
||||
for (size_t j = 0; j < N2; j++) {
|
||||
ok &= nestedArray.add(array[i][j]);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Copy a ArrayRef
|
||||
FORCE_INLINE bool copyFrom(ArrayRef src) const {
|
||||
if (!_data || !src._data) return false;
|
||||
return _data->copyFrom(*src._data, _pool);
|
||||
}
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T, size_t N>
|
||||
FORCE_INLINE size_t copyTo(T (&array)[N]) const {
|
||||
return copyTo(array, N);
|
||||
}
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T>
|
||||
size_t copyTo(T* array, size_t len) const {
|
||||
size_t i = 0;
|
||||
for (iterator it = begin(); it != end() && i < len; ++it) array[i++] = *it;
|
||||
return i;
|
||||
}
|
||||
|
||||
// Exports a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
void copyTo(T (&array)[N1][N2]) const {
|
||||
if (!_data) return;
|
||||
size_t i = 0;
|
||||
for (iterator it = begin(); it != end() && i < N1; ++it) {
|
||||
it->as<ArrayRef>().copyTo(array[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE ArrayRef createNestedArray() const;
|
||||
FORCE_INLINE ObjectRef createNestedObject() const;
|
||||
|
||||
FORCE_INLINE ArraySubscript operator[](size_t index) const;
|
||||
|
||||
FORCE_INLINE bool operator==(ArrayRef rhs) const {
|
||||
return arrayEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
// Gets the value at the specified index.
|
||||
FORCE_INLINE VariantRef get(size_t index) const {
|
||||
return VariantRef(_pool, _data ? _data->get(index) : 0);
|
||||
}
|
||||
|
||||
// Removes element at specified position.
|
||||
FORCE_INLINE void remove(iterator it) const {
|
||||
if (!_data) return;
|
||||
_data->remove(it.internal());
|
||||
}
|
||||
|
||||
// Removes element at specified index.
|
||||
FORCE_INLINE void remove(size_t index) const {
|
||||
if (!_data) return;
|
||||
_data->remove(index);
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool* _pool;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
112
src/ArduinoJson/Array/ArraySubscript.hpp
Normal file
112
src/ArduinoJson/Array/ArraySubscript.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Operators/VariantOperators.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class ArraySubscript : public VariantOperators<ArraySubscript>,
|
||||
public Visitable {
|
||||
public:
|
||||
FORCE_INLINE ArraySubscript(ArrayRef array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
FORCE_INLINE ArraySubscript& operator=(const ArraySubscript& src) {
|
||||
get_impl().set(src.as<VariantConstRef>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// operator=(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename T>
|
||||
FORCE_INLINE ArraySubscript& operator=(const T& src) {
|
||||
get_impl().set(src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue)
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE ArraySubscript& operator=(T* src) {
|
||||
get_impl().set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return get_impl().isNull();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename VariantAs<T>::type as() const {
|
||||
return get_impl().as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is() const {
|
||||
return get_impl().is<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename VariantTo<T>::type to() const {
|
||||
return get_impl().to<T>();
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// bool set(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue& value) const {
|
||||
return get_impl().set(value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue)
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue* value) const {
|
||||
return get_impl().set(value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor& visitor) const {
|
||||
return get_impl().accept(visitor);
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return get_impl().size();
|
||||
}
|
||||
|
||||
private:
|
||||
FORCE_INLINE VariantRef get_impl() const {
|
||||
return _array.get(_index);
|
||||
}
|
||||
|
||||
ArrayRef _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
inline ArraySubscript VariantSubscripts<TImpl>::operator[](size_t index) const {
|
||||
return impl()->template as<ArrayRef>()[index];
|
||||
}
|
||||
|
||||
inline ArraySubscript ArrayRef::operator[](size_t index) const {
|
||||
return ArraySubscript(*this, index);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
68
src/ArduinoJson/Collection/CollectionData.hpp
Normal file
68
src/ArduinoJson/Collection/CollectionData.hpp
Normal file
@ -0,0 +1,68 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class MemoryPool;
|
||||
class VariantData;
|
||||
class VariantSlot;
|
||||
|
||||
class CollectionData {
|
||||
VariantSlot *_head;
|
||||
VariantSlot *_tail;
|
||||
|
||||
public:
|
||||
// Must be a POD!
|
||||
// - no constructor
|
||||
// - no destructor
|
||||
// - no virtual
|
||||
// - no inheritance
|
||||
VariantSlot *addSlot(MemoryPool *);
|
||||
|
||||
VariantData *add(MemoryPool *pool);
|
||||
|
||||
template <typename TKey>
|
||||
VariantData *add(TKey key, MemoryPool *pool);
|
||||
|
||||
void clear();
|
||||
|
||||
template <typename TKey>
|
||||
bool containsKey(const TKey &key) const;
|
||||
|
||||
bool copyFrom(const CollectionData &src, MemoryPool *pool);
|
||||
|
||||
bool equalsArray(const CollectionData &other) const;
|
||||
bool equalsObject(const CollectionData &other) const;
|
||||
|
||||
VariantData *get(size_t index) const;
|
||||
|
||||
template <typename TKey>
|
||||
VariantData *get(TKey key) const;
|
||||
|
||||
VariantSlot *head() const {
|
||||
return _head;
|
||||
}
|
||||
|
||||
void remove(size_t index);
|
||||
|
||||
template <typename TKey>
|
||||
void remove(TKey key) {
|
||||
remove(getSlot(key));
|
||||
}
|
||||
|
||||
void remove(VariantSlot *slot);
|
||||
|
||||
size_t size() const;
|
||||
|
||||
private:
|
||||
VariantSlot *getSlot(size_t index) const;
|
||||
|
||||
template <typename TKey>
|
||||
VariantSlot *getSlot(TKey key) const;
|
||||
|
||||
VariantSlot *getPreviousSlot(VariantSlot *) const;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
145
src/ArduinoJson/Collection/CollectionImpl.hpp
Normal file
145
src/ArduinoJson/Collection/CollectionImpl.hpp
Normal file
@ -0,0 +1,145 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Variant/VariantData.hpp"
|
||||
#include "CollectionData.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
|
||||
VariantSlot* slot = pool->allocVariant();
|
||||
if (!slot) return 0;
|
||||
|
||||
if (_tail) {
|
||||
_tail->setNextNotNull(slot);
|
||||
_tail = slot;
|
||||
} else {
|
||||
_head = slot;
|
||||
_tail = slot;
|
||||
}
|
||||
|
||||
slot->clear();
|
||||
return slot;
|
||||
}
|
||||
|
||||
inline VariantData* CollectionData::add(MemoryPool* pool) {
|
||||
return addSlot(pool)->data();
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline VariantData* CollectionData::add(TKey key, MemoryPool* pool) {
|
||||
VariantSlot* slot = addSlot(pool);
|
||||
if (!slotSetKey(slot, key, pool)) return 0;
|
||||
return slot->data();
|
||||
}
|
||||
|
||||
inline void CollectionData::clear() {
|
||||
_head = 0;
|
||||
_tail = 0;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline bool CollectionData::containsKey(const TKey& key) const {
|
||||
return getSlot(key) != 0;
|
||||
}
|
||||
|
||||
inline bool CollectionData::copyFrom(const CollectionData& src,
|
||||
MemoryPool* pool) {
|
||||
clear();
|
||||
for (VariantSlot* s = src._head; s; s = s->next()) {
|
||||
VariantData* var;
|
||||
if (s->key() != 0) {
|
||||
if (s->ownsKey())
|
||||
var = add(RamStringWrapper(s->key()), pool);
|
||||
else
|
||||
var = add(ConstRamStringWrapper(s->key()), pool);
|
||||
} else {
|
||||
var = add(pool);
|
||||
}
|
||||
if (!var) return false;
|
||||
if (!var->copyFrom(*s->data(), pool)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool CollectionData::equalsObject(const CollectionData& other) const {
|
||||
size_t count = 0;
|
||||
for (VariantSlot* slot = _head; slot; slot = slot->next()) {
|
||||
VariantData* v1 = slot->data();
|
||||
VariantData* v2 = other.get(wrapString(slot->key()));
|
||||
if (!variantEquals(v1, v2)) return false;
|
||||
count++;
|
||||
}
|
||||
return count == other.size();
|
||||
}
|
||||
|
||||
inline bool CollectionData::equalsArray(const CollectionData& other) const {
|
||||
VariantSlot* s1 = _head;
|
||||
VariantSlot* s2 = other._head;
|
||||
for (;;) {
|
||||
if (s1 == s2) return true;
|
||||
if (!s1 || !s2) return false;
|
||||
if (!variantEquals(s1->data(), s2->data())) return false;
|
||||
s1 = s1->next();
|
||||
s2 = s2->next();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline VariantSlot* CollectionData::getSlot(TKey key) const {
|
||||
VariantSlot* slot = _head;
|
||||
while (slot) {
|
||||
if (key.equals(slot->key())) break;
|
||||
slot = slot->next();
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
inline VariantSlot* CollectionData::getSlot(size_t index) const {
|
||||
return _head->next(index);
|
||||
}
|
||||
|
||||
inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
|
||||
VariantSlot* current = _head;
|
||||
while (current) {
|
||||
VariantSlot* next = current->next();
|
||||
if (next == target) return current;
|
||||
current = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline VariantData* CollectionData::get(TKey key) const {
|
||||
VariantSlot* slot = getSlot(key);
|
||||
return slot ? slot->data() : 0;
|
||||
}
|
||||
|
||||
inline VariantData* CollectionData::get(size_t index) const {
|
||||
VariantSlot* slot = getSlot(index);
|
||||
return slot ? slot->data() : 0;
|
||||
}
|
||||
|
||||
inline void CollectionData::remove(VariantSlot* slot) {
|
||||
if (!slot) return;
|
||||
VariantSlot* prev = getPreviousSlot(slot);
|
||||
VariantSlot* next = slot->next();
|
||||
if (prev)
|
||||
prev->setNext(next);
|
||||
else
|
||||
_head = next;
|
||||
if (!next) _tail = prev;
|
||||
}
|
||||
|
||||
inline void CollectionData::remove(size_t index) {
|
||||
remove(getSlot(index));
|
||||
}
|
||||
|
||||
inline size_t CollectionData::size() const {
|
||||
return slotSize(_head);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -4,6 +4,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ARDUINOJSON_HAS_INT64 1
|
||||
#else
|
||||
#define ARDUINOJSON_HAS_INT64 0
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#define ARDUINOJSON_HAS_LONG_LONG 1
|
||||
#else
|
||||
#define ARDUINOJSON_HAS_LONG_LONG 0
|
||||
#endif
|
||||
|
||||
// Small or big machine?
|
||||
#ifndef ARDUINOJSON_EMBEDDED_MODE
|
||||
#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
|
||||
@ -25,9 +37,6 @@
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
|
||||
// Embedded systems usually don't have std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
@ -44,6 +53,11 @@
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
|
||||
#endif
|
||||
|
||||
// Default capacity for DynamicJsonDocument
|
||||
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
|
||||
#define ARDUINOJSON_DEFAULT_POOL_SIZE 1024
|
||||
#endif
|
||||
|
||||
#else // ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
// On a computer we have plenty of memory so we can use doubles
|
||||
@ -53,22 +67,13 @@
|
||||
|
||||
// Use long long when available
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64
|
||||
#define ARDUINOJSON_USE_LONG_LONG 1
|
||||
#else
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Use _int64 on old versions of Visual Studio
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
#define ARDUINOJSON_USE_INT64 1
|
||||
#else
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// On a computer, we can use std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
#define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||
@ -84,6 +89,11 @@
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
|
||||
#endif
|
||||
|
||||
// Default capacity for DynamicJsonDocument
|
||||
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
|
||||
#define ARDUINOJSON_DEFAULT_POOL_SIZE 16384
|
||||
#endif
|
||||
|
||||
#endif // ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
#ifdef ARDUINO
|
||||
@ -120,16 +130,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
// alignment isn't needed for 8-bit AVR
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
|
||||
#else
|
||||
// but most processors need pointers to be align on word size
|
||||
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Control the exponentiation threshold for big numbers
|
||||
// CAUTION: cannot be more that 1e9 !!!!
|
||||
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
|
||||
@ -141,10 +141,6 @@
|
||||
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
|
||||
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_LITTLE_ENDIAN
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
|
||||
|
@ -1,17 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class JsonVariantTag {};
|
||||
|
||||
template <typename T>
|
||||
struct IsVariant : is_base_of<JsonVariantTag, T> {};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,23 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
typedef long long JsonInteger;
|
||||
typedef unsigned long long JsonUInt;
|
||||
#elif ARDUINOJSON_USE_INT64
|
||||
typedef __int64 JsonInteger;
|
||||
typedef unsigned _int64 JsonUInt;
|
||||
#else
|
||||
typedef long JsonInteger;
|
||||
typedef unsigned long JsonUInt;
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// JsonVariant::as<T>()
|
||||
template <typename T>
|
||||
struct JsonVariantAs {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<char*> {
|
||||
typedef const char* type;
|
||||
};
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,30 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
// Forward declarations
|
||||
struct JsonArrayData;
|
||||
struct JsonObjectData;
|
||||
|
||||
// A union that defines the actual content of a JsonVariant.
|
||||
// The enum JsonVariantType determines which member is in use.
|
||||
union JsonVariantContent {
|
||||
JsonFloat asFloat; // used for double and float
|
||||
JsonUInt asInteger; // used for bool, char, short, int and longs
|
||||
JsonArrayData* asArray; // asArray cannot be null
|
||||
JsonObjectData* asObject; // asObject cannot be null
|
||||
const char* asString; // asString can be null
|
||||
struct {
|
||||
const char* data;
|
||||
size_t size;
|
||||
} asRaw;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,23 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault {
|
||||
static T get() {
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_UNDEFINED, // JsonVariant has not been initialized
|
||||
JSON_UNPARSED, // JsonVariant contains an unparsed string
|
||||
JSON_STRING, // JsonVariant stores a const char*
|
||||
JSON_BOOLEAN, // JsonVariant stores a bool
|
||||
JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt
|
||||
JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated
|
||||
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArrayData
|
||||
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObjectData
|
||||
JSON_FLOAT // JsonVariant stores a JsonFloat
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,88 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListIterator.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A singly linked list of T.
|
||||
// The linked list is composed of ListNode<T>.
|
||||
// It is derived by JsonArrayData and JsonObjectData
|
||||
template <typename T>
|
||||
class List {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ListNode<T> node_type;
|
||||
typedef ListIterator<T> iterator;
|
||||
typedef ListConstIterator<T> const_iterator;
|
||||
|
||||
explicit List(JsonBuffer *buf) : _buffer(buf), _firstNode(NULL) {}
|
||||
|
||||
// Returns the numbers of elements in the list.
|
||||
// For a JsonObjectData, it would return the number of key-value pairs
|
||||
size_t size() const {
|
||||
size_t nodeCount = 0;
|
||||
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
iterator add() {
|
||||
node_type *newNode = new (_buffer) node_type();
|
||||
|
||||
if (_firstNode) {
|
||||
node_type *lastNode = _firstNode;
|
||||
while (lastNode->next) lastNode = lastNode->next;
|
||||
lastNode->next = newNode;
|
||||
} else {
|
||||
_firstNode = newNode;
|
||||
}
|
||||
|
||||
return iterator(newNode);
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return iterator(_firstNode);
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(NULL);
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return const_iterator(_firstNode);
|
||||
}
|
||||
const_iterator end() const {
|
||||
return const_iterator(NULL);
|
||||
}
|
||||
|
||||
void remove(iterator it) {
|
||||
node_type *nodeToRemove = it._node;
|
||||
if (!nodeToRemove) return;
|
||||
if (nodeToRemove == _firstNode) {
|
||||
_firstNode = nodeToRemove->next;
|
||||
} else {
|
||||
for (node_type *node = _firstNode; node; node = node->next)
|
||||
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
|
||||
}
|
||||
}
|
||||
|
||||
JsonBuffer &buffer() const {
|
||||
return *_buffer;
|
||||
}
|
||||
JsonBuffer *_buffer; // TODO!!
|
||||
|
||||
protected:
|
||||
void clear() {
|
||||
_firstNode = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
node_type *_firstNode;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,50 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ListNode.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A read-only forward itertor for List<T>
|
||||
template <typename T>
|
||||
class ListConstIterator {
|
||||
public:
|
||||
explicit ListConstIterator(const ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
const T &operator*() const {
|
||||
return _node->content;
|
||||
}
|
||||
const T *operator->() {
|
||||
return &_node->content;
|
||||
}
|
||||
|
||||
bool operator==(const ListConstIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
}
|
||||
|
||||
bool operator!=(const ListConstIterator<T> &other) const {
|
||||
return _node != other._node;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator++() {
|
||||
if (_node) _node = _node->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListNode.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename T>
|
||||
class List;
|
||||
|
||||
// A read-write forward iterator for List<T>
|
||||
template <typename T>
|
||||
class ListIterator {
|
||||
friend class List<T>;
|
||||
|
||||
public:
|
||||
explicit ListIterator(ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
T &operator*() const {
|
||||
return _node->content;
|
||||
}
|
||||
T *operator->() {
|
||||
return &_node->content;
|
||||
}
|
||||
|
||||
bool operator==(const ListIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
}
|
||||
|
||||
bool operator!=(const ListIterator<T> &other) const {
|
||||
return _node != other._node;
|
||||
}
|
||||
|
||||
ListIterator<T> &operator++() {
|
||||
if (_node) _node = _node->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator ListConstIterator<T>() const {
|
||||
return ListConstIterator<T>(_node);
|
||||
}
|
||||
|
||||
private:
|
||||
ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for NULL
|
||||
|
||||
#include "../Memory/JsonBufferAllocated.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A node for a singly-linked list.
|
||||
// Used by List<T> and its iterators.
|
||||
template <typename T>
|
||||
struct ListNode : public Internals::JsonBufferAllocated {
|
||||
ListNode() throw() : next(NULL) {}
|
||||
|
||||
ListNode<T> *next;
|
||||
T content;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,53 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Strings/StringTypes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename Source, typename Enable = void>
|
||||
struct ValueSaver {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& destination, Source source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// We duplicate all strings except const char*
|
||||
template <typename TString>
|
||||
struct ValueSaver<
|
||||
TString, typename enable_if<IsString<TString>::value &&
|
||||
!is_same<const char*, TString>::value>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer* buffer, Destination& dest, TString source) {
|
||||
const char* dup = makeString(source).save(buffer);
|
||||
if (!dup) return false;
|
||||
dest = dup;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// We duplicate all SerializedValue<T> except SerializedValue<const char*>
|
||||
template <typename TString>
|
||||
struct ValueSaver<
|
||||
const SerializedValue<TString>&,
|
||||
typename enable_if<!is_same<const char*, TString>::value>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer* buffer, Destination& dest,
|
||||
const SerializedValue<TString>& source) {
|
||||
const char* dup = makeString(source.data(), source.size()).save(buffer);
|
||||
if (!dup) return false;
|
||||
dest = SerializedValue<const char*>(dup, source.size());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -8,8 +8,7 @@
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct ArduinoStreamReader {
|
||||
Stream& _stream;
|
||||
@ -35,7 +34,6 @@ struct ArduinoStreamReader {
|
||||
inline ArduinoStreamReader makeReader(Stream& input) {
|
||||
return ArduinoStreamReader(input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -4,36 +4,32 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TChar>
|
||||
class UnsafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
explicit UnsafeCharPointerReader(const TChar* ptr)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")) {}
|
||||
explicit UnsafeCharPointerReader(const char* ptr)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// we cannot know
|
||||
// we cannot know, that's why it's unsafe
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
class SafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
const TChar* _end;
|
||||
const char* _ptr;
|
||||
const char* _end;
|
||||
|
||||
public:
|
||||
explicit SafeCharPointerReader(const TChar* ptr, size_t len)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")),
|
||||
_end(_ptr + len) {}
|
||||
explicit SafeCharPointerReader(const char* ptr, size_t len)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")), _end(_ptr + len) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
@ -45,20 +41,19 @@ class SafeCharPointerReader {
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
inline UnsafeCharPointerReader<TChar> makeReader(TChar* input) {
|
||||
return UnsafeCharPointerReader<TChar>(input);
|
||||
inline UnsafeCharPointerReader makeReader(TChar* input) {
|
||||
return UnsafeCharPointerReader(reinterpret_cast<const char*>(input));
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline SafeCharPointerReader<TChar> makeReader(TChar* input, size_t n) {
|
||||
return SafeCharPointerReader<TChar>(input, n);
|
||||
inline SafeCharPointerReader makeReader(TChar* input, size_t n) {
|
||||
return SafeCharPointerReader(reinterpret_cast<const char*>(input), n);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
inline SafeCharPointerReader<char> makeReader(const String& input) {
|
||||
return SafeCharPointerReader<char>(input.c_str(), input.length());
|
||||
inline SafeCharPointerReader makeReader(const ::String& input) {
|
||||
return SafeCharPointerReader(input.c_str(), input.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -8,9 +8,13 @@
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class DeserializationError {
|
||||
// safe bool idiom
|
||||
typedef void (DeserializationError::*bool_type)() const;
|
||||
void safeBoolHelper() const {}
|
||||
|
||||
public:
|
||||
enum Code {
|
||||
Ok,
|
||||
@ -22,26 +26,52 @@ class DeserializationError {
|
||||
};
|
||||
|
||||
DeserializationError() {}
|
||||
DeserializationError(Code code) : _code(code) {}
|
||||
DeserializationError(Code c) : _code(c) {}
|
||||
|
||||
friend bool operator==(const DeserializationError& err, Code code) {
|
||||
return err._code == code;
|
||||
// Compare with DeserializationError
|
||||
friend bool operator==(const DeserializationError& lhs,
|
||||
const DeserializationError& rhs) {
|
||||
return lhs._code == rhs._code;
|
||||
}
|
||||
friend bool operator!=(const DeserializationError& lhs,
|
||||
const DeserializationError& rhs) {
|
||||
return lhs._code != rhs._code;
|
||||
}
|
||||
|
||||
friend bool operator==(Code code, const DeserializationError& err) {
|
||||
return err._code == code;
|
||||
// Compare with Code
|
||||
friend bool operator==(const DeserializationError& lhs, Code rhs) {
|
||||
return lhs._code == rhs;
|
||||
}
|
||||
friend bool operator==(Code lhs, const DeserializationError& rhs) {
|
||||
return lhs == rhs._code;
|
||||
}
|
||||
friend bool operator!=(const DeserializationError& lhs, Code rhs) {
|
||||
return lhs._code != rhs;
|
||||
}
|
||||
friend bool operator!=(Code lhs, const DeserializationError& rhs) {
|
||||
return lhs != rhs._code;
|
||||
}
|
||||
|
||||
friend bool operator!=(const DeserializationError& err, Code code) {
|
||||
return err._code != code;
|
||||
// Behaves like a bool
|
||||
operator bool_type() const {
|
||||
return _code != Ok ? &DeserializationError::safeBoolHelper : 0;
|
||||
}
|
||||
friend bool operator==(bool value, const DeserializationError& err) {
|
||||
return static_cast<bool>(err) == value;
|
||||
}
|
||||
friend bool operator==(const DeserializationError& err, bool value) {
|
||||
return static_cast<bool>(err) == value;
|
||||
}
|
||||
friend bool operator!=(bool value, const DeserializationError& err) {
|
||||
return static_cast<bool>(err) != value;
|
||||
}
|
||||
friend bool operator!=(const DeserializationError& err, bool value) {
|
||||
return static_cast<bool>(err) != value;
|
||||
}
|
||||
|
||||
friend bool operator!=(Code code, const DeserializationError& err) {
|
||||
return err._code != code;
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return _code != Ok;
|
||||
// Returns internal enum, useful for switch statement
|
||||
Code code() const {
|
||||
return _code;
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
@ -80,4 +110,4 @@ inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -6,8 +6,7 @@
|
||||
|
||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class UnsafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
|
||||
@ -50,7 +49,6 @@ inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
|
||||
size_t size) {
|
||||
return SafeFlashStringReader(input, size);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TIterator>
|
||||
class IteratorReader {
|
||||
@ -30,5 +29,4 @@ inline IteratorReader<typename TInput::const_iterator> makeReader(
|
||||
return IteratorReader<typename TInput::const_iterator>(input.begin(),
|
||||
input.end());
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -8,8 +8,7 @@
|
||||
|
||||
#include <istream>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StdStreamReader {
|
||||
std::istream& _stream;
|
||||
@ -34,7 +33,6 @@ class StdStreamReader {
|
||||
inline StdStreamReader makeReader(std::istream& input) {
|
||||
return StdStreamReader(input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -12,71 +12,60 @@
|
||||
#include "./IteratorReader.hpp"
|
||||
#include "./StdStreamReader.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <template <typename, typename> class TDeserializer,
|
||||
typename TJsonBuffer, typename TReader, typename TWriter>
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(TJsonBuffer *buffer,
|
||||
template <template <typename, typename> class TDeserializer, typename TReader,
|
||||
typename TWriter>
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
|
||||
TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit) {
|
||||
return TDeserializer<TReader, TWriter>(buffer, reader, writer, nestingLimit);
|
||||
return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit);
|
||||
}
|
||||
|
||||
// DeserializationError deserialize(TDocument& doc, TString input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// DeserializationError deserialize(JsonDocument& doc, TString input);
|
||||
// TString = const std::string&, const String&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TString>
|
||||
typename Internals::enable_if<!Internals::is_array<TString>::value,
|
||||
DeserializationError>::type
|
||||
deserialize(TDocument &doc, const TString &input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TChar>
|
||||
DeserializationError deserialize(TDocument &doc, TChar *input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input, size_t
|
||||
// inputSize);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TChar>
|
||||
DeserializationError deserialize(TDocument &doc, TChar *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
template <template <typename, typename> class TDeserializer, typename TString>
|
||||
typename enable_if<!is_array<TString>::value, DeserializationError>::type
|
||||
deserialize(JsonDocument &doc, const TString &input) {
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
&doc.buffer(), makeReader(input, inputSize),
|
||||
makeStringStorage(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
doc.memoryPool(), makeReader(input),
|
||||
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
|
||||
.parse(doc.data());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TStream input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TStream = std::istream&, Stream&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TStream>
|
||||
DeserializationError deserialize(TDocument &doc, TStream &input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
// DeserializationError deserialize(JsonDocument& doc, TChar* input);
|
||||
// TChar* = char*, const char*, const __FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TChar>
|
||||
DeserializationError deserialize(JsonDocument &doc, TChar *input) {
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), makeReader(input),
|
||||
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
|
||||
.parse(doc.data());
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
//
|
||||
// DeserializationError deserialize(JsonDocument& doc, TChar* input, size_t
|
||||
// inputSize);
|
||||
// TChar* = char*, const char*, const __FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TChar>
|
||||
DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
||||
size_t inputSize) {
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), makeReader(input, inputSize),
|
||||
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
|
||||
.parse(doc.data());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(JsonDocument& doc, TStream input);
|
||||
// TStream = std::istream&, Stream&
|
||||
template <template <typename, typename> class TDeserializer, typename TStream>
|
||||
DeserializationError deserialize(JsonDocument &doc, TStream &input) {
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), makeReader(input),
|
||||
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
|
||||
.parse(doc.data());
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
61
src/ArduinoJson/Document/DynamicJsonDocument.hpp
Normal file
61
src/ArduinoJson/Document/DynamicJsonDocument.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonDocument.hpp"
|
||||
|
||||
#include <stdlib.h> // malloc, free
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class DynamicJsonDocument : public JsonDocument {
|
||||
public:
|
||||
DynamicJsonDocument(size_t capa = ARDUINOJSON_DEFAULT_POOL_SIZE)
|
||||
: JsonDocument(allocPool(addPadding(capa))) {}
|
||||
|
||||
DynamicJsonDocument(const DynamicJsonDocument& src)
|
||||
: JsonDocument(allocPool(src.capacity())) {
|
||||
copy(src);
|
||||
}
|
||||
|
||||
DynamicJsonDocument(const JsonDocument& src)
|
||||
: JsonDocument(allocPool(src.capacity())) {
|
||||
copy(src);
|
||||
}
|
||||
|
||||
~DynamicJsonDocument() {
|
||||
freePool();
|
||||
}
|
||||
|
||||
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
|
||||
reallocPoolIfTooSmall(src.memoryUsage());
|
||||
copy(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DynamicJsonDocument& operator=(const JsonDocument& src) {
|
||||
reallocPoolIfTooSmall(src.memoryUsage());
|
||||
copy(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool allocPool(size_t capa) {
|
||||
return MemoryPool(reinterpret_cast<char*>(malloc(capa)), capa);
|
||||
}
|
||||
|
||||
void reallocPoolIfTooSmall(size_t requiredSize) {
|
||||
if (requiredSize <= capacity()) return;
|
||||
freePool();
|
||||
replacePool(allocPool(addPadding(requiredSize)));
|
||||
}
|
||||
|
||||
void freePool() {
|
||||
free(memoryPool().buffer());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
94
src/ArduinoJson/Document/JsonDocument.hpp
Normal file
94
src/ArduinoJson/Document/JsonDocument.hpp
Normal file
@ -0,0 +1,94 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Memory/MemoryPool.hpp"
|
||||
#include "../Variant/VariantRef.hpp"
|
||||
#include "../Variant/VariantTo.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonDocument : public Visitable {
|
||||
public:
|
||||
uint8_t nestingLimit;
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor& visitor) const {
|
||||
return getVariant().accept(visitor);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename VariantAs<T>::type as() {
|
||||
return getVariant().template as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename VariantConstAs<T>::type as() const {
|
||||
return getVariant().template as<T>();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_pool.clear();
|
||||
_data.setNull();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return getVariant().template is<T>();
|
||||
}
|
||||
|
||||
size_t memoryUsage() const {
|
||||
return _pool.size();
|
||||
}
|
||||
|
||||
size_t capacity() const {
|
||||
return _pool.capacity();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename VariantTo<T>::type to() {
|
||||
clear();
|
||||
return getVariant().template to<T>();
|
||||
}
|
||||
|
||||
// for internal use only
|
||||
MemoryPool& memoryPool() {
|
||||
return _pool;
|
||||
}
|
||||
|
||||
VariantData& data() {
|
||||
return _data;
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonDocument(MemoryPool pool)
|
||||
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(pool) {}
|
||||
|
||||
JsonDocument(char* buf, size_t capa)
|
||||
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT), _pool(buf, capa) {}
|
||||
|
||||
void copy(const JsonDocument& src) {
|
||||
nestingLimit = src.nestingLimit;
|
||||
to<VariantRef>().set(src.as<VariantRef>());
|
||||
}
|
||||
|
||||
void replacePool(MemoryPool pool) {
|
||||
_pool = pool;
|
||||
}
|
||||
|
||||
private:
|
||||
VariantRef getVariant() {
|
||||
return VariantRef(&_pool, &_data);
|
||||
}
|
||||
|
||||
VariantConstRef getVariant() const {
|
||||
return VariantConstRef(&_data);
|
||||
}
|
||||
|
||||
MemoryPool _pool;
|
||||
VariantData _data;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
33
src/ArduinoJson/Document/StaticJsonDocument.hpp
Normal file
33
src/ArduinoJson/Document/StaticJsonDocument.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonDocument.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <size_t CAPACITY>
|
||||
class StaticJsonDocument : public JsonDocument {
|
||||
static const size_t ACTUAL_CAPACITY =
|
||||
AddPadding<Max<1, CAPACITY>::value>::value;
|
||||
|
||||
public:
|
||||
StaticJsonDocument() : JsonDocument(_buffer, ACTUAL_CAPACITY) {}
|
||||
|
||||
StaticJsonDocument(const JsonDocument& src)
|
||||
: JsonDocument(_buffer, ACTUAL_CAPACITY) {
|
||||
copy(src);
|
||||
}
|
||||
|
||||
StaticJsonDocument operator=(const JsonDocument& src) {
|
||||
copy(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
char _buffer[ACTUAL_CAPACITY];
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,84 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Memory/DynamicJsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class DynamicJsonDocument {
|
||||
Internals::DynamicJsonBuffer _buffer;
|
||||
JsonVariant _root;
|
||||
|
||||
public:
|
||||
uint8_t nestingLimit;
|
||||
|
||||
DynamicJsonDocument() : nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
||||
DynamicJsonDocument(size_t capacity)
|
||||
: _buffer(capacity), nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return _root.is<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type as() const {
|
||||
return _root.as<T>();
|
||||
}
|
||||
|
||||
// JsonObject to<JsonObject>()
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonObject>::value,
|
||||
JsonObject>::type
|
||||
to() {
|
||||
clear();
|
||||
JsonObject object(&_buffer);
|
||||
_root = object;
|
||||
return object;
|
||||
}
|
||||
|
||||
// JsonArray to<JsonArray>()
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonArray>::value,
|
||||
JsonArray>::type
|
||||
to() {
|
||||
clear();
|
||||
JsonArray array(&_buffer);
|
||||
_root = array;
|
||||
return array;
|
||||
}
|
||||
|
||||
// JsonVariant& to<JsonVariant>()
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
|
||||
T&>::type
|
||||
to() {
|
||||
clear();
|
||||
return _root;
|
||||
}
|
||||
|
||||
Internals::DynamicJsonBuffer& buffer() {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_buffer.clear();
|
||||
_root = JsonVariant();
|
||||
}
|
||||
|
||||
size_t memoryUsage() const {
|
||||
return _buffer.size();
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor& visitor) const {
|
||||
return _root.visit(visitor);
|
||||
}
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -4,8 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class EscapeSequence {
|
||||
public:
|
||||
@ -33,5 +32,4 @@ class EscapeSequence {
|
||||
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// Decorator on top of Print to allow indented output.
|
||||
// This class is used by serializeJsonPretty() but can also be used
|
||||
@ -67,5 +66,4 @@ class IndentedPrint {
|
||||
static const int MAX_LEVEL = 15; // because it's only 4 bits
|
||||
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -5,34 +5,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Deserialization/deserialize.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Memory/MemoryPool.hpp"
|
||||
#include "../Numbers/isFloat.hpp"
|
||||
#include "../Numbers/isInteger.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "./EscapeSequence.hpp"
|
||||
#include "../Variant/VariantData.hpp"
|
||||
#include "EscapeSequence.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TReader, typename TStringStorage>
|
||||
class JsonDeserializer {
|
||||
typedef typename remove_reference<TStringStorage>::type::StringBuilder
|
||||
StringBuilder;
|
||||
typedef const char *StringType;
|
||||
|
||||
public:
|
||||
JsonDeserializer(JsonBuffer *buffer, TReader reader,
|
||||
JsonDeserializer(MemoryPool &pool, TReader reader,
|
||||
TStringStorage stringStorage, uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
: _pool(&pool),
|
||||
_reader(reader),
|
||||
_stringStorage(stringStorage),
|
||||
_nestingLimit(nestingLimit),
|
||||
_loaded(false) {}
|
||||
DeserializationError parse(JsonVariant &variant) {
|
||||
DeserializationError parse(VariantData &variant) {
|
||||
DeserializationError err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
switch (current()) {
|
||||
case '[':
|
||||
return parseArray(variant);
|
||||
return parseArray(variant.toArray());
|
||||
|
||||
case '{':
|
||||
return parseObject(variant);
|
||||
return parseObject(variant.toObject());
|
||||
|
||||
default:
|
||||
return parseValue(variant);
|
||||
@ -63,13 +68,9 @@ class JsonDeserializer {
|
||||
return true;
|
||||
}
|
||||
|
||||
DeserializationError parseArray(JsonVariant &variant) {
|
||||
DeserializationError parseArray(CollectionData &array) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
|
||||
JsonArray array(_buffer);
|
||||
if (array.isNull()) return DeserializationError::NoMemory;
|
||||
variant = array;
|
||||
|
||||
// Check opening braket
|
||||
if (!eat('[')) return DeserializationError::InvalidInput;
|
||||
|
||||
@ -82,13 +83,15 @@ class JsonDeserializer {
|
||||
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// Allocate slot in array
|
||||
VariantData *value = array.add(_pool);
|
||||
if (!value) return DeserializationError::NoMemory;
|
||||
|
||||
// 1 - Parse value
|
||||
JsonVariant value;
|
||||
_nestingLimit--;
|
||||
err = parse(value);
|
||||
err = parse(*value);
|
||||
_nestingLimit++;
|
||||
if (err) return err;
|
||||
if (!array.add(value)) return DeserializationError::NoMemory;
|
||||
|
||||
// 2 - Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
@ -100,13 +103,9 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseObject(JsonVariant &variant) {
|
||||
DeserializationError parseObject(CollectionData &object) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
|
||||
JsonObject object(_buffer);
|
||||
if (object.isNull()) return DeserializationError::NoMemory;
|
||||
variant = object;
|
||||
|
||||
// Check opening brace
|
||||
if (!eat('{')) return DeserializationError::InvalidInput;
|
||||
|
||||
@ -119,10 +118,15 @@ class JsonDeserializer {
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// Allocate slot in object
|
||||
VariantSlot *slot = object.addSlot(_pool);
|
||||
if (!slot) return DeserializationError::NoMemory;
|
||||
|
||||
// Parse key
|
||||
const char *key;
|
||||
err = parseKey(&key);
|
||||
StringType key;
|
||||
err = parseKey(key);
|
||||
if (err) return err;
|
||||
slot->setOwnedKey(key);
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
@ -130,12 +134,10 @@ class JsonDeserializer {
|
||||
if (!eat(':')) return DeserializationError::InvalidInput;
|
||||
|
||||
// Parse value
|
||||
JsonVariant value;
|
||||
_nestingLimit--;
|
||||
err = parse(value);
|
||||
err = parse(*slot->data());
|
||||
_nestingLimit++;
|
||||
if (err) return err;
|
||||
if (!object.set(key, value)) return DeserializationError::NoMemory;
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
@ -151,7 +153,7 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseValue(JsonVariant &variant) {
|
||||
DeserializationError parseValue(VariantData &variant) {
|
||||
if (isQuote(current())) {
|
||||
return parseStringValue(variant);
|
||||
} else {
|
||||
@ -159,7 +161,7 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseKey(const char **key) {
|
||||
DeserializationError parseKey(StringType &key) {
|
||||
if (isQuote(current())) {
|
||||
return parseQuotedString(key);
|
||||
} else {
|
||||
@ -167,19 +169,17 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseStringValue(JsonVariant &variant) {
|
||||
const char *value;
|
||||
DeserializationError err = parseQuotedString(&value);
|
||||
DeserializationError parseStringValue(VariantData &variant) {
|
||||
StringType value;
|
||||
DeserializationError err = parseQuotedString(value);
|
||||
if (err) return err;
|
||||
variant = value;
|
||||
variant.setOwnedString(value);
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError parseQuotedString(const char **result) {
|
||||
typename remove_reference<TStringStorage>::type::String str =
|
||||
_stringStorage.startString();
|
||||
|
||||
char stopChar = current();
|
||||
DeserializationError parseQuotedString(StringType &result) {
|
||||
StringBuilder builder = _stringStorage.startString();
|
||||
const char stopChar = current();
|
||||
|
||||
move();
|
||||
for (;;) {
|
||||
@ -199,17 +199,16 @@ class JsonDeserializer {
|
||||
move();
|
||||
}
|
||||
|
||||
str.append(c);
|
||||
builder.append(c);
|
||||
}
|
||||
|
||||
*result = str.c_str();
|
||||
if (*result == NULL) return DeserializationError::NoMemory;
|
||||
result = builder.complete();
|
||||
if (!result) return DeserializationError::NoMemory;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError parseNonQuotedString(const char **result) {
|
||||
typename remove_reference<TStringStorage>::type::String str =
|
||||
_stringStorage.startString();
|
||||
DeserializationError parseNonQuotedString(StringType &result) {
|
||||
StringBuilder builder = _stringStorage.startString();
|
||||
|
||||
char c = current();
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
@ -217,19 +216,19 @@ class JsonDeserializer {
|
||||
if (canBeInNonQuotedString(c)) { // no quotes
|
||||
do {
|
||||
move();
|
||||
str.append(c);
|
||||
builder.append(c);
|
||||
c = current();
|
||||
} while (canBeInNonQuotedString(c));
|
||||
} else {
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
|
||||
*result = str.c_str();
|
||||
if (*result == NULL) return DeserializationError::NoMemory;
|
||||
result = builder.complete();
|
||||
if (!result) return DeserializationError::NoMemory;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError parseNumericValue(JsonVariant &result) {
|
||||
DeserializationError parseNumericValue(VariantData &result) {
|
||||
char buffer[64];
|
||||
uint8_t n = 0;
|
||||
|
||||
@ -242,15 +241,15 @@ class JsonDeserializer {
|
||||
buffer[n] = 0;
|
||||
|
||||
if (isInteger(buffer)) {
|
||||
result = parseInteger<JsonInteger>(buffer);
|
||||
result.setInteger(parseInteger<Integer>(buffer));
|
||||
} else if (isFloat(buffer)) {
|
||||
result = parseFloat<JsonFloat>(buffer);
|
||||
result.setFloat(parseFloat<Float>(buffer));
|
||||
} else if (!strcmp(buffer, "true")) {
|
||||
result = true;
|
||||
result.setBoolean(true);
|
||||
} else if (!strcmp(buffer, "false")) {
|
||||
result = false;
|
||||
result.setBoolean(false);
|
||||
} else if (!strcmp(buffer, "null")) {
|
||||
result = static_cast<const char *>(0);
|
||||
// already null
|
||||
} else {
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
@ -329,37 +328,32 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
MemoryPool *_pool;
|
||||
TReader _reader;
|
||||
TStringStorage _stringStorage;
|
||||
uint8_t _nestingLimit;
|
||||
char _current;
|
||||
bool _loaded;
|
||||
}; // namespace Internals
|
||||
} // namespace Internals
|
||||
};
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, const TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput *input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -4,31 +4,32 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Misc/Visitable.hpp"
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "./JsonWriter.hpp"
|
||||
#include "JsonWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TWriter>
|
||||
class JsonSerializer {
|
||||
public:
|
||||
JsonSerializer(TWriter &writer) : _writer(writer) {}
|
||||
|
||||
void acceptFloat(JsonFloat value) {
|
||||
void visitFloat(Float value) {
|
||||
_writer.writeFloat(value);
|
||||
}
|
||||
|
||||
void acceptArray(const JsonArray &array) {
|
||||
void visitArray(const CollectionData &array) {
|
||||
_writer.beginArray();
|
||||
|
||||
JsonArray::const_iterator it = array.begin();
|
||||
while (it != array.end()) {
|
||||
it->visit(*this);
|
||||
VariantSlot *slot = array.head();
|
||||
|
||||
++it;
|
||||
if (it == array.end()) break;
|
||||
while (slot != 0) {
|
||||
slot->data()->accept(*this);
|
||||
|
||||
slot = slot->next();
|
||||
if (slot == 0) break;
|
||||
|
||||
_writer.writeComma();
|
||||
}
|
||||
@ -36,17 +37,18 @@ class JsonSerializer {
|
||||
_writer.endArray();
|
||||
}
|
||||
|
||||
void acceptObject(const JsonObject &object) {
|
||||
void visitObject(const CollectionData &object) {
|
||||
_writer.beginObject();
|
||||
|
||||
JsonObject::const_iterator it = object.begin();
|
||||
while (it != object.end()) {
|
||||
_writer.writeString(it->key);
|
||||
_writer.writeColon();
|
||||
it->value.visit(*this);
|
||||
VariantSlot *slot = object.head();
|
||||
|
||||
++it;
|
||||
if (it == object.end()) break;
|
||||
while (slot != 0) {
|
||||
_writer.writeString(slot->key());
|
||||
_writer.writeColon();
|
||||
slot->data()->accept(*this);
|
||||
|
||||
slot = slot->next();
|
||||
if (slot == 0) break;
|
||||
|
||||
_writer.writeComma();
|
||||
}
|
||||
@ -54,29 +56,29 @@ class JsonSerializer {
|
||||
_writer.endObject();
|
||||
}
|
||||
|
||||
void acceptString(const char *value) {
|
||||
void visitString(const char *value) {
|
||||
_writer.writeString(value);
|
||||
}
|
||||
|
||||
void acceptRawJson(const char *data, size_t n) {
|
||||
void visitRawJson(const char *data, size_t n) {
|
||||
// TODO
|
||||
for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]);
|
||||
}
|
||||
|
||||
void acceptNegativeInteger(JsonUInt value) {
|
||||
void visitNegativeInteger(UInt value) {
|
||||
_writer.writeRaw('-');
|
||||
_writer.writeInteger(value);
|
||||
}
|
||||
|
||||
void acceptPositiveInteger(JsonUInt value) {
|
||||
void visitPositiveInteger(UInt value) {
|
||||
_writer.writeInteger(value);
|
||||
}
|
||||
|
||||
void acceptBoolean(bool value) {
|
||||
void visitBoolean(bool value) {
|
||||
_writer.writeBoolean(value);
|
||||
}
|
||||
|
||||
void acceptNull() {
|
||||
void visitNull() {
|
||||
_writer.writeRaw("null");
|
||||
}
|
||||
|
||||
@ -88,55 +90,28 @@ class JsonSerializer {
|
||||
JsonWriter<TWriter> _writer;
|
||||
};
|
||||
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
size_t serializeJson(TSource &source, TDestination &destination) {
|
||||
using namespace Internals;
|
||||
size_t serializeJson(const TSource &source, TDestination &destination) {
|
||||
return serialize<JsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJson(const TSource &source, char *buffer, size_t bufferSize) {
|
||||
using namespace Internals;
|
||||
return serialize<JsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJson(const TSource &source) {
|
||||
using namespace Internals;
|
||||
return measure<JsonSerializer>(source);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonArray &source) {
|
||||
template <typename T>
|
||||
inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type
|
||||
operator<<(std::ostream &os, const T &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonObject &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
|
||||
namespace Internals {
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
const JsonArraySubscript &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
const JsonObjectSubscript<TKey> &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
} // namespace Internals
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -6,13 +6,12 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h> // for strlen
|
||||
#include "../Data/JsonInteger.hpp"
|
||||
#include "../Numbers/FloatParts.hpp"
|
||||
#include "../Numbers/Integer.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
#include "./EscapeSequence.hpp"
|
||||
#include "EscapeSequence.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TWriter>
|
||||
class JsonWriter {
|
||||
@ -72,8 +71,8 @@ class JsonWriter {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TFloat>
|
||||
void writeFloat(TFloat value) {
|
||||
template <typename T>
|
||||
void writeFloat(T value) {
|
||||
if (isnan(value)) return writeRaw("NaN");
|
||||
|
||||
if (value < 0.0) {
|
||||
@ -83,7 +82,7 @@ class JsonWriter {
|
||||
|
||||
if (isinf(value)) return writeRaw("Infinity");
|
||||
|
||||
FloatParts<TFloat> parts(value);
|
||||
FloatParts<T> parts(value);
|
||||
|
||||
writeInteger(parts.integral);
|
||||
if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces);
|
||||
@ -99,8 +98,8 @@ class JsonWriter {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename UInt>
|
||||
void writeInteger(UInt value) {
|
||||
template <typename T>
|
||||
void writeInteger(T value) {
|
||||
char buffer[22];
|
||||
char *end = buffer + sizeof(buffer);
|
||||
char *begin = end;
|
||||
@ -108,7 +107,7 @@ class JsonWriter {
|
||||
// write the string in reverse order
|
||||
do {
|
||||
*--begin = char(value % 10 + '0');
|
||||
value = UInt(value / 10);
|
||||
value = T(value / 10);
|
||||
} while (value);
|
||||
|
||||
// and dump it in the right order
|
||||
@ -154,5 +153,4 @@ class JsonWriter {
|
||||
private:
|
||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -10,8 +10,7 @@
|
||||
#include "./JsonSerializer.hpp"
|
||||
#include "./Prettyfier.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TPrint>
|
||||
class PrettyJsonSerializer_Base {
|
||||
@ -33,25 +32,21 @@ class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>,
|
||||
JsonSerializer<Prettyfier<TPrint> >(
|
||||
PrettyJsonSerializer_Base<TPrint>::_prettyfier) {}
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
size_t serializeJsonPretty(TSource &source, TDestination &destination) {
|
||||
using namespace Internals;
|
||||
return serialize<PrettyJsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJsonPretty(const TSource &source, char *buffer,
|
||||
size_t bufferSize) {
|
||||
using namespace Internals;
|
||||
return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJsonPretty(const TSource &source) {
|
||||
using namespace Internals;
|
||||
return measure<PrettyJsonSerializer>(source);
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -6,8 +6,7 @@
|
||||
|
||||
#include "IndentedPrint.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// Converts a compact JSON string into an indented one.
|
||||
template <typename TWriter>
|
||||
@ -141,5 +140,4 @@ class Prettyfier {
|
||||
IndentedPrint<TWriter>& _sink;
|
||||
bool _inString;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -1,208 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./JsonArrayData.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
class JsonArraySubscript;
|
||||
}
|
||||
|
||||
class JsonArray {
|
||||
friend class JsonVariant;
|
||||
|
||||
public:
|
||||
typedef Internals::JsonArrayData::iterator iterator;
|
||||
typedef Internals::JsonArrayData::const_iterator const_iterator;
|
||||
|
||||
JsonArray() : _data(0) {}
|
||||
JsonArray(Internals::JsonArrayData* arr) : _data(arr) {}
|
||||
JsonArray(Internals::JsonBuffer* buf)
|
||||
: _data(new (buf) Internals::JsonArrayData(buf)) {}
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArrayData, JsonObject
|
||||
template <typename T>
|
||||
bool add(const T& value) {
|
||||
return add_impl<const T&>(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool add(T* value) {
|
||||
return add_impl<T*>(value);
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
if (!_data) return iterator();
|
||||
return _data->begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
if (!_data) return const_iterator();
|
||||
return _data->begin();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if (!_data) return;
|
||||
size_t i = 0;
|
||||
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
|
||||
it->as<JsonArray>().copyTo(array[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
JsonArray createNestedArray();
|
||||
JsonObject createNestedObject();
|
||||
|
||||
Internals::JsonArraySubscript operator[](size_t index);
|
||||
|
||||
const Internals::JsonArraySubscript operator[](size_t index) const;
|
||||
|
||||
bool operator==(const JsonArray& rhs) const {
|
||||
return _data == rhs._data;
|
||||
}
|
||||
|
||||
// Gets the value at the specified index.
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
|
||||
const_iterator it = begin() += index;
|
||||
return it != end() ? it->as<T>() : Internals::JsonVariantDefault<T>::get();
|
||||
}
|
||||
|
||||
// Check the type of the value at specified index.
|
||||
template <typename T>
|
||||
bool is(size_t index) const {
|
||||
const_iterator it = begin() += index;
|
||||
return it != end() ? it->is<T>() : false;
|
||||
}
|
||||
|
||||
// Removes element at specified position.
|
||||
void remove(iterator it) {
|
||||
if (!_data) return;
|
||||
_data->remove(it);
|
||||
}
|
||||
|
||||
// Removes element at specified index.
|
||||
void remove(size_t index) {
|
||||
remove(begin() += index);
|
||||
}
|
||||
|
||||
// Sets the value at specified index.
|
||||
//
|
||||
// bool add(size_t index, const TValue&);
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArrayData, JsonObject
|
||||
template <typename T>
|
||||
bool set(size_t index, const T& value) {
|
||||
if (!_data) return false;
|
||||
return set_impl<const T&>(index, value);
|
||||
}
|
||||
//
|
||||
// bool add(size_t index, TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool set(size_t index, T* value) {
|
||||
if (!_data) return false;
|
||||
return set_impl<T*>(index, value);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
if (!_data) return 0;
|
||||
return _data->size();
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor& visitor) const {
|
||||
if (_data)
|
||||
return visitor.acceptArray(*this);
|
||||
else
|
||||
visitor.acceptNull();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TValueRef>
|
||||
bool set_impl(size_t index, TValueRef value) {
|
||||
iterator it = begin() += index;
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, *it, value);
|
||||
}
|
||||
|
||||
template <typename TValueRef>
|
||||
bool add_impl(TValueRef value) {
|
||||
if (!_data) return false;
|
||||
iterator it = _data->add();
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, *it, value);
|
||||
}
|
||||
|
||||
Internals::JsonArrayData* _data;
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,26 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/List.hpp"
|
||||
#include "Data/ValueSaver.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Memory/JsonBufferAllocated.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(ArduinoJson::Internals::JsonArrayData) + \
|
||||
(NUMBER_OF_ELEMENTS) * \
|
||||
sizeof(ArduinoJson::Internals::JsonArrayData::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
struct JsonArrayData : List<JsonVariant>, JsonBufferAllocated {
|
||||
explicit JsonArrayData(JsonBuffer *buf) throw() : List<JsonVariant>(buf) {}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,25 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonArray JsonArray::createNestedArray() {
|
||||
if (!_data) return JsonArray();
|
||||
JsonArray array(_data->_buffer);
|
||||
if (!array.isNull()) add(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
inline JsonObject JsonArray::createNestedObject() {
|
||||
if (!_data) return JsonObject();
|
||||
JsonObject object(_data->_buffer);
|
||||
if (!object.isNull()) add(object);
|
||||
return object;
|
||||
}
|
||||
} // namespace ArduinoJson
|
@ -1,112 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
public:
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// operator=(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue)
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(T* src) {
|
||||
_array.set(_index, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _index >= _array.size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename JsonVariantAs<T>::type as() const {
|
||||
return _array.get<T>(_index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is() const {
|
||||
return _array.is<T>(_index);
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
//
|
||||
// bool set(const TValue&)
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue& value) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue)
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue* value) {
|
||||
return _array.set(_index, value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor& visitor) const {
|
||||
return _array.get<JsonVariant>(_index).visit(visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonArray _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
inline const JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) const {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
} // namespace Internals
|
||||
|
||||
inline Internals::JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||
return Internals::JsonArraySubscript(*this, index);
|
||||
}
|
||||
|
||||
inline const Internals::JsonArraySubscript JsonArray::operator[](
|
||||
size_t index) const {
|
||||
return Internals::JsonArraySubscript(*this, index);
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
@ -1,311 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./JsonObjectData.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class JsonObject {
|
||||
friend class JsonVariant;
|
||||
|
||||
public:
|
||||
typedef Internals::JsonObjectData::iterator iterator;
|
||||
typedef Internals::JsonObjectData::const_iterator const_iterator;
|
||||
|
||||
JsonObject() : _data(0) {}
|
||||
JsonObject(Internals::JsonObjectData* object) : _data(object) {}
|
||||
JsonObject(Internals::JsonBuffer* buf)
|
||||
: _data(new (buf) Internals::JsonObjectData(buf)) {}
|
||||
|
||||
iterator begin() {
|
||||
if (!_data) return iterator();
|
||||
return _data->begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
if (!_data) return const_iterator();
|
||||
return _data->begin();
|
||||
}
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
bool containsKey(const TString& key) const {
|
||||
return containsKey_impl<const TString&>(key);
|
||||
}
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
bool containsKey(TString* key) const {
|
||||
return containsKey_impl<TString*>(key);
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
//
|
||||
// JsonArray createNestedArray(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
JsonArray createNestedArray(const TString& key);
|
||||
// JsonArray createNestedArray(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonArray createNestedArray(TString* key);
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
//
|
||||
// JsonObject createNestedObject(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
JsonObject createNestedObject(const TString& key) {
|
||||
if (!_data) return JsonObject();
|
||||
return createNestedObject_impl<const TString&>(key);
|
||||
}
|
||||
//
|
||||
// JsonObject createNestedObject(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
JsonObject createNestedObject(TString* key) {
|
||||
return createNestedObject_impl<TString*>(key);
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
typename Internals::JsonVariantAs<TValue>::type get(
|
||||
const TString& key) const {
|
||||
return get_impl<const TString&, TValue>(key);
|
||||
}
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
typename Internals::JsonVariantAs<TValue>::type get(TString* key) const {
|
||||
return get_impl<TString*, TValue>(key);
|
||||
}
|
||||
|
||||
// Checks the type of the value associated with the specified key.
|
||||
//
|
||||
//
|
||||
// bool is<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool is(const TString& key) const {
|
||||
return is_impl<const TString&, TValue>(key);
|
||||
}
|
||||
//
|
||||
// bool is<TValue>(TKey) const;
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool is(TString* key) const {
|
||||
return is_impl<TString*, TValue>(key);
|
||||
}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
Internals::JsonObjectSubscript<const TString&> operator[](
|
||||
const TString& key) {
|
||||
return Internals::JsonObjectSubscript<const TString&>(*this, key);
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
Internals::JsonObjectSubscript<TString*> operator[](TString* key) {
|
||||
return Internals::JsonObjectSubscript<TString*>(*this, key);
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
const Internals::JsonObjectSubscript<const TString&> operator[](
|
||||
const TString& key) const {
|
||||
return Internals::JsonObjectSubscript<const TString&>(*this, key);
|
||||
}
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
const Internals::JsonObjectSubscript<TString*> operator[](
|
||||
TString* key) const {
|
||||
return Internals::JsonObjectSubscript<TString*>(*this, key);
|
||||
}
|
||||
|
||||
bool operator==(const JsonObject& rhs) const {
|
||||
return _data == rhs._data;
|
||||
}
|
||||
|
||||
void remove(iterator it) {
|
||||
if (!_data) return;
|
||||
_data->remove(it);
|
||||
}
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
void remove(const TString& key) {
|
||||
remove_impl<const TString&>(key);
|
||||
}
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
void remove(TString* key) {
|
||||
remove_impl<TString*>(key);
|
||||
}
|
||||
|
||||
// Sets the specified key with the specified value.
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool set(const TString& key, const TValue& value) {
|
||||
return set_impl<const TString&, const TValue&>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue, typename TString>
|
||||
bool set(const TString& key, TValue* value) {
|
||||
return set_impl<const TString&, TValue*>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, const TValue&);
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TString>
|
||||
bool set(TString* key, const TValue& value) {
|
||||
return set_impl<TString*, const TValue&>(key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue, typename TString>
|
||||
bool set(TString* key, TValue* value) {
|
||||
return set_impl<TString*, TValue*>(key, value);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
if (!_data) return 0;
|
||||
return _data->size();
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor& visitor) const {
|
||||
if (_data)
|
||||
visitor.acceptObject(*this);
|
||||
else
|
||||
return visitor.acceptNull();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TStringRef>
|
||||
bool containsKey_impl(TStringRef key) const {
|
||||
return findKey<TStringRef>(key) != end();
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
JsonArray createNestedArray_impl(TStringRef key);
|
||||
|
||||
template <typename TStringRef>
|
||||
JsonObject createNestedObject_impl(TStringRef key);
|
||||
|
||||
// Returns the list node that matches the specified key.
|
||||
template <typename TStringRef>
|
||||
iterator findKey(TStringRef key) {
|
||||
iterator it;
|
||||
for (it = begin(); it != end(); ++it) {
|
||||
if (Internals::makeString(key).equals(it->key)) break;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
template <typename TStringRef>
|
||||
const_iterator findKey(TStringRef key) const {
|
||||
return const_cast<JsonObject*>(this)->findKey<TStringRef>(key);
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValue>
|
||||
typename Internals::JsonVariantAs<TValue>::type get_impl(
|
||||
TStringRef key) const {
|
||||
const_iterator it = findKey<TStringRef>(key);
|
||||
return it != end() ? it->value.as<TValue>()
|
||||
: Internals::JsonVariantDefault<TValue>::get();
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValue>
|
||||
bool is_impl(TStringRef key) const {
|
||||
const_iterator it = findKey<TStringRef>(key);
|
||||
return it != end() ? it->value.is<TValue>() : false;
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
void remove_impl(TStringRef key) {
|
||||
if (!_data) return;
|
||||
_data->remove(findKey<TStringRef>(key));
|
||||
}
|
||||
|
||||
template <typename TStringRef, typename TValueRef>
|
||||
bool set_impl(TStringRef key, TValueRef value) {
|
||||
if (!_data) return false;
|
||||
|
||||
// ignore null key
|
||||
if (Internals::makeString(key).is_null()) return false;
|
||||
|
||||
// search a matching key
|
||||
iterator it = findKey<TStringRef>(key);
|
||||
if (it == end()) {
|
||||
// add the key
|
||||
it = _data->add();
|
||||
if (it == end()) return false;
|
||||
bool key_ok =
|
||||
Internals::ValueSaver<TStringRef>::save(_data->_buffer, it->key, key);
|
||||
if (!key_ok) return false;
|
||||
}
|
||||
|
||||
// save the value
|
||||
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, it->value,
|
||||
value);
|
||||
}
|
||||
|
||||
Internals::JsonObjectData* _data;
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,26 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/List.hpp"
|
||||
#include "Data/ValueSaver.hpp"
|
||||
#include "JsonPair.hpp"
|
||||
#include "Memory/JsonBufferAllocated.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(ArduinoJson::Internals::JsonObjectData) + \
|
||||
(NUMBER_OF_ELEMENTS) * \
|
||||
sizeof(ArduinoJson::Internals::JsonObjectData::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
struct JsonObjectData : List<JsonPair>, JsonBufferAllocated {
|
||||
explicit JsonObjectData(JsonBuffer* buf) throw() : List<JsonPair>(buf) {}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,37 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TString>
|
||||
inline JsonArray JsonObject::createNestedArray(const TString& key) {
|
||||
return createNestedArray_impl<const TString&>(key);
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
inline JsonArray JsonObject::createNestedArray(TString* key) {
|
||||
return createNestedArray_impl<TString*>(key);
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
inline JsonArray JsonObject::createNestedArray_impl(TStringRef key) {
|
||||
if (!_data) return JsonArray();
|
||||
JsonArray array(_data->_buffer);
|
||||
if (!array.isNull()) set(key, array);
|
||||
return array;
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
inline JsonObject JsonObject::createNestedObject_impl(TStringRef key) {
|
||||
if (!_data) return JsonObject();
|
||||
JsonObject object(_data->_buffer);
|
||||
if (!object.isNull()) set(key, object);
|
||||
return object;
|
||||
}
|
||||
} // namespace ArduinoJson
|
@ -1,133 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TStringRef>
|
||||
class JsonObjectSubscript
|
||||
: public JsonVariantBase<JsonObjectSubscript<TStringRef> > {
|
||||
typedef JsonObjectSubscript<TStringRef> this_type;
|
||||
|
||||
public:
|
||||
FORCE_INLINE JsonObjectSubscript(JsonObject object, TStringRef key)
|
||||
: _object(object), _key(key) {}
|
||||
|
||||
FORCE_INLINE this_type &operator=(const this_type &src) {
|
||||
_object.set(_key, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Set the specified value
|
||||
//
|
||||
// operator=(const TValue&);
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
|
||||
operator=(const TValue &src) {
|
||||
_object.set(_key, src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE this_type &operator=(TValue *src) {
|
||||
_object.set(_key, src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return !_object.containsKey(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename JsonVariantAs<TValue>::type as() const {
|
||||
return _object.get<TValue>(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool is() const {
|
||||
return _object.is<TValue>(_key);
|
||||
}
|
||||
|
||||
// Sets the specified value.
|
||||
//
|
||||
// bool set(const TValue&);
|
||||
// TValue = bool, char, long, int, short, float, double, serialized,
|
||||
// JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
|
||||
const TValue &value) {
|
||||
return _object.set(_key, value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue);
|
||||
// TValue = char*, const char, const FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue *value) {
|
||||
return _object.set(_key, value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor &visitor) const {
|
||||
return _object.get<JsonVariant>(_key).visit(visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonObject _object;
|
||||
TStringRef _key;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString>::value,
|
||||
const JsonObjectSubscript<const TString &> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](const TString &key) const {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString>::value,
|
||||
JsonObjectSubscript<const TString &> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](const TString &key) {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<const TString *>::value,
|
||||
JsonObjectSubscript<const TString *> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](const TString *key) {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString *>::value,
|
||||
const JsonObjectSubscript<const TString *> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](const TString *key) const {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
@ -1,16 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// A key value pair for JsonObjectData.
|
||||
struct JsonPair {
|
||||
const char* key;
|
||||
JsonVariant value;
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,324 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h> // for uint8_t
|
||||
|
||||
#include "Data/JsonVariantContent.hpp"
|
||||
#include "Data/JsonVariantDefault.hpp"
|
||||
#include "Data/JsonVariantType.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "Serialization/DynamicStringWriter.hpp"
|
||||
#include "SerializedValue.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
// A variant that can be a any value serializable to a JSON value.
|
||||
//
|
||||
// It can be set to:
|
||||
// - a boolean
|
||||
// - a char, short, int or a long (signed or unsigned)
|
||||
// - a string (const char*)
|
||||
// - a reference to a JsonArray or JsonObject
|
||||
class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
|
||||
public:
|
||||
// Creates an uninitialized JsonVariant
|
||||
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||
|
||||
// Create a JsonVariant containing a boolean value.
|
||||
// It will be serialized as "true" or "false" in JSON.
|
||||
JsonVariant(bool value) {
|
||||
using namespace Internals;
|
||||
_type = JSON_BOOLEAN;
|
||||
_content.asInteger = static_cast<JsonUInt>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing a floating point value.
|
||||
// JsonVariant(double value);
|
||||
// JsonVariant(float value);
|
||||
template <typename T>
|
||||
JsonVariant(T value,
|
||||
typename Internals::enable_if<
|
||||
Internals::is_floating_point<T>::value>::type * = 0) {
|
||||
using namespace Internals;
|
||||
_type = JSON_FLOAT;
|
||||
_content.asFloat = static_cast<JsonFloat>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing an integer value.
|
||||
// JsonVariant(char)
|
||||
// JsonVariant(signed short)
|
||||
// JsonVariant(signed int)
|
||||
// JsonVariant(signed long)
|
||||
// JsonVariant(signed char)
|
||||
template <typename T>
|
||||
JsonVariant(
|
||||
T value,
|
||||
typename Internals::enable_if<Internals::is_integral<T>::value &&
|
||||
Internals::is_signed<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) + 1;
|
||||
}
|
||||
}
|
||||
// JsonVariant(unsigned short)
|
||||
// JsonVariant(unsigned int)
|
||||
// JsonVariant(unsigned long)
|
||||
template <typename T>
|
||||
JsonVariant(
|
||||
T value,
|
||||
typename Internals::enable_if<Internals::is_integral<T>::value &&
|
||||
Internals::is_unsigned<T>::value>::type * =
|
||||
0) {
|
||||
using namespace Internals;
|
||||
_type = JSON_POSITIVE_INTEGER;
|
||||
_content.asInteger = static_cast<JsonUInt>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing a string.
|
||||
// JsonVariant(const char*);
|
||||
// JsonVariant(const signed char*);
|
||||
// JsonVariant(const unsigned char*);
|
||||
template <typename TChar>
|
||||
JsonVariant(const TChar *value,
|
||||
typename Internals::enable_if<sizeof(TChar) == 1>::type * = 0) {
|
||||
_type = Internals::JSON_STRING;
|
||||
_content.asString = reinterpret_cast<const char *>(value);
|
||||
}
|
||||
|
||||
// Create a JsonVariant containing an unparsed string
|
||||
JsonVariant(Internals::SerializedValue<const char *> value) {
|
||||
_type = Internals::JSON_UNPARSED;
|
||||
_content.asRaw.data = value.data();
|
||||
_content.asRaw.size = value.size();
|
||||
}
|
||||
|
||||
JsonVariant(JsonArray array);
|
||||
JsonVariant(JsonObject object);
|
||||
|
||||
// Get the variant as the specified type.
|
||||
//
|
||||
// char as<char>() const;
|
||||
// signed char as<signed char>() const;
|
||||
// signed short as<signed short>() const;
|
||||
// signed int as<signed int>() const;
|
||||
// signed long as<signed long>() const;
|
||||
// unsigned char as<unsigned char>() const;
|
||||
// unsigned short as<unsigned short>() const;
|
||||
// unsigned int as<unsigned int>() const;
|
||||
// unsigned long as<unsigned long>() const;
|
||||
template <typename T>
|
||||
const typename Internals::enable_if<Internals::is_integral<T>::value, T>::type
|
||||
as() const {
|
||||
return variantAsInteger<T>();
|
||||
}
|
||||
// bool as<bool>() const
|
||||
template <typename T>
|
||||
const typename Internals::enable_if<Internals::is_same<T, bool>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return variantAsInteger<int>() != 0;
|
||||
}
|
||||
//
|
||||
// double as<double>() const;
|
||||
// float as<float>() const;
|
||||
template <typename T>
|
||||
const typename Internals::enable_if<Internals::is_floating_point<T>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return variantAsFloat<T>();
|
||||
}
|
||||
//
|
||||
// const char* as<const char*>() const;
|
||||
// const char* as<char*>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, const char *>::value ||
|
||||
Internals::is_same<T, char *>::value,
|
||||
const char *>::type
|
||||
as() const {
|
||||
return variantAsString();
|
||||
}
|
||||
//
|
||||
// std::string as<std::string>() const;
|
||||
// String as<String>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::IsWriteableString<T>::value, T>::type
|
||||
as() const {
|
||||
const char *cstr = variantAsString();
|
||||
if (cstr) return T(cstr);
|
||||
T s;
|
||||
serializeJson(*this, s);
|
||||
return s;
|
||||
}
|
||||
//
|
||||
// JsonArray as<JsonArray>() const;
|
||||
// const JsonArray as<const JsonArray>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonArray>::value,
|
||||
JsonArray>::type
|
||||
as() const;
|
||||
//
|
||||
// JsonObject as<JsonObject>() const;
|
||||
// const JsonObject as<const JsonObject>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonObject>::value,
|
||||
T>::type
|
||||
as() const;
|
||||
//
|
||||
// JsonVariant as<JsonVariant> const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Tells weither the variant has the specified type.
|
||||
// Returns true if the variant has type type T, false otherwise.
|
||||
//
|
||||
// bool is<char>() const;
|
||||
// bool is<signed char>() const;
|
||||
// bool is<signed short>() const;
|
||||
// bool is<signed int>() const;
|
||||
// bool is<signed long>() const;
|
||||
// bool is<unsigned char>() const;
|
||||
// bool is<unsigned short>() const;
|
||||
// bool is<unsigned int>() const;
|
||||
// bool is<unsigned long>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_integral<T>::value, bool>::type
|
||||
is() const {
|
||||
return variantIsInteger();
|
||||
}
|
||||
//
|
||||
// bool is<double>() const;
|
||||
// bool is<float>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_floating_point<T>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return variantIsFloat();
|
||||
}
|
||||
//
|
||||
// bool is<bool>() const
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, bool>::value, bool>::type
|
||||
is() const {
|
||||
return variantIsBoolean();
|
||||
}
|
||||
//
|
||||
// bool is<const char*>() const;
|
||||
// bool is<char*>() const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, const char *>::value ||
|
||||
Internals::is_same<T, char *>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return variantIsString();
|
||||
}
|
||||
//
|
||||
// bool is<JsonArray> const;
|
||||
// bool is<const JsonArray> const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonArray>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return variantIsArray();
|
||||
}
|
||||
//
|
||||
// bool is<JsonObject> const;
|
||||
// bool is<const JsonObject> const;
|
||||
template <typename T>
|
||||
typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonObject>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return variantIsObject();
|
||||
}
|
||||
|
||||
// Returns true if the variant has a value
|
||||
bool isNull() const {
|
||||
return _type == Internals::JSON_UNDEFINED;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor &visitor) const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_FLOAT:
|
||||
return visitor.acceptFloat(_content.asFloat);
|
||||
|
||||
case JSON_ARRAY:
|
||||
return visitor.acceptArray(_content.asArray);
|
||||
|
||||
case JSON_OBJECT:
|
||||
return visitor.acceptObject(_content.asObject);
|
||||
|
||||
case JSON_STRING:
|
||||
return visitor.acceptString(_content.asString);
|
||||
|
||||
case JSON_UNPARSED:
|
||||
return visitor.acceptRawJson(_content.asRaw.data, _content.asRaw.size);
|
||||
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return visitor.acceptNegativeInteger(_content.asInteger);
|
||||
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
return visitor.acceptPositiveInteger(_content.asInteger);
|
||||
|
||||
case JSON_BOOLEAN:
|
||||
return visitor.acceptBoolean(_content.asInteger != 0);
|
||||
|
||||
default: // JSON_UNDEFINED
|
||||
return visitor.acceptNull();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
JsonArray variantAsArray() const;
|
||||
JsonObject variantAsObject() const;
|
||||
const char *variantAsString() const;
|
||||
template <typename T>
|
||||
T variantAsFloat() const;
|
||||
template <typename T>
|
||||
T variantAsInteger() const;
|
||||
bool variantIsBoolean() const;
|
||||
bool variantIsFloat() const;
|
||||
bool variantIsInteger() const;
|
||||
bool variantIsArray() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
bool variantIsObject() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
bool variantIsString() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
}
|
||||
|
||||
// The current type of the variant
|
||||
Internals::JsonVariantType _type;
|
||||
|
||||
// The various alternatives for the value of the variant.
|
||||
Internals::JsonVariantContent _content;
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,22 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantCasts.hpp"
|
||||
#include "JsonVariantComparisons.hpp"
|
||||
#include "JsonVariantOr.hpp"
|
||||
#include "JsonVariantSubscripts.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantBase : public JsonVariantCasts<TImpl>,
|
||||
public JsonVariantComparisons<TImpl>,
|
||||
public JsonVariantOr<TImpl>,
|
||||
public JsonVariantSubscripts<TImpl>,
|
||||
public JsonVariantTag {};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,139 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/IsVariant.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "Strings/StringTypes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantComparisons {
|
||||
public:
|
||||
template <typename TComparand>
|
||||
friend bool operator==(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend typename enable_if<!IsVariant<TComparand>::value, bool>::type
|
||||
operator==(TComparand comparand, const JsonVariantComparisons &variant) {
|
||||
return variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator!=(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return !variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend typename enable_if<!IsVariant<TComparand>::value, bool>::type
|
||||
operator!=(TComparand comparand, const JsonVariantComparisons &variant) {
|
||||
return !variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator<=(const JsonVariantComparisons &left, TComparand right) {
|
||||
return left.as<TComparand>() <= right;
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator<=(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand <= variant.as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator>=(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return variant.as<TComparand>() >= comparand;
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator>=(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand >= variant.as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator<(const JsonVariantComparisons &varian,
|
||||
TComparand comparand) {
|
||||
return varian.as<TComparand>() < comparand;
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator<(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand < variant.as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator>(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return variant.as<TComparand>() > comparand;
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator>(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand > variant.as<TComparand>();
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const typename JsonVariantAs<T>::type as() const {
|
||||
return impl()->template as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return impl()->template is<T>();
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
typename enable_if<IsString<TString>::value, bool>::type equals(
|
||||
const TString &comparand) const {
|
||||
return makeString(comparand).equals(as<const char *>());
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
typename enable_if<
|
||||
!IsVariant<TComparand>::value && !IsString<TComparand>::value, bool>::type
|
||||
equals(const TComparand &comparand) const {
|
||||
return as<TComparand>() == comparand;
|
||||
}
|
||||
|
||||
template <typename TVariant2>
|
||||
bool equals(const JsonVariantComparisons<TVariant2> &right) const {
|
||||
using namespace Internals;
|
||||
if (is<bool>() && right.template is<bool>())
|
||||
return as<bool>() == right.template as<bool>();
|
||||
if (is<JsonInteger>() && right.template is<JsonInteger>())
|
||||
return as<JsonInteger>() == right.template as<JsonInteger>();
|
||||
if (is<JsonFloat>() && right.template is<JsonFloat>())
|
||||
return as<JsonFloat>() == right.template as<JsonFloat>();
|
||||
if (is<JsonArray>() && right.template is<JsonArray>())
|
||||
return as<JsonArray>() == right.template as<JsonArray>();
|
||||
if (is<JsonObject>() && right.template is<JsonObject>())
|
||||
return as<JsonObject>() == right.template as<JsonObject>();
|
||||
if (is<char *>() && right.template is<char *>())
|
||||
return makeString(as<char *>()).equals(right.template as<char *>());
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,127 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonArrayData.hpp"
|
||||
#include "JsonObjectData.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Numbers/isFloat.hpp"
|
||||
#include "Numbers/isInteger.hpp"
|
||||
#include "Numbers/parseFloat.hpp"
|
||||
#include "Numbers/parseInteger.hpp"
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonVariant::JsonVariant(JsonArray array) {
|
||||
if (!array.isNull()) {
|
||||
_type = Internals::JSON_ARRAY;
|
||||
_content.asArray = array._data;
|
||||
} else {
|
||||
_type = Internals::JSON_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(JsonObject object) {
|
||||
if (!object.isNull()) {
|
||||
_type = Internals::JSON_OBJECT;
|
||||
_content.asObject = object._data;
|
||||
} else {
|
||||
_type = Internals::JSON_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonArray>::value,
|
||||
JsonArray>::type
|
||||
JsonVariant::as() const {
|
||||
return variantAsArray();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename Internals::enable_if<
|
||||
Internals::is_same<typename Internals::remove_const<T>::type,
|
||||
JsonObject>::value,
|
||||
T>::type
|
||||
JsonVariant::as() const {
|
||||
return variantAsObject();
|
||||
}
|
||||
|
||||
inline JsonArray JsonVariant::variantAsArray() const {
|
||||
if (_type == Internals::JSON_ARRAY) return _content.asArray;
|
||||
return JsonArray();
|
||||
}
|
||||
|
||||
inline JsonObject JsonVariant::variantAsObject() const {
|
||||
if (_type == Internals::JSON_OBJECT) return _content.asObject;
|
||||
return JsonObject();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonVariant::variantAsInteger() const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
case JSON_UNPARSED:
|
||||
return 0;
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return T(_content.asInteger);
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return T(~_content.asInteger + 1);
|
||||
case JSON_STRING:
|
||||
return parseInteger<T>(_content.asString);
|
||||
default:
|
||||
return T(_content.asFloat);
|
||||
}
|
||||
}
|
||||
|
||||
inline const char *JsonVariant::variantAsString() const {
|
||||
using namespace Internals;
|
||||
return _type == JSON_STRING ? _content.asString : NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T JsonVariant::variantAsFloat() const {
|
||||
using namespace Internals;
|
||||
switch (_type) {
|
||||
case JSON_UNDEFINED:
|
||||
case JSON_UNPARSED:
|
||||
return 0;
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return static_cast<T>(_content.asInteger);
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return -static_cast<T>(_content.asInteger);
|
||||
case JSON_STRING:
|
||||
return parseFloat<T>(_content.asString);
|
||||
default:
|
||||
return static_cast<T>(_content.asFloat);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool JsonVariant::variantIsBoolean() const {
|
||||
using namespace Internals;
|
||||
return _type == JSON_BOOLEAN;
|
||||
}
|
||||
|
||||
inline bool JsonVariant::variantIsInteger() const {
|
||||
using namespace Internals;
|
||||
|
||||
return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER;
|
||||
}
|
||||
|
||||
inline bool JsonVariant::variantIsFloat() const {
|
||||
using namespace Internals;
|
||||
|
||||
return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER ||
|
||||
_type == JSON_NEGATIVE_INTEGER;
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
@ -1,78 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "Strings/StringTypes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
namespace Internals {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArraySubscript;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantSubscripts {
|
||||
public:
|
||||
// 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 impl()->template as<JsonArray>().size() +
|
||||
impl()->template as<JsonObject>().size();
|
||||
}
|
||||
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
|
||||
FORCE_INLINE JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is
|
||||
// an object.
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString>::value,
|
||||
const JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) const;
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value,
|
||||
JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key);
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<const TString *>::value,
|
||||
JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key);
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString *>::value,
|
||||
const JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) const;
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
28
src/ArduinoJson/Memory/Alignment.hpp
Normal file
28
src/ArduinoJson/Memory/Alignment.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline bool isAligned(void *ptr) {
|
||||
const size_t mask = sizeof(void *) - 1;
|
||||
size_t addr = reinterpret_cast<size_t>(ptr);
|
||||
return (addr & mask) == 0;
|
||||
}
|
||||
|
||||
inline size_t addPadding(size_t bytes) {
|
||||
const size_t mask = sizeof(void *) - 1;
|
||||
return (bytes + mask) & ~mask;
|
||||
}
|
||||
|
||||
template <size_t bytes>
|
||||
struct AddPadding {
|
||||
static const size_t mask = sizeof(void *) - 1;
|
||||
static const size_t value = (bytes + mask) & ~mask;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,169 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#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 DynamicJsonBufferBase : public JsonBuffer {
|
||||
struct Block;
|
||||
struct EmptyBlock {
|
||||
Block* next;
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
};
|
||||
struct Block : EmptyBlock {
|
||||
uint8_t data[1];
|
||||
};
|
||||
|
||||
public:
|
||||
enum { EmptyBlockSize = sizeof(EmptyBlock) };
|
||||
|
||||
DynamicJsonBufferBase(size_t initialSize = 256)
|
||||
: _head(NULL), _nextBlockCapacity(initialSize) {}
|
||||
|
||||
~DynamicJsonBufferBase() {
|
||||
clear();
|
||||
}
|
||||
|
||||
// Gets the number of bytes occupied in the buffer
|
||||
size_t size() const {
|
||||
size_t total = 0;
|
||||
for (const Block* b = _head; b; b = b->next) total += b->size;
|
||||
return total;
|
||||
}
|
||||
|
||||
// Allocates the specified amount of bytes in the buffer
|
||||
virtual void* alloc(size_t bytes) {
|
||||
alignNextAlloc();
|
||||
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
|
||||
}
|
||||
|
||||
// Resets the buffer.
|
||||
// USE WITH CAUTION: this invalidates all previously allocated data
|
||||
void clear() {
|
||||
Block* currentBlock = _head;
|
||||
while (currentBlock != NULL) {
|
||||
_nextBlockCapacity = currentBlock->capacity;
|
||||
Block* nextBlock = currentBlock->next;
|
||||
_allocator.deallocate(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
}
|
||||
_head = 0;
|
||||
}
|
||||
|
||||
class String {
|
||||
public:
|
||||
String(DynamicJsonBufferBase* parent)
|
||||
: _parent(parent), _start(NULL), _length(0) {}
|
||||
|
||||
void append(char c) {
|
||||
if (_parent->canAllocInHead(1)) {
|
||||
char* end = static_cast<char*>(_parent->allocInHead(1));
|
||||
*end = c;
|
||||
if (_length == 0) _start = end;
|
||||
} else {
|
||||
char* newStart =
|
||||
static_cast<char*>(_parent->allocInNewBlock(_length + 1));
|
||||
if (_start && newStart) memcpy(newStart, _start, _length);
|
||||
if (newStart) newStart[_length] = c;
|
||||
_start = newStart;
|
||||
}
|
||||
_length++;
|
||||
}
|
||||
|
||||
const char* c_str() {
|
||||
append(0);
|
||||
return _start;
|
||||
}
|
||||
|
||||
private:
|
||||
DynamicJsonBufferBase* _parent;
|
||||
char* _start;
|
||||
size_t _length;
|
||||
};
|
||||
|
||||
String startString() {
|
||||
return String(this);
|
||||
}
|
||||
|
||||
private:
|
||||
void alignNextAlloc() {
|
||||
if (_head) _head->size = this->round_size_up(_head->size);
|
||||
}
|
||||
|
||||
bool canAllocInHead(size_t bytes) const {
|
||||
return _head != NULL && _head->size + bytes <= _head->capacity;
|
||||
}
|
||||
|
||||
void* allocInHead(size_t bytes) {
|
||||
void* p = _head->data + _head->size;
|
||||
_head->size += bytes;
|
||||
return p;
|
||||
}
|
||||
|
||||
void* allocInNewBlock(size_t bytes) {
|
||||
size_t capacity = _nextBlockCapacity;
|
||||
if (bytes > capacity) capacity = bytes;
|
||||
if (!addNewBlock(capacity)) return NULL;
|
||||
_nextBlockCapacity *= 2;
|
||||
return allocInHead(bytes);
|
||||
}
|
||||
|
||||
bool addNewBlock(size_t capacity) {
|
||||
size_t bytes = EmptyBlockSize + capacity;
|
||||
Block* block = static_cast<Block*>(_allocator.allocate(bytes));
|
||||
if (block == NULL) return false;
|
||||
block->capacity = capacity;
|
||||
block->size = 0;
|
||||
block->next = _head;
|
||||
_head = block;
|
||||
return true;
|
||||
}
|
||||
|
||||
TAllocator _allocator;
|
||||
Block* _head;
|
||||
size_t _nextBlockCapacity;
|
||||
};
|
||||
|
||||
// Implements a JsonBuffer with dynamic memory allocation.
|
||||
// You are strongly encouraged to consider using StaticJsonBuffer which is much
|
||||
// more suitable for embedded systems.
|
||||
typedef Internals::DynamicJsonBufferBase<Internals::DefaultAllocator>
|
||||
DynamicJsonBuffer;
|
||||
} // namespace Internals
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
} // namespace ArduinoJson
|
@ -1,42 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <string.h>
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
// Handle the memory management (done in derived classes) and calls the parser.
|
||||
// This abstract class is implemented by StaticJsonBuffer which implements a
|
||||
// fixed memory allocation.
|
||||
class JsonBuffer {
|
||||
public:
|
||||
// Allocates n bytes in the JsonBuffer.
|
||||
// Return a pointer to the allocated memory or NULL if allocation fails.
|
||||
virtual void *alloc(size_t size) = 0;
|
||||
|
||||
protected:
|
||||
// CAUTION: NO VIRTUAL DESTRUCTOR!
|
||||
// If we add a virtual constructor the Arduino compiler will add malloc()
|
||||
// and free() to the binary, adding 706 useless bytes.
|
||||
~JsonBuffer() {}
|
||||
|
||||
// Preserve aligment if necessary
|
||||
static FORCE_INLINE size_t round_size_up(size_t bytes) {
|
||||
#if ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
const size_t x = sizeof(void *) - 1;
|
||||
return (bytes + x) & ~x;
|
||||
#else
|
||||
return bytes;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,22 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class JsonBufferAllocated {
|
||||
public:
|
||||
void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() {
|
||||
if (!jsonBuffer) return NULL;
|
||||
return jsonBuffer->alloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *, JsonBuffer *)throw();
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
120
src/ArduinoJson/Memory/MemoryPool.hpp
Normal file
120
src/ArduinoJson/Memory/MemoryPool.hpp
Normal file
@ -0,0 +1,120 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Polyfills/assert.hpp"
|
||||
#include "../Polyfills/mpl/max.hpp"
|
||||
#include "../Variant/VariantSlot.hpp"
|
||||
#include "Alignment.hpp"
|
||||
#include "MemoryPool.hpp"
|
||||
#include "StringSlot.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// _begin _end
|
||||
// v v
|
||||
// +-------------+--------------+-----------+
|
||||
// | strings... | (free) | ...slots |
|
||||
// +-------------+--------------+-----------+
|
||||
// ^ ^
|
||||
// _left _right
|
||||
|
||||
class MemoryPool {
|
||||
public:
|
||||
MemoryPool(char* buf, size_t capa)
|
||||
: _begin(buf),
|
||||
_left(buf),
|
||||
_right(buf ? buf + capa : 0),
|
||||
_end(buf ? buf + capa : 0) {
|
||||
ARDUINOJSON_ASSERT(isAligned(_begin));
|
||||
ARDUINOJSON_ASSERT(isAligned(_right));
|
||||
ARDUINOJSON_ASSERT(isAligned(_end));
|
||||
}
|
||||
|
||||
void* buffer() {
|
||||
return _begin;
|
||||
}
|
||||
|
||||
// Gets the capacity of the memoryPool in bytes
|
||||
size_t capacity() const {
|
||||
return size_t(_end - _begin);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return size_t(_left - _begin + _end - _right);
|
||||
}
|
||||
|
||||
VariantSlot* allocVariant() {
|
||||
return allocRight<VariantSlot>();
|
||||
}
|
||||
|
||||
char* allocFrozenString(size_t n) {
|
||||
if (!canAlloc(n)) return 0;
|
||||
char* s = _left;
|
||||
_left += n;
|
||||
checkInvariants();
|
||||
return s;
|
||||
}
|
||||
|
||||
StringSlot allocExpandableString() {
|
||||
StringSlot s;
|
||||
s.value = _left;
|
||||
s.size = size_t(_right - _left);
|
||||
_left = _right;
|
||||
checkInvariants();
|
||||
return s;
|
||||
}
|
||||
|
||||
void freezeString(StringSlot& s, size_t newSize) {
|
||||
_left -= (s.size - newSize);
|
||||
s.size = newSize;
|
||||
checkInvariants();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_left = _begin;
|
||||
_right = _end;
|
||||
}
|
||||
|
||||
bool canAlloc(size_t bytes) const {
|
||||
return _left + bytes <= _right;
|
||||
}
|
||||
|
||||
bool owns(void* p) const {
|
||||
return _begin <= p && p < _end;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* allocRight() {
|
||||
return reinterpret_cast<T*>(allocRight(sizeof(T)));
|
||||
}
|
||||
|
||||
char* allocRight(size_t bytes) {
|
||||
if (!canAlloc(bytes)) return 0;
|
||||
_right -= bytes;
|
||||
return _right;
|
||||
}
|
||||
|
||||
// Workaround for missing placement new
|
||||
void* operator new(size_t, void* p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
StringSlot* allocStringSlot() {
|
||||
return allocRight<StringSlot>();
|
||||
}
|
||||
|
||||
void checkInvariants() {
|
||||
ARDUINOJSON_ASSERT(_begin <= _left);
|
||||
ARDUINOJSON_ASSERT(_left <= _right);
|
||||
ARDUINOJSON_ASSERT(_right <= _end);
|
||||
ARDUINOJSON_ASSERT(isAligned(_right));
|
||||
}
|
||||
|
||||
char *_begin, *_left, *_right, *_end;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,129 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Polyfills/mpl/max.hpp"
|
||||
#include "JsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class StaticJsonBufferBase : public JsonBuffer {
|
||||
public:
|
||||
class String {
|
||||
public:
|
||||
String(StaticJsonBufferBase* parent) : _parent(parent) {
|
||||
_start = parent->_buffer + parent->_size;
|
||||
}
|
||||
|
||||
void append(char c) {
|
||||
if (_parent->canAlloc(1)) {
|
||||
char* last = static_cast<char*>(_parent->doAlloc(1));
|
||||
*last = c;
|
||||
}
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
if (_parent->canAlloc(1)) {
|
||||
char* last = static_cast<char*>(_parent->doAlloc(1));
|
||||
*last = '\0';
|
||||
return _start;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
StaticJsonBufferBase* _parent;
|
||||
char* _start;
|
||||
};
|
||||
|
||||
StaticJsonBufferBase(char* buffer, size_t capa)
|
||||
: _buffer(buffer), _capacity(capa), _size(0) {}
|
||||
|
||||
// Gets the capacity of the buffer in bytes
|
||||
size_t capacity() const {
|
||||
return _capacity;
|
||||
}
|
||||
|
||||
// Gets the current usage of the buffer in bytes
|
||||
size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
// Allocates the specified amount of bytes in the buffer
|
||||
virtual void* alloc(size_t bytes) {
|
||||
alignNextAlloc();
|
||||
if (!canAlloc(bytes)) return NULL;
|
||||
return doAlloc(bytes);
|
||||
}
|
||||
|
||||
// Resets the buffer.
|
||||
// USE WITH CAUTION: this invalidates all previously allocated data
|
||||
void clear() {
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
String startString() {
|
||||
return String(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
~StaticJsonBufferBase() {}
|
||||
|
||||
private:
|
||||
void alignNextAlloc() {
|
||||
_size = round_size_up(_size);
|
||||
}
|
||||
|
||||
bool canAlloc(size_t bytes) const {
|
||||
return _size + bytes <= _capacity;
|
||||
}
|
||||
|
||||
void* doAlloc(size_t bytes) {
|
||||
void* p = &_buffer[_size];
|
||||
_size += bytes;
|
||||
return p;
|
||||
}
|
||||
|
||||
char* _buffer;
|
||||
size_t _capacity;
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
#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
|
||||
|
||||
// Implements a JsonBuffer with fixed memory allocation.
|
||||
// The template paramenter CAPACITY specifies the capacity of the buffer in
|
||||
// bytes.
|
||||
template <size_t CAPACITY>
|
||||
class StaticJsonBuffer : public Internals::StaticJsonBufferBase {
|
||||
static const size_t ACTUAL_CAPACITY = Internals::Max<1, CAPACITY>::value;
|
||||
|
||||
public:
|
||||
explicit StaticJsonBuffer()
|
||||
: Internals::StaticJsonBufferBase(_buffer, ACTUAL_CAPACITY) {}
|
||||
|
||||
private:
|
||||
char _buffer[ACTUAL_CAPACITY];
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
50
src/ArduinoJson/Memory/StringBuilder.hpp
Normal file
50
src/ArduinoJson/Memory/StringBuilder.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MemoryPool.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StringBuilder {
|
||||
public:
|
||||
explicit StringBuilder(MemoryPool* parent) : _parent(parent), _size(0) {
|
||||
_slot = _parent->allocExpandableString();
|
||||
}
|
||||
|
||||
void append(const char* s) {
|
||||
while (*s) append(*s++);
|
||||
}
|
||||
|
||||
void append(const char* s, size_t n) {
|
||||
while (n-- > 0) append(*s++);
|
||||
}
|
||||
|
||||
void append(char c) {
|
||||
if (!_slot.value) return;
|
||||
|
||||
if (_size >= _slot.size) {
|
||||
_slot.value = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
_slot.value[_size++] = c;
|
||||
}
|
||||
|
||||
char* complete() {
|
||||
append('\0');
|
||||
if (_slot.value) {
|
||||
_parent->freezeString(_slot, _size);
|
||||
}
|
||||
return _slot.value;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool* _parent;
|
||||
size_t _size;
|
||||
StringSlot _slot;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
18
src/ArduinoJson/Memory/StringSlot.hpp
Normal file
18
src/ArduinoJson/Memory/StringSlot.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
#define JSON_STRING_SIZE(SIZE) (SIZE)
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct StringSlot {
|
||||
char *value;
|
||||
size_t size;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -4,11 +4,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Strings/StringTypes.hpp"
|
||||
#include "../Strings/StringWrappers.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
namespace Internals {
|
||||
// A special type of data that can be used to insert pregenerated JSON portions.
|
||||
template <typename T>
|
||||
class SerializedValue {
|
||||
@ -51,20 +50,19 @@ class SerializedValue<TChar*> {
|
||||
TChar* _data;
|
||||
size_t _size;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
template <typename T>
|
||||
inline Internals::SerializedValue<T> serialized(T str) {
|
||||
return Internals::SerializedValue<T>(str);
|
||||
inline SerializedValue<T> serialized(T str) {
|
||||
return SerializedValue<T>(str);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline Internals::SerializedValue<TChar*> serialized(TChar* p) {
|
||||
return Internals::SerializedValue<TChar*>(p, Internals::makeString(p).size());
|
||||
inline SerializedValue<TChar*> serialized(TChar* p) {
|
||||
return SerializedValue<TChar*>(p, wrapString(p).size());
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline Internals::SerializedValue<TChar*> serialized(TChar* p, size_t n) {
|
||||
return Internals::SerializedValue<TChar*>(p, n);
|
||||
inline SerializedValue<TChar*> serialized(TChar* p, size_t n) {
|
||||
return SerializedValue<TChar*>(p, n);
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
18
src/ArduinoJson/Misc/Visitable.hpp
Normal file
18
src/ArduinoJson/Misc/Visitable.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct Visitable {
|
||||
// template<Visitor>
|
||||
// void accept(Visitor&) const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IsVisitable : is_base_of<Visitable, T> {};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -5,36 +5,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Deserialization/deserialize.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Memory/MemoryPool.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "./endianess.hpp"
|
||||
#include "./ieee754.hpp"
|
||||
#include "../Variant/VariantData.hpp"
|
||||
#include "endianess.hpp"
|
||||
#include "ieee754.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TReader, typename TStringStorage>
|
||||
class MsgPackDeserializer {
|
||||
typedef typename remove_reference<TStringStorage>::type::StringBuilder
|
||||
StringBuilder;
|
||||
typedef const char *StringType;
|
||||
|
||||
public:
|
||||
MsgPackDeserializer(JsonBuffer *buffer, TReader reader,
|
||||
MsgPackDeserializer(MemoryPool &pool, TReader reader,
|
||||
TStringStorage stringStorage, uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
: _pool(&pool),
|
||||
_reader(reader),
|
||||
_stringStorage(stringStorage),
|
||||
_nestingLimit(nestingLimit) {}
|
||||
|
||||
DeserializationError parse(JsonVariant &variant) {
|
||||
DeserializationError parse(VariantData &variant) {
|
||||
uint8_t code;
|
||||
if (!readByte(code)) return DeserializationError::IncompleteInput;
|
||||
|
||||
if ((code & 0x80) == 0) {
|
||||
variant = code;
|
||||
variant.setUnsignedInteger(code);
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
if ((code & 0xe0) == 0xe0) {
|
||||
variant = static_cast<int8_t>(code);
|
||||
// TODO: add setNegativeInteger()
|
||||
variant.setSignedInteger(static_cast<int8_t>(code));
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
@ -42,21 +46,25 @@ class MsgPackDeserializer {
|
||||
return readString(variant, code & 0x1f);
|
||||
}
|
||||
|
||||
if ((code & 0xf0) == 0x90) return readArray(variant, code & 0x0F);
|
||||
if ((code & 0xf0) == 0x90) {
|
||||
return readArray(variant.toArray(), code & 0x0F);
|
||||
}
|
||||
|
||||
if ((code & 0xf0) == 0x80) return readObject(variant, code & 0x0F);
|
||||
if ((code & 0xf0) == 0x80) {
|
||||
return readObject(variant.toObject(), code & 0x0F);
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case 0xc0:
|
||||
variant = static_cast<char *>(0);
|
||||
// already null
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc2:
|
||||
variant = false;
|
||||
variant.setBoolean(false);
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc3:
|
||||
variant = true;
|
||||
variant.setBoolean(true);
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xcc:
|
||||
@ -69,7 +77,7 @@ class MsgPackDeserializer {
|
||||
return readInteger<uint32_t>(variant);
|
||||
|
||||
case 0xcf:
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
return readInteger<uint64_t>(variant);
|
||||
#else
|
||||
readInteger<uint32_t>();
|
||||
@ -86,7 +94,7 @@ class MsgPackDeserializer {
|
||||
return readInteger<int32_t>(variant);
|
||||
|
||||
case 0xd3:
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
return readInteger<int64_t>(variant);
|
||||
#else
|
||||
if (!skip(4)) return DeserializationError::IncompleteInput;
|
||||
@ -109,16 +117,16 @@ class MsgPackDeserializer {
|
||||
return readString<uint32_t>(variant);
|
||||
|
||||
case 0xdc:
|
||||
return readArray<uint16_t>(variant);
|
||||
return readArray<uint16_t>(variant.toArray());
|
||||
|
||||
case 0xdd:
|
||||
return readArray<uint32_t>(variant);
|
||||
return readArray<uint32_t>(variant.toArray());
|
||||
|
||||
case 0xde:
|
||||
return readObject<uint16_t>(variant);
|
||||
return readObject<uint16_t>(variant.toObject());
|
||||
|
||||
case 0xdf:
|
||||
return readObject<uint32_t>(variant);
|
||||
return readObject<uint32_t>(variant.toObject());
|
||||
|
||||
default:
|
||||
return DeserializationError::NotSupported;
|
||||
@ -171,155 +179,171 @@ class MsgPackDeserializer {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DeserializationError readInteger(JsonVariant &variant) {
|
||||
DeserializationError readInteger(VariantData &variant) {
|
||||
T value;
|
||||
if (!readInteger(value)) return DeserializationError::IncompleteInput;
|
||||
variant = value;
|
||||
variant.setInteger(value);
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 4, DeserializationError>::type readFloat(
|
||||
JsonVariant &variant) {
|
||||
VariantData &variant) {
|
||||
T value;
|
||||
if (!readBytes(value)) return DeserializationError::IncompleteInput;
|
||||
fixEndianess(value);
|
||||
variant = value;
|
||||
variant.setFloat(value);
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 8, DeserializationError>::type readDouble(
|
||||
JsonVariant &variant) {
|
||||
VariantData &variant) {
|
||||
T value;
|
||||
if (!readBytes(value)) return DeserializationError::IncompleteInput;
|
||||
fixEndianess(value);
|
||||
variant = value;
|
||||
variant.setFloat(value);
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 4, DeserializationError>::type readDouble(
|
||||
JsonVariant &variant) {
|
||||
VariantData &variant) {
|
||||
uint8_t i[8]; // input is 8 bytes
|
||||
T value; // output is 4 bytes
|
||||
uint8_t *o = reinterpret_cast<uint8_t *>(&value);
|
||||
if (!readBytes(i, 8)) return DeserializationError::IncompleteInput;
|
||||
doubleToFloat(i, o);
|
||||
fixEndianess(value);
|
||||
variant = value;
|
||||
variant.setFloat(value);
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DeserializationError readString(JsonVariant &variant) {
|
||||
DeserializationError readString(VariantData &variant) {
|
||||
T size;
|
||||
if (!readInteger(size)) return DeserializationError::IncompleteInput;
|
||||
return readString(variant, size);
|
||||
}
|
||||
|
||||
DeserializationError readString(JsonVariant &variant, size_t n) {
|
||||
typename remove_reference<TStringStorage>::type::String str =
|
||||
_stringStorage.startString();
|
||||
template <typename T>
|
||||
DeserializationError readString(StringType &str) {
|
||||
T size;
|
||||
if (!readInteger(size)) return DeserializationError::IncompleteInput;
|
||||
return readString(str, size);
|
||||
}
|
||||
|
||||
DeserializationError readString(VariantData &variant, size_t n) {
|
||||
StringType s;
|
||||
DeserializationError err = readString(s, n);
|
||||
if (!err) variant.setOwnedString(s);
|
||||
return err;
|
||||
}
|
||||
|
||||
DeserializationError readString(StringType &result, size_t n) {
|
||||
StringBuilder builder = _stringStorage.startString();
|
||||
for (; n; --n) {
|
||||
uint8_t c;
|
||||
if (!readBytes(c)) return DeserializationError::IncompleteInput;
|
||||
str.append(static_cast<char>(c));
|
||||
builder.append(static_cast<char>(c));
|
||||
}
|
||||
const char *s = str.c_str();
|
||||
if (s == NULL) return DeserializationError::NoMemory;
|
||||
variant = s;
|
||||
result = builder.complete();
|
||||
if (!result) return DeserializationError::NoMemory;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename TSize>
|
||||
DeserializationError readArray(JsonVariant &variant) {
|
||||
DeserializationError readArray(CollectionData &array) {
|
||||
TSize size;
|
||||
if (!readInteger(size)) return DeserializationError::IncompleteInput;
|
||||
return readArray(variant, size);
|
||||
return readArray(array, size);
|
||||
}
|
||||
|
||||
DeserializationError readArray(JsonVariant &variant, size_t n) {
|
||||
JsonArray array(_buffer);
|
||||
if (array.isNull()) return DeserializationError::NoMemory;
|
||||
variant = array;
|
||||
return readArray(array, n);
|
||||
}
|
||||
|
||||
DeserializationError readArray(JsonArray array, size_t n) {
|
||||
DeserializationError readArray(CollectionData &array, size_t n) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
--_nestingLimit;
|
||||
for (; n; --n) {
|
||||
JsonVariant variant;
|
||||
DeserializationError err = parse(variant);
|
||||
VariantData *value = array.add(_pool);
|
||||
if (!value) return DeserializationError::NoMemory;
|
||||
|
||||
DeserializationError err = parse(*value);
|
||||
if (err) return err;
|
||||
if (!array.add(variant)) return DeserializationError::NoMemory;
|
||||
}
|
||||
++_nestingLimit;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename TSize>
|
||||
DeserializationError readObject(JsonVariant &variant) {
|
||||
DeserializationError readObject(CollectionData &object) {
|
||||
TSize size;
|
||||
if (!readInteger(size)) return DeserializationError::IncompleteInput;
|
||||
return readObject(variant, size);
|
||||
return readObject(object, size);
|
||||
}
|
||||
|
||||
DeserializationError readObject(JsonVariant &variant, size_t n) {
|
||||
JsonObject object(_buffer);
|
||||
if (object.isNull()) return DeserializationError::NoMemory;
|
||||
variant = object;
|
||||
return readObject(object, n);
|
||||
}
|
||||
|
||||
DeserializationError readObject(JsonObject object, size_t n) {
|
||||
DeserializationError readObject(CollectionData &object, size_t n) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
--_nestingLimit;
|
||||
for (; n; --n) {
|
||||
DeserializationError err;
|
||||
JsonVariant variant;
|
||||
err = parse(variant);
|
||||
VariantSlot *slot = object.addSlot(_pool);
|
||||
if (!slot) return DeserializationError::NoMemory;
|
||||
|
||||
StringType key;
|
||||
DeserializationError err = parseKey(key);
|
||||
if (err) return err;
|
||||
const char *key = variant.as<char *>();
|
||||
if (!key) return DeserializationError::NotSupported;
|
||||
err = parse(variant);
|
||||
slot->setOwnedKey(key);
|
||||
|
||||
err = parse(*slot->data());
|
||||
if (err) return err;
|
||||
if (!object.set(key, variant)) return DeserializationError::NoMemory;
|
||||
}
|
||||
++_nestingLimit;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
DeserializationError parseKey(StringType &key) {
|
||||
uint8_t code;
|
||||
if (!readByte(code)) return DeserializationError::IncompleteInput;
|
||||
|
||||
if ((code & 0xe0) == 0xa0) return readString(key, code & 0x1f);
|
||||
|
||||
switch (code) {
|
||||
case 0xd9:
|
||||
return readString<uint8_t>(key);
|
||||
|
||||
case 0xda:
|
||||
return readString<uint16_t>(key);
|
||||
|
||||
case 0xdb:
|
||||
return readString<uint32_t>(key);
|
||||
|
||||
default:
|
||||
return DeserializationError::NotSupported;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryPool *_pool;
|
||||
TReader _reader;
|
||||
TStringStorage _stringStorage;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, const TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<MsgPackDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input) {
|
||||
using namespace Internals;
|
||||
return deserialize<MsgPackDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return deserialize<MsgPackDeserializer>(doc, input, inputSize);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeMsgPack(TDocument &doc, TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<MsgPackDeserializer>(doc, input);
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -4,14 +4,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "./endianess.hpp"
|
||||
#include "../Variant/VariantData.hpp"
|
||||
#include "endianess.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TWriter>
|
||||
class MsgPackSerializer {
|
||||
@ -19,13 +18,13 @@ class MsgPackSerializer {
|
||||
MsgPackSerializer(TWriter& writer) : _writer(&writer), _bytesWritten(0) {}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 4>::type acceptFloat(T value32) {
|
||||
typename enable_if<sizeof(T) == 4>::type visitFloat(T value32) {
|
||||
writeByte(0xCA);
|
||||
writeInteger(value32);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 8>::type acceptFloat(T value64) {
|
||||
typename enable_if<sizeof(T) == 8>::type visitFloat(T value64) {
|
||||
float value32 = float(value64);
|
||||
if (value32 == value64) {
|
||||
writeByte(0xCA);
|
||||
@ -36,7 +35,7 @@ class MsgPackSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
void acceptArray(const JsonArray& array) {
|
||||
void visitArray(const CollectionData& array) {
|
||||
size_t n = array.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x90 + array.size()));
|
||||
@ -47,13 +46,12 @@ class MsgPackSerializer {
|
||||
writeByte(0xDD);
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
for (JsonArray::const_iterator it = array.begin(); it != array.end();
|
||||
++it) {
|
||||
it->visit(*this);
|
||||
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
|
||||
slot->data()->accept(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void acceptObject(const JsonObject& object) {
|
||||
void visitObject(const CollectionData& object) {
|
||||
size_t n = object.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x80 + n));
|
||||
@ -64,14 +62,13 @@ class MsgPackSerializer {
|
||||
writeByte(0xDF);
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
for (JsonObject::const_iterator it = object.begin(); it != object.end();
|
||||
++it) {
|
||||
acceptString(it->key);
|
||||
it->value.visit(*this);
|
||||
for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
|
||||
visitString(slot->key());
|
||||
slot->data()->accept(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void acceptString(const char* value) {
|
||||
void visitString(const char* value) {
|
||||
if (!value) return writeByte(0xC0); // nil
|
||||
|
||||
size_t n = strlen(value);
|
||||
@ -91,12 +88,12 @@ class MsgPackSerializer {
|
||||
writeBytes(reinterpret_cast<const uint8_t*>(value), n);
|
||||
}
|
||||
|
||||
void acceptRawJson(const char* data, size_t size) {
|
||||
void visitRawJson(const char* data, size_t size) {
|
||||
writeBytes(reinterpret_cast<const uint8_t*>(data), size);
|
||||
}
|
||||
|
||||
void acceptNegativeInteger(JsonUInt value) {
|
||||
JsonUInt negated = JsonUInt(~value + 1);
|
||||
void visitNegativeInteger(UInt value) {
|
||||
UInt negated = UInt(~value + 1);
|
||||
if (value <= 0x20) {
|
||||
writeInteger(int8_t(negated));
|
||||
} else if (value <= 0x80) {
|
||||
@ -109,7 +106,7 @@ class MsgPackSerializer {
|
||||
writeByte(0xD2);
|
||||
writeInteger(int32_t(negated));
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
else {
|
||||
writeByte(0xD3);
|
||||
writeInteger(int64_t(negated));
|
||||
@ -117,7 +114,7 @@ class MsgPackSerializer {
|
||||
#endif
|
||||
}
|
||||
|
||||
void acceptPositiveInteger(JsonUInt value) {
|
||||
void visitPositiveInteger(UInt value) {
|
||||
if (value <= 0x7F) {
|
||||
writeInteger(uint8_t(value));
|
||||
} else if (value <= 0xFF) {
|
||||
@ -130,7 +127,7 @@ class MsgPackSerializer {
|
||||
writeByte(0xCE);
|
||||
writeInteger(uint32_t(value));
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
else {
|
||||
writeByte(0xCF);
|
||||
writeInteger(uint64_t(value));
|
||||
@ -138,11 +135,11 @@ class MsgPackSerializer {
|
||||
#endif
|
||||
}
|
||||
|
||||
void acceptBoolean(bool value) {
|
||||
void visitBoolean(bool value) {
|
||||
writeByte(value ? 0xC3 : 0xC2);
|
||||
}
|
||||
|
||||
void acceptNull() {
|
||||
void visitNull() {
|
||||
writeByte(0xC0);
|
||||
}
|
||||
|
||||
@ -168,25 +165,21 @@ class MsgPackSerializer {
|
||||
TWriter* _writer;
|
||||
size_t _bytesWritten;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
|
||||
using namespace Internals;
|
||||
return serialize<MsgPackSerializer>(source, output);
|
||||
}
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
inline size_t serializeMsgPack(const TSource& source, TDestination* output,
|
||||
size_t size) {
|
||||
using namespace Internals;
|
||||
return serialize<MsgPackSerializer>(source, output, size);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
inline size_t measureMsgPack(const TSource& source) {
|
||||
using namespace Internals;
|
||||
return measure<MsgPackSerializer>(source);
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -7,8 +7,7 @@
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Polyfills/utility.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 8>) {
|
||||
swap(p[0], p[7]);
|
||||
@ -36,5 +35,4 @@ inline void fixEndianess(T& value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {
|
||||
f[0] = uint8_t((d[0] & 0xC0) | (d[0] << 3 & 0x3f) | (d[1] >> 5));
|
||||
@ -14,5 +13,4 @@ inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {
|
||||
f[3] = uint8_t((d[3] << 3) | (d[4] >> 5));
|
||||
}
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
22
src/ArduinoJson/Namespace.hpp
Normal file
22
src/ArduinoJson/Namespace.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "version.hpp"
|
||||
|
||||
#include "Configuration.hpp"
|
||||
|
||||
#define ARDUINOJSON_DO_CONCAT(A, B) A##B
|
||||
#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_DO_CONCAT(A, B)
|
||||
#define ARDUINOJSON_CONCAT4(A, B, C, D) \
|
||||
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
|
||||
#define ARDUINOJSON_CONCAT8(A, B, C, D, E, F, G, H) \
|
||||
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT4(A, B, C, D), \
|
||||
ARDUINOJSON_CONCAT4(E, F, G, H))
|
||||
|
||||
#define ARDUINOJSON_NAMESPACE \
|
||||
ARDUINOJSON_CONCAT8(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
|
||||
ARDUINOJSON_VERSION_MINOR, ARDUINOJSON_VERSION_REVISION, \
|
||||
_, ARDUINOJSON_USE_LONG_LONG, _, ARDUINOJSON_USE_DOUBLE)
|
@ -6,13 +6,11 @@
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
typedef double JsonFloat;
|
||||
typedef double Float;
|
||||
#else
|
||||
typedef float JsonFloat;
|
||||
typedef float Float;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -8,8 +8,7 @@
|
||||
#include "../Polyfills/math.hpp"
|
||||
#include "./FloatTraits.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TFloat>
|
||||
struct FloatParts {
|
||||
@ -85,5 +84,4 @@ struct FloatParts {
|
||||
return powersOf10;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -4,13 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> // for size_t
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Polyfills/math.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T, size_t = sizeof(T)>
|
||||
struct FloatTraits {};
|
||||
@ -167,5 +166,4 @@ struct FloatTraits<T, 4 /*32bits*/> {
|
||||
return forge(0x7f800000);
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
20
src/ArduinoJson/Numbers/Integer.hpp
Normal file
20
src/ArduinoJson/Numbers/Integer.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
#include <stdint.h> // int64_t
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
typedef int64_t Integer;
|
||||
typedef uint64_t UInt;
|
||||
#else
|
||||
typedef long Integer;
|
||||
typedef unsigned long UInt;
|
||||
#endif
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -7,8 +7,7 @@
|
||||
#include <string.h> // for strcmp
|
||||
#include "../Polyfills/ctype.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline bool isFloat(const char* s) {
|
||||
if (!s) return false;
|
||||
@ -34,5 +33,4 @@ inline bool isFloat(const char* s) {
|
||||
|
||||
return *s == '\0';
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -6,8 +6,7 @@
|
||||
|
||||
#include "../Polyfills/ctype.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline bool isInteger(const char* s) {
|
||||
if (!s || !*s) return false;
|
||||
@ -15,5 +14,4 @@ inline bool isInteger(const char* s) {
|
||||
while (isdigit(*s)) s++;
|
||||
return *s == '\0';
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -8,8 +8,7 @@
|
||||
#include "../Polyfills/ctype.hpp"
|
||||
#include "../Polyfills/math.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T>
|
||||
inline T parseFloat(const char* s) {
|
||||
@ -86,5 +85,4 @@ inline T parseFloat(const char* s) {
|
||||
|
||||
return negative_result ? -result : result;
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -4,13 +4,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Polyfills/ctype.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
template <typename T>
|
||||
T parseInteger(const char *s) {
|
||||
if (!s) return 0; // NULL
|
||||
@ -37,5 +34,4 @@ T parseInteger(const char *s) {
|
||||
|
||||
return negative_result ? T(~result + 1) : result;
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
55
src/ArduinoJson/Object/ObjectFunctions.hpp
Normal file
55
src/ArduinoJson/Object/ObjectFunctions.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Collection/CollectionData.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename Visitor>
|
||||
void objectAccept(const CollectionData *obj, Visitor &visitor) {
|
||||
if (obj)
|
||||
visitor.visitObject(*obj);
|
||||
else
|
||||
visitor.visitNull();
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline bool objectContainsKey(const CollectionData *obj, TKey key) {
|
||||
return obj && obj->containsKey(key);
|
||||
}
|
||||
|
||||
inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
|
||||
if (lhs == rhs) return true;
|
||||
if (!lhs || !rhs) return false;
|
||||
return lhs->equalsObject(*rhs);
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline VariantData *objectGet(const CollectionData *obj, TKey key) {
|
||||
if (!obj) return 0;
|
||||
return obj->get(key);
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
void objectRemove(CollectionData *obj, TKey key) {
|
||||
if (!obj) return;
|
||||
obj->remove(key);
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline VariantData *objectSet(CollectionData *obj, TKey key, MemoryPool *pool) {
|
||||
if (!obj) return 0;
|
||||
|
||||
// ignore null key
|
||||
if (key.isNull()) return 0;
|
||||
|
||||
// search a matching key
|
||||
VariantData *var = obj->get(key);
|
||||
if (var) return var;
|
||||
|
||||
return obj->add(key, pool);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
21
src/ArduinoJson/Object/ObjectImpl.hpp
Normal file
21
src/ArduinoJson/Object/ObjectImpl.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Array/ArrayRef.hpp"
|
||||
#include "ObjectRef.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TString>
|
||||
inline ArrayRef ObjectRef::createNestedArray(const TString& key) const {
|
||||
return set(key).template to<ArrayRef>();
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
inline ArrayRef ObjectRef::createNestedArray(TString* key) const {
|
||||
return set(key).template to<ArrayRef>();
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
123
src/ArduinoJson/Object/ObjectIterator.hpp
Normal file
123
src/ArduinoJson/Object/ObjectIterator.hpp
Normal file
@ -0,0 +1,123 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Variant/SlotFunctions.hpp"
|
||||
#include "Pair.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class PairPtr {
|
||||
public:
|
||||
PairPtr(MemoryPool *pool, VariantSlot *slot) : _pair(pool, slot) {}
|
||||
|
||||
const Pair *operator->() const {
|
||||
return &_pair;
|
||||
}
|
||||
|
||||
const Pair &operator*() const {
|
||||
return _pair;
|
||||
}
|
||||
|
||||
private:
|
||||
Pair _pair;
|
||||
};
|
||||
|
||||
class ObjectIterator {
|
||||
public:
|
||||
ObjectIterator() : _slot(0) {}
|
||||
|
||||
explicit ObjectIterator(MemoryPool *pool, VariantSlot *slot)
|
||||
: _pool(pool), _slot(slot) {}
|
||||
|
||||
Pair operator*() const {
|
||||
return Pair(_pool, _slot);
|
||||
}
|
||||
PairPtr operator->() {
|
||||
return PairPtr(_pool, _slot);
|
||||
}
|
||||
|
||||
bool operator==(const ObjectIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const ObjectIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
ObjectIterator &operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ObjectIterator &operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
VariantSlot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool *_pool;
|
||||
VariantSlot *_slot;
|
||||
};
|
||||
|
||||
class PairConstPtr {
|
||||
public:
|
||||
PairConstPtr(const VariantSlot *slot) : _pair(slot) {}
|
||||
|
||||
const PairConst *operator->() const {
|
||||
return &_pair;
|
||||
}
|
||||
|
||||
const PairConst &operator*() const {
|
||||
return _pair;
|
||||
}
|
||||
|
||||
private:
|
||||
PairConst _pair;
|
||||
};
|
||||
|
||||
class ObjectConstIterator {
|
||||
public:
|
||||
ObjectConstIterator() : _slot(0) {}
|
||||
|
||||
explicit ObjectConstIterator(const VariantSlot *slot) : _slot(slot) {}
|
||||
|
||||
PairConst operator*() const {
|
||||
return PairConst(_slot);
|
||||
}
|
||||
PairConstPtr operator->() {
|
||||
return PairConstPtr(_slot);
|
||||
}
|
||||
|
||||
bool operator==(const ObjectConstIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const ObjectConstIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
ObjectConstIterator &operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ObjectConstIterator &operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const VariantSlot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
const VariantSlot *_slot;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
271
src/ArduinoJson/Object/ObjectRef.hpp
Normal file
271
src/ArduinoJson/Object/ObjectRef.hpp
Normal file
@ -0,0 +1,271 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ObjectFunctions.hpp"
|
||||
#include "ObjectIterator.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
// Can be very handy to determine the size of a StaticMemoryPool.
|
||||
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TData>
|
||||
class ObjectRefBase {
|
||||
public:
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
objectAccept(_data, visitor);
|
||||
}
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE bool containsKey(const TKey& key) const {
|
||||
return objectContainsKey(_data, wrapString(key));
|
||||
}
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE bool containsKey(TKey* key) const {
|
||||
return objectContainsKey(_data, wrapString(key));
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return _data ? _data->size() : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
ObjectRefBase(TData* data) : _data(data) {}
|
||||
TData* _data;
|
||||
};
|
||||
|
||||
class ObjectConstRef : public ObjectRefBase<const CollectionData>,
|
||||
public Visitable {
|
||||
friend class ObjectRef;
|
||||
typedef ObjectRefBase<const CollectionData> base_type;
|
||||
|
||||
public:
|
||||
typedef ObjectConstIterator iterator;
|
||||
|
||||
ObjectConstRef() : base_type(0) {}
|
||||
ObjectConstRef(const CollectionData* data) : base_type(data) {}
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_data->head());
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, ArrayConstRef, ObjectConstRef
|
||||
template <typename TKey>
|
||||
FORCE_INLINE VariantConstRef get(const TKey& key) const {
|
||||
return get_impl(wrapString(key));
|
||||
}
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = char*, const char*, const __FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, ArrayConstRef, ObjectConstRef
|
||||
template <typename TKey>
|
||||
FORCE_INLINE VariantConstRef get(TKey* key) const {
|
||||
return get_impl(wrapString(key));
|
||||
}
|
||||
|
||||
//
|
||||
// VariantConstRef operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantConstRef>::type
|
||||
operator[](const TKey& key) const {
|
||||
return get_impl(wrapString(key));
|
||||
}
|
||||
//
|
||||
// VariantConstRef operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const __FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE typename enable_if<IsString<TKey*>::value, VariantConstRef>::type
|
||||
operator[](TKey* key) const {
|
||||
return get_impl(wrapString(key));
|
||||
}
|
||||
|
||||
FORCE_INLINE bool operator==(ObjectConstRef rhs) const {
|
||||
return objectEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TKey>
|
||||
FORCE_INLINE VariantConstRef get_impl(TKey key) const {
|
||||
return VariantConstRef(objectGet(_data, key));
|
||||
}
|
||||
};
|
||||
|
||||
class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable {
|
||||
typedef ObjectRefBase<CollectionData> base_type;
|
||||
|
||||
public:
|
||||
typedef ObjectIterator iterator;
|
||||
|
||||
FORCE_INLINE ObjectRef() : base_type(0), _pool(0) {}
|
||||
FORCE_INLINE ObjectRef(MemoryPool* buf, CollectionData* data)
|
||||
: base_type(data), _pool(buf) {}
|
||||
|
||||
operator VariantRef() const {
|
||||
return VariantRef(_pool, reinterpret_cast<VariantData*>(_data));
|
||||
}
|
||||
|
||||
operator ObjectConstRef() const {
|
||||
return ObjectConstRef(_data);
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_pool, _data->head());
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
void clear() const {
|
||||
if (!_data) return;
|
||||
_data->clear();
|
||||
}
|
||||
|
||||
FORCE_INLINE bool copyFrom(ObjectConstRef src) {
|
||||
if (!_data || !src._data) return false;
|
||||
return _data->copyFrom(*src._data, _pool);
|
||||
}
|
||||
|
||||
// Creates and adds a ArrayRef.
|
||||
//
|
||||
// ArrayRef createNestedArray(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE ArrayRef createNestedArray(const TKey& key) const;
|
||||
// ArrayRef createNestedArray(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE ArrayRef createNestedArray(TKey* key) const;
|
||||
|
||||
// Creates and adds a ObjectRef.
|
||||
//
|
||||
// ObjectRef createNestedObject(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE ObjectRef createNestedObject(const TKey& key) const {
|
||||
return set(key).template to<ObjectRef>();
|
||||
}
|
||||
//
|
||||
// ObjectRef createNestedObject(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE ObjectRef createNestedObject(TKey* key) const {
|
||||
return set(key).template to<ObjectRef>();
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename TKey>
|
||||
FORCE_INLINE VariantRef get(const TKey& key) const {
|
||||
return get_impl(wrapString(key));
|
||||
}
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = char*, const char*, const __FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename TKey>
|
||||
FORCE_INLINE VariantRef get(TKey* key) const {
|
||||
return get_impl(wrapString(key));
|
||||
}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
//
|
||||
// ObjectSubscript operator[](TKey)
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE ObjectSubscript<const TKey&> operator[](const TKey& key) const {
|
||||
return ObjectSubscript<const TKey&>(*this, key);
|
||||
}
|
||||
//
|
||||
// ObjectSubscript operator[](TKey)
|
||||
// TKey = char*, const char*, char[], const char[N], const
|
||||
// __FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE ObjectSubscript<TKey*> operator[](TKey* key) const {
|
||||
return ObjectSubscript<TKey*>(*this, key);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool operator==(ObjectRef rhs) const {
|
||||
return objectEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
FORCE_INLINE void remove(iterator it) const {
|
||||
if (!_data) return;
|
||||
_data->remove(it.internal());
|
||||
}
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE void remove(const TKey& key) const {
|
||||
objectRemove(_data, wrapString(key));
|
||||
}
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE void remove(TKey* key) const {
|
||||
objectRemove(_data, wrapString(key));
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
FORCE_INLINE VariantRef set(TKey* key) const {
|
||||
return set_impl(wrapString(key));
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
FORCE_INLINE VariantRef set(const TKey& key) const {
|
||||
return set_impl(wrapString(key));
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TKey>
|
||||
FORCE_INLINE VariantRef get_impl(TKey key) const {
|
||||
return VariantRef(_pool, objectGet(_data, key));
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
FORCE_INLINE VariantRef set_impl(TKey key) const {
|
||||
return VariantRef(_pool, objectSet(_data, key, _pool));
|
||||
}
|
||||
|
||||
MemoryPool* _pool;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
132
src/ArduinoJson/Object/ObjectSubscript.hpp
Normal file
132
src/ArduinoJson/Object/ObjectSubscript.hpp
Normal file
@ -0,0 +1,132 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Operators/VariantOperators.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4522)
|
||||
#endif
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TStringRef>
|
||||
class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >,
|
||||
public Visitable {
|
||||
typedef ObjectSubscript<TStringRef> this_type;
|
||||
|
||||
public:
|
||||
FORCE_INLINE ObjectSubscript(ObjectRef object, TStringRef key)
|
||||
: _object(object), _key(key) {}
|
||||
|
||||
operator VariantConstRef() const {
|
||||
return get_impl();
|
||||
}
|
||||
|
||||
FORCE_INLINE this_type &operator=(const this_type &src) {
|
||||
set_impl().set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Set the specified value
|
||||
//
|
||||
// operator=(const TValue&);
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
|
||||
operator=(const TValue &src) {
|
||||
set_impl().set(src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue);
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE this_type &operator=(TValue *src) {
|
||||
set_impl().set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return get_impl().isNull();
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename VariantAs<TValue>::type as() const {
|
||||
return get_impl().template as<TValue>();
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool is() const {
|
||||
return get_impl().template is<TValue>();
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename VariantTo<TValue>::type to() {
|
||||
return set_impl().template to<TValue>();
|
||||
}
|
||||
|
||||
// Sets the specified value.
|
||||
//
|
||||
// bool set(const TValue&);
|
||||
// TValue = bool, char, long, int, short, float, double, serialized,
|
||||
// VariantRef,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
|
||||
const TValue &value) {
|
||||
return set_impl().set(value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue);
|
||||
// TValue = char*, const char, const __FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue *value) {
|
||||
return set_impl().set(value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor &visitor) const {
|
||||
return get_impl().accept(visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
FORCE_INLINE VariantRef get_impl() const {
|
||||
return _object.get(_key);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantRef set_impl() const {
|
||||
return _object.set(_key);
|
||||
}
|
||||
|
||||
ObjectRef _object;
|
||||
TStringRef _key;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString>::value,
|
||||
ObjectSubscript<const TString &> >::type
|
||||
VariantSubscripts<TImpl>::operator[](const TString &key) const {
|
||||
return impl()->template as<ObjectRef>()[key];
|
||||
}
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString *>::value,
|
||||
ObjectSubscript<TString *> >::type
|
||||
VariantSubscripts<TImpl>::operator[](TString *key) const {
|
||||
return impl()->template as<ObjectRef>()[key];
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
55
src/ArduinoJson/Object/Pair.hpp
Normal file
55
src/ArduinoJson/Object/Pair.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Strings/String.hpp"
|
||||
#include "../Variant/VariantRef.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
// A key value pair for CollectionData.
|
||||
class Pair {
|
||||
public:
|
||||
Pair(MemoryPool* pool, VariantSlot* slot) {
|
||||
if (slot) {
|
||||
_key = slot->key();
|
||||
_value = VariantRef(pool, slot->data());
|
||||
}
|
||||
}
|
||||
|
||||
String key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
VariantRef value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
String _key;
|
||||
VariantRef _value;
|
||||
};
|
||||
|
||||
class PairConst {
|
||||
public:
|
||||
PairConst(const VariantSlot* slot) {
|
||||
if (slot) {
|
||||
_key = slot->key();
|
||||
_value = VariantConstRef(slot->data());
|
||||
}
|
||||
}
|
||||
|
||||
String key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
VariantConstRef value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
String _key;
|
||||
VariantConstRef _value;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user