forked from bblanchon/ArduinoJson
Compare commits
31 Commits
v6.5.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 |
@ -125,4 +125,6 @@ matrix:
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- "fuzzing/json_corpus"
|
||||
- "fuzzing/msgpack_corpus"
|
||||
script: scripts/travis/$SCRIPT.sh
|
||||
|
21
CHANGELOG.md
21
CHANGELOG.md
@ -1,6 +1,27 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
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)
|
||||
-----------
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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.5.0-beta",
|
||||
"version": "6.7.0-beta",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "https://blog.benoitblanchon.fr"
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=ArduinoJson
|
||||
version=6.5.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
|
@ -47,3 +47,7 @@ update_version_in_source
|
||||
commit_new_version
|
||||
add_tag
|
||||
push
|
||||
|
||||
scripts/build-arduino-package.sh
|
||||
scripts/build-single-header.sh
|
||||
scripts/wandbox/publish.sh "../ArduinoJson-$TAG.h"
|
||||
|
@ -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"
|
@ -6,17 +6,20 @@
|
||||
|
||||
#include "ArduinoJson/Namespace.hpp"
|
||||
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonDocument.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/JsonVariant.hpp"
|
||||
#include "ArduinoJson/Array/ArrayRef.hpp"
|
||||
#include "ArduinoJson/Object/ObjectRef.hpp"
|
||||
#include "ArduinoJson/Variant/VariantRef.hpp"
|
||||
|
||||
#include "ArduinoJson/Data/VariantAsImpl.hpp"
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonArraySubscript.hpp"
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/JsonObjectSubscript.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
|
||||
|
||||
#include "ArduinoJson/Array/ArrayImpl.hpp"
|
||||
#include "ArduinoJson/Array/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"
|
||||
@ -25,19 +28,19 @@
|
||||
#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::JsonArray;
|
||||
using ARDUINOJSON_NAMESPACE::JsonArrayConst;
|
||||
using ARDUINOJSON_NAMESPACE::JsonFloat;
|
||||
using ARDUINOJSON_NAMESPACE::JsonInteger;
|
||||
using ARDUINOJSON_NAMESPACE::JsonKey;
|
||||
using ARDUINOJSON_NAMESPACE::JsonObject;
|
||||
using ARDUINOJSON_NAMESPACE::JsonObjectConst;
|
||||
using ARDUINOJSON_NAMESPACE::JsonPair;
|
||||
using ARDUINOJSON_NAMESPACE::JsonUInt;
|
||||
using ARDUINOJSON_NAMESPACE::JsonVariant;
|
||||
using ARDUINOJSON_NAMESPACE::JsonVariantConst;
|
||||
using ARDUINOJSON_NAMESPACE::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
|
@ -4,8 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Operators/VariantOperators.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
@ -13,67 +13,67 @@
|
||||
#endif
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript>,
|
||||
public Visitable {
|
||||
class ArraySubscript : public VariantOperators<ArraySubscript>,
|
||||
public Visitable {
|
||||
public:
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
|
||||
FORCE_INLINE ArraySubscript(ArrayRef array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
|
||||
get_impl().set(src.as<JsonVariantConst>());
|
||||
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, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
|
||||
FORCE_INLINE ArraySubscript& operator=(const T& src) {
|
||||
get_impl().set(src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
// operator=(TValue)
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE JsonArraySubscript& operator=(T* src) {
|
||||
FORCE_INLINE ArraySubscript& operator=(T* src) {
|
||||
get_impl().set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _index >= _array.size();
|
||||
return get_impl().isNull();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename JsonVariantAs<T>::type as() const {
|
||||
return _array.get<T>(_index);
|
||||
FORCE_INLINE typename VariantAs<T>::type as() const {
|
||||
return get_impl().as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is() const {
|
||||
return _array.is<T>(_index);
|
||||
return get_impl().is<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename JsonVariantTo<T>::type to() const {
|
||||
return _array.get<JsonVariant>(_index).to<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, JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
// 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*
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue* value) const {
|
||||
return get_impl().set(value);
|
||||
@ -89,22 +89,21 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript>,
|
||||
}
|
||||
|
||||
private:
|
||||
JsonVariant get_impl() const {
|
||||
return _array.get<JsonVariant>(_index);
|
||||
FORCE_INLINE VariantRef get_impl() const {
|
||||
return _array.get(_index);
|
||||
}
|
||||
|
||||
JsonArray _array;
|
||||
ArrayRef _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) const {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
inline ArraySubscript VariantSubscripts<TImpl>::operator[](size_t index) const {
|
||||
return impl()->template as<ArrayRef>()[index];
|
||||
}
|
||||
|
||||
inline JsonArraySubscript JsonArray::operator[](size_t index) const {
|
||||
return JsonArraySubscript(*this, index);
|
||||
inline ArraySubscript ArrayRef::operator[](size_t index) const {
|
||||
return ArraySubscript(*this, index);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
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
|
@ -130,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
|
||||
|
@ -1,99 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantData.hpp"
|
||||
#include "Slot.hpp"
|
||||
#include "SlotFunctions.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline JsonVariantData* arrayAdd(JsonArrayData* arr, MemoryPool* pool) {
|
||||
if (!arr) return 0;
|
||||
|
||||
Slot* slot = new (pool) Slot();
|
||||
if (!slot) return 0;
|
||||
|
||||
slot->next = 0;
|
||||
|
||||
if (arr->tail) {
|
||||
slot->prev = arr->tail;
|
||||
arr->tail->next = slot;
|
||||
arr->tail = slot;
|
||||
} else {
|
||||
slot->prev = 0;
|
||||
arr->head = slot;
|
||||
arr->tail = slot;
|
||||
}
|
||||
|
||||
return &slot->value;
|
||||
}
|
||||
|
||||
inline Slot* arrayGetSlot(const JsonArrayData* arr, size_t index) {
|
||||
if (!arr) return 0;
|
||||
return slotAdvance(arr->head, index);
|
||||
}
|
||||
|
||||
inline JsonVariantData* arrayGet(const JsonArrayData* arr, size_t index) {
|
||||
Slot* slot = arrayGetSlot(arr, index);
|
||||
return slot ? &slot->value : 0;
|
||||
}
|
||||
|
||||
inline void arrayRemove(JsonArrayData* arr, Slot* slot) {
|
||||
if (!arr || !slot) return;
|
||||
|
||||
if (slot->prev)
|
||||
slot->prev->next = slot->next;
|
||||
else
|
||||
arr->head = slot->next;
|
||||
if (slot->next)
|
||||
slot->next->prev = slot->prev;
|
||||
else
|
||||
arr->tail = slot->prev;
|
||||
}
|
||||
|
||||
inline void arrayRemove(JsonArrayData* arr, size_t index) {
|
||||
arrayRemove(arr, arrayGetSlot(arr, index));
|
||||
}
|
||||
|
||||
inline void arrayClear(JsonArrayData* arr) {
|
||||
if (!arr) return;
|
||||
arr->head = 0;
|
||||
arr->tail = 0;
|
||||
}
|
||||
|
||||
bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
|
||||
|
||||
inline bool arrayCopy(JsonArrayData* dst, const JsonArrayData* src,
|
||||
MemoryPool* pool) {
|
||||
if (!dst || !src) return false;
|
||||
arrayClear(dst);
|
||||
for (Slot* s = src->head; s; s = s->next) {
|
||||
if (!variantCopy(arrayAdd(dst, pool), &s->value, pool)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool variantEquals(const JsonVariantData*, const JsonVariantData*);
|
||||
|
||||
inline bool arrayEquals(const JsonArrayData* a1, const JsonArrayData* a2) {
|
||||
if (a1 == a2) return true;
|
||||
if (!a1 || !a2) return false;
|
||||
Slot* s1 = a1->head;
|
||||
Slot* s2 = a2->head;
|
||||
for (;;) {
|
||||
if (s1 == s2) return true;
|
||||
if (!s1 || !s2) return false;
|
||||
if (!variantEquals(&s1->value, &s2->value)) return false;
|
||||
s1 = s1->next;
|
||||
s2 = s2->next;
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t arraySize(const JsonArrayData* arr) {
|
||||
if (!arr) return 0;
|
||||
return slotSize(arr->head);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,49 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonArray;
|
||||
class JsonArrayConst;
|
||||
class JsonObject;
|
||||
class JsonObjectConst;
|
||||
class JsonVariant;
|
||||
class JsonVariantConst;
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// JsonVariant::as<T>()
|
||||
template <typename T>
|
||||
struct JsonVariantAs {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantAs<char*> {
|
||||
typedef const char* type;
|
||||
};
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// JsonVariant::as<T>()
|
||||
template <typename T>
|
||||
struct JsonVariantConstAs {
|
||||
typedef typename JsonVariantAs<T>::type type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantConstAs<JsonVariant> {
|
||||
typedef JsonVariantConst type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantConstAs<JsonObject> {
|
||||
typedef JsonObjectConst type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantConstAs<JsonArray> {
|
||||
typedef JsonArrayConst type;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,79 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // ptrdiff_t, size_t
|
||||
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
enum JsonVariantType {
|
||||
JSON_NULL,
|
||||
JSON_LINKED_RAW,
|
||||
JSON_OWNED_RAW,
|
||||
JSON_LINKED_STRING,
|
||||
JSON_OWNED_STRING,
|
||||
JSON_BOOLEAN,
|
||||
JSON_POSITIVE_INTEGER,
|
||||
JSON_NEGATIVE_INTEGER,
|
||||
JSON_ARRAY,
|
||||
JSON_OBJECT,
|
||||
JSON_FLOAT
|
||||
};
|
||||
|
||||
struct JsonObjectData {
|
||||
struct Slot *head;
|
||||
struct Slot *tail;
|
||||
};
|
||||
|
||||
struct JsonArrayData {
|
||||
struct Slot *head;
|
||||
struct Slot *tail;
|
||||
};
|
||||
|
||||
struct RawData {
|
||||
const char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// A union that defines the actual content of a JsonVariantData.
|
||||
// The enum JsonVariantType determines which member is in use.
|
||||
union JsonVariantContent {
|
||||
JsonFloat asFloat;
|
||||
JsonUInt asInteger;
|
||||
JsonArrayData asArray;
|
||||
JsonObjectData asObject;
|
||||
const char *asString;
|
||||
struct {
|
||||
const char *data;
|
||||
size_t size;
|
||||
} asRaw;
|
||||
};
|
||||
|
||||
// this struct must be a POD type to prevent error calling offsetof on clang
|
||||
struct JsonVariantData {
|
||||
bool keyIsStatic : 1;
|
||||
JsonVariantType type : 7;
|
||||
JsonVariantContent content;
|
||||
};
|
||||
|
||||
inline JsonVariantData *getVariantData(JsonArrayData *arr) {
|
||||
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
|
||||
offsetof(JsonVariantContent, asArray);
|
||||
if (!arr) return 0;
|
||||
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(arr) -
|
||||
offset);
|
||||
}
|
||||
|
||||
inline JsonVariantData *getVariantData(JsonObjectData *obj) {
|
||||
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
|
||||
offsetof(JsonVariantContent, asObject);
|
||||
if (!obj) return 0;
|
||||
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(obj) -
|
||||
offset);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,123 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantData.hpp"
|
||||
#include "SlotFunctions.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TKey>
|
||||
inline Slot* objectFindSlot(const JsonObjectData* obj, TKey key) {
|
||||
if (!obj) return 0;
|
||||
Slot* slot = obj->head;
|
||||
while (slot) {
|
||||
if (key.equals(slot->key)) break;
|
||||
slot = slot->next;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline bool objectContainsKey(const JsonObjectData* obj, const TKey& key) {
|
||||
return objectFindSlot(obj, key) != 0;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline JsonVariantData* objectAdd(JsonObjectData* obj, TKey key,
|
||||
MemoryPool* pool) {
|
||||
Slot* slot = new (pool) Slot();
|
||||
if (!slot) return 0;
|
||||
|
||||
slot->next = 0;
|
||||
|
||||
if (obj->tail) {
|
||||
slot->prev = obj->tail;
|
||||
obj->tail->next = slot;
|
||||
obj->tail = slot;
|
||||
} else {
|
||||
slot->prev = 0;
|
||||
obj->head = slot;
|
||||
obj->tail = slot;
|
||||
}
|
||||
|
||||
if (!slotSetKey(slot, key, pool)) return 0;
|
||||
return &slot->value;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline JsonVariantData* objectSet(JsonObjectData* obj, TKey key,
|
||||
MemoryPool* pool) {
|
||||
if (!obj) return 0;
|
||||
|
||||
// ignore null key
|
||||
if (key.isNull()) return 0;
|
||||
|
||||
// search a matching key
|
||||
Slot* slot = objectFindSlot(obj, key);
|
||||
if (slot) return &slot->value;
|
||||
|
||||
return objectAdd(obj, key, pool);
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline JsonVariantData* objectGet(const JsonObjectData* obj, TKey key) {
|
||||
Slot* slot = objectFindSlot(obj, key);
|
||||
return slot ? &slot->value : 0;
|
||||
}
|
||||
|
||||
inline void objectClear(JsonObjectData* obj) {
|
||||
if (!obj) return;
|
||||
obj->head = 0;
|
||||
obj->tail = 0;
|
||||
}
|
||||
|
||||
inline void objectRemove(JsonObjectData* obj, Slot* slot) {
|
||||
if (!obj) return;
|
||||
if (!slot) return;
|
||||
if (slot->prev)
|
||||
slot->prev->next = slot->next;
|
||||
else
|
||||
obj->head = slot->next;
|
||||
if (slot->next)
|
||||
slot->next->prev = slot->prev;
|
||||
else
|
||||
obj->tail = slot->prev;
|
||||
}
|
||||
|
||||
inline size_t objectSize(const JsonObjectData* obj) {
|
||||
if (!obj) return 0;
|
||||
return slotSize(obj->head);
|
||||
}
|
||||
|
||||
// bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
|
||||
|
||||
inline bool objectCopy(JsonObjectData* dst, const JsonObjectData* src,
|
||||
MemoryPool* pool) {
|
||||
if (!dst || !src) return false;
|
||||
objectClear(dst);
|
||||
for (Slot* s = src->head; s; s = s->next) {
|
||||
JsonVariantData* var;
|
||||
if (s->value.keyIsStatic)
|
||||
var = objectAdd(dst, ZeroTerminatedRamStringConst(s->key), pool);
|
||||
else
|
||||
var = objectAdd(dst, ZeroTerminatedRamString(s->key), pool);
|
||||
if (!variantCopy(var, &s->value, pool)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool objectEquals(const JsonObjectData* o1, const JsonObjectData* o2) {
|
||||
if (o1 == o2) return true;
|
||||
if (!o1 || !o2) return false;
|
||||
|
||||
for (Slot* s = o1->head; s; s = s->next) {
|
||||
JsonVariantData* v1 = &s->value;
|
||||
JsonVariantData* v2 = objectGet(o2, makeString(s->key));
|
||||
if (!variantEquals(v1, v2)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,19 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Memory/AllocableInMemoryPool.hpp"
|
||||
#include "JsonVariantData.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct Slot : AllocableInMemoryPool {
|
||||
JsonVariantData value;
|
||||
struct Slot* next;
|
||||
struct Slot* prev;
|
||||
const char* key;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,59 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Strings/StringTypes.hpp"
|
||||
#include "JsonVariantData.hpp"
|
||||
#include "Slot.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TKey>
|
||||
inline bool slotSetKey(Slot* slot, TKey key, MemoryPool* pool) {
|
||||
const char* dup = key.save(pool);
|
||||
if (!dup) return false;
|
||||
slot->key = dup;
|
||||
slot->value.keyIsStatic = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool slotSetKey(Slot* slot, ZeroTerminatedRamStringConst key,
|
||||
MemoryPool* pool) {
|
||||
slot->key = key.save(pool);
|
||||
slot->value.keyIsStatic = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool slotSetKey(Slot* slot, StringInMemoryPool key, MemoryPool* pool) {
|
||||
slot->key = key.save(pool);
|
||||
slot->value.keyIsStatic = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const Slot* slotAdvance(const Slot* slot, size_t distance) {
|
||||
while (distance && slot) {
|
||||
slot = slot->next;
|
||||
distance--;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
inline Slot* slotAdvance(Slot* slot, size_t distance) {
|
||||
while (distance && slot) {
|
||||
slot = slot->next;
|
||||
distance--;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
inline size_t slotSize(const Slot* slot) {
|
||||
size_t n = 0;
|
||||
while (slot) {
|
||||
n++;
|
||||
slot = slot->next;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,48 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Serialization/DynamicStringWriter.hpp"
|
||||
#include "VariantFunctions.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonVariantConst;
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_integral<T>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data) {
|
||||
return variantAsIntegral<T>(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, bool>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data) {
|
||||
return variantAsBoolean(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_floating_point<T>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data) {
|
||||
return variantAsFloat<T>(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, const char*>::value ||
|
||||
is_same<T, char*>::value,
|
||||
const char*>::type
|
||||
variantAs(const JsonVariantData* _data) {
|
||||
return variantAsString(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<JsonVariantConst, T>::value, T>::type
|
||||
variantAs(const JsonVariantData* _data);
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data);
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,287 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Numbers/parseFloat.hpp"
|
||||
#include "../Numbers/parseInteger.hpp"
|
||||
#include "../SerializedValue.hpp"
|
||||
#include "ArrayFunctions.hpp"
|
||||
#include "JsonVariantData.hpp"
|
||||
#include "ObjectFunctions.hpp"
|
||||
#include "Slot.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T>
|
||||
inline T variantAsIntegral(const JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
switch (var->type) {
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return T(var->content.asInteger);
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return T(~var->content.asInteger + 1);
|
||||
case JSON_LINKED_STRING:
|
||||
case JSON_OWNED_STRING:
|
||||
return parseInteger<T>(var->content.asString);
|
||||
case JSON_FLOAT:
|
||||
return T(var->content.asFloat);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool variantAsBoolean(const JsonVariantData* var) {
|
||||
return variantAsIntegral<int>(var) != 0;
|
||||
}
|
||||
|
||||
// T = float/double
|
||||
template <typename T>
|
||||
inline T variantAsFloat(const JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
switch (var->type) {
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return static_cast<T>(var->content.asInteger);
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return -static_cast<T>(var->content.asInteger);
|
||||
case JSON_LINKED_STRING:
|
||||
case JSON_OWNED_STRING:
|
||||
return parseFloat<T>(var->content.asString);
|
||||
case JSON_FLOAT:
|
||||
return static_cast<T>(var->content.asFloat);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline const char* variantAsString(const JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
if (var &&
|
||||
(var->type == JSON_LINKED_STRING || var->type == JSON_OWNED_STRING))
|
||||
return var->content.asString;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline JsonArrayData* variantAsArray(JsonVariantData* var) {
|
||||
if (var && var->type == JSON_ARRAY)
|
||||
return &var->content.asArray;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline const JsonArrayData* variantAsArray(const JsonVariantData* var) {
|
||||
if (var && var->type == JSON_ARRAY)
|
||||
return &var->content.asArray;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline JsonObjectData* variantAsObject(JsonVariantData* var) {
|
||||
if (var && var->type == JSON_OBJECT)
|
||||
return &var->content.asObject;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline const JsonObjectData* variantAsObject(const JsonVariantData* var) {
|
||||
if (var && var->type == JSON_OBJECT)
|
||||
return &var->content.asObject;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool variantSetBoolean(JsonVariantData* var, bool value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_BOOLEAN;
|
||||
var->content.asInteger = static_cast<JsonUInt>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool variantSetFloat(JsonVariantData* var, JsonFloat value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_FLOAT;
|
||||
var->content.asFloat = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool variantSetSignedInteger(JsonVariantData* var, T value) {
|
||||
if (!var) return false;
|
||||
if (value >= 0) {
|
||||
var->type = JSON_POSITIVE_INTEGER;
|
||||
var->content.asInteger = static_cast<JsonUInt>(value);
|
||||
} else {
|
||||
var->type = JSON_NEGATIVE_INTEGER;
|
||||
var->content.asInteger = ~static_cast<JsonUInt>(value) + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool variantSetSignedInteger(JsonVariantData* var, JsonUInt value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_POSITIVE_INTEGER;
|
||||
var->content.asInteger = static_cast<JsonUInt>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool variantSetLinkedRaw(JsonVariantData* var,
|
||||
SerializedValue<const char*> value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_LINKED_RAW;
|
||||
var->content.asRaw.data = value.data();
|
||||
var->content.asRaw.size = value.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value,
|
||||
MemoryPool* pool) {
|
||||
if (!var) return false;
|
||||
const char* dup = makeString(value.data(), value.size()).save(pool);
|
||||
if (dup) {
|
||||
var->type = JSON_OWNED_RAW;
|
||||
var->content.asRaw.data = dup;
|
||||
var->content.asRaw.size = value.size();
|
||||
return true;
|
||||
} else {
|
||||
var->type = JSON_NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) {
|
||||
if (!var) return false;
|
||||
const char* dup = value.save(pool);
|
||||
if (dup) {
|
||||
var->type = JSON_OWNED_STRING;
|
||||
var->content.asString = dup;
|
||||
return true;
|
||||
} else {
|
||||
var->type = JSON_NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool variantSetString(JsonVariantData* var, const char* value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_LINKED_STRING;
|
||||
var->content.asString = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool variantSetString(JsonVariantData* var, const char* value,
|
||||
MemoryPool* pool) {
|
||||
return variantSetString(var, makeString(const_cast<char*>(value)), pool);
|
||||
}
|
||||
|
||||
inline void variantSetNull(JsonVariantData* var) {
|
||||
if (var) var->type = JSON_NULL;
|
||||
}
|
||||
|
||||
inline JsonArrayData* variantToArray(JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
var->type = JSON_ARRAY;
|
||||
var->content.asArray.head = 0;
|
||||
var->content.asArray.tail = 0;
|
||||
return &var->content.asArray;
|
||||
}
|
||||
|
||||
inline JsonObjectData* variantToObject(JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
var->type = JSON_OBJECT;
|
||||
var->content.asObject.head = 0;
|
||||
var->content.asObject.tail = 0;
|
||||
return &var->content.asObject;
|
||||
}
|
||||
|
||||
inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src,
|
||||
MemoryPool* pool) {
|
||||
if (!dst) return false;
|
||||
if (!src) {
|
||||
dst->type = JSON_NULL;
|
||||
return true;
|
||||
}
|
||||
switch (src->type) {
|
||||
case JSON_ARRAY:
|
||||
return arrayCopy(variantToArray(dst), &src->content.asArray, pool);
|
||||
case JSON_OBJECT:
|
||||
return objectCopy(variantToObject(dst), &src->content.asObject, pool);
|
||||
case JSON_OWNED_STRING:
|
||||
return variantSetString(dst, src->content.asString, pool);
|
||||
case JSON_OWNED_RAW:
|
||||
return variantSetOwnedRaw(
|
||||
dst,
|
||||
serialized(const_cast<char*>(src->content.asRaw.data),
|
||||
src->content.asRaw.size),
|
||||
pool);
|
||||
default:
|
||||
*dst = *src;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool variantIsInteger(const JsonVariantData* var) {
|
||||
return var && (var->type == JSON_POSITIVE_INTEGER ||
|
||||
var->type == JSON_NEGATIVE_INTEGER);
|
||||
}
|
||||
|
||||
inline bool variantIsFloat(const JsonVariantData* var) {
|
||||
return var &&
|
||||
(var->type == JSON_FLOAT || var->type == JSON_POSITIVE_INTEGER ||
|
||||
var->type == JSON_NEGATIVE_INTEGER);
|
||||
}
|
||||
|
||||
inline bool variantIsString(const JsonVariantData* var) {
|
||||
return var &&
|
||||
(var->type == JSON_LINKED_STRING || var->type == JSON_OWNED_STRING);
|
||||
}
|
||||
|
||||
inline bool variantIsArray(const JsonVariantData* var) {
|
||||
return var && var->type == JSON_ARRAY;
|
||||
}
|
||||
|
||||
inline bool variantIsObject(const JsonVariantData* var) {
|
||||
return var && var->type == JSON_OBJECT;
|
||||
}
|
||||
|
||||
inline bool variantIsNull(const JsonVariantData* var) {
|
||||
return var == 0 || var->type == JSON_NULL;
|
||||
}
|
||||
|
||||
inline bool variantEquals(const JsonVariantData* a, const JsonVariantData* b) {
|
||||
if (a == b) return true;
|
||||
if (!a || !b) return false;
|
||||
if (a->type != b->type) return false;
|
||||
|
||||
switch (a->type) {
|
||||
case JSON_LINKED_RAW:
|
||||
case JSON_OWNED_RAW:
|
||||
case JSON_LINKED_STRING:
|
||||
case JSON_OWNED_STRING:
|
||||
return !strcmp(a->content.asString, b->content.asString);
|
||||
|
||||
case JSON_BOOLEAN:
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return a->content.asInteger == b->content.asInteger;
|
||||
|
||||
case JSON_ARRAY:
|
||||
return arrayEquals(&a->content.asArray, &b->content.asArray);
|
||||
|
||||
case JSON_OBJECT:
|
||||
return objectEquals(&a->content.asObject, &b->content.asObject);
|
||||
|
||||
case JSON_FLOAT:
|
||||
return a->content.asFloat == b->content.asFloat;
|
||||
|
||||
case JSON_NULL:
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -6,33 +6,30 @@
|
||||
|
||||
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++);
|
||||
@ -44,18 +41,18 @@ 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
|
||||
|
||||
|
@ -11,6 +11,10 @@
|
||||
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 {
|
||||
|
@ -14,63 +14,58 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <template <typename, typename> class TDeserializer,
|
||||
typename TMemoryPool, typename TReader, typename TWriter>
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(TMemoryPool &memoryPool,
|
||||
template <template <typename, typename> class TDeserializer, typename TReader,
|
||||
typename TWriter>
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
|
||||
TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit) {
|
||||
return TDeserializer<TReader, TWriter>(memoryPool, reader, writer,
|
||||
nestingLimit);
|
||||
return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit);
|
||||
}
|
||||
|
||||
// DeserializationError deserialize(TDocument& doc, TString input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// DeserializationError deserialize(JsonDocument& doc, TString input);
|
||||
// TString = const std::string&, const String&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TString>
|
||||
template <template <typename, typename> class TDeserializer, typename TString>
|
||||
typename enable_if<!is_array<TString>::value, DeserializationError>::type
|
||||
deserialize(TDocument &doc, const TString &input) {
|
||||
deserialize(JsonDocument &doc, const TString &input) {
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), makeReader(input),
|
||||
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
.parse(doc.data());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TChar>
|
||||
DeserializationError deserialize(TDocument &doc, TChar *input) {
|
||||
// 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.template to<JsonVariant>());
|
||||
.parse(doc.data());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input, size_t
|
||||
// DeserializationError deserialize(JsonDocument& 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,
|
||||
// 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.template to<JsonVariant>());
|
||||
.parse(doc.data());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TStream input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// DeserializationError deserialize(JsonDocument& doc, TStream input);
|
||||
// TStream = std::istream&, Stream&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TStream>
|
||||
DeserializationError deserialize(TDocument &doc, TStream &input) {
|
||||
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.template to<JsonVariant>());
|
||||
.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
|
@ -5,12 +5,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Deserialization/deserialize.hpp"
|
||||
#include "../JsonVariant.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 {
|
||||
|
||||
@ -18,25 +18,26 @@ template <typename TReader, typename TStringStorage>
|
||||
class JsonDeserializer {
|
||||
typedef typename remove_reference<TStringStorage>::type::StringBuilder
|
||||
StringBuilder;
|
||||
typedef const char *StringType;
|
||||
|
||||
public:
|
||||
JsonDeserializer(MemoryPool &memoryPool, TReader reader,
|
||||
JsonDeserializer(MemoryPool &pool, TReader reader,
|
||||
TStringStorage stringStorage, uint8_t nestingLimit)
|
||||
: _memoryPool(&memoryPool),
|
||||
: _pool(&pool),
|
||||
_reader(reader),
|
||||
_stringStorage(stringStorage),
|
||||
_nestingLimit(nestingLimit),
|
||||
_loaded(false) {}
|
||||
DeserializationError parse(JsonVariant variant) {
|
||||
DeserializationError 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);
|
||||
@ -67,12 +68,9 @@ class JsonDeserializer {
|
||||
return true;
|
||||
}
|
||||
|
||||
DeserializationError parseArray(JsonVariant variant) {
|
||||
DeserializationError parseArray(CollectionData &array) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
|
||||
JsonArray array = variant.to<JsonArray>();
|
||||
if (array.isNull()) return DeserializationError::NoMemory;
|
||||
|
||||
// Check opening braket
|
||||
if (!eat('[')) return DeserializationError::InvalidInput;
|
||||
|
||||
@ -86,12 +84,12 @@ class JsonDeserializer {
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// Allocate slot in array
|
||||
JsonVariant value = array.add();
|
||||
if (value.isInvalid()) return DeserializationError::NoMemory;
|
||||
VariantData *value = array.add(_pool);
|
||||
if (!value) return DeserializationError::NoMemory;
|
||||
|
||||
// 1 - Parse value
|
||||
_nestingLimit--;
|
||||
err = parse(value);
|
||||
err = parse(*value);
|
||||
_nestingLimit++;
|
||||
if (err) return err;
|
||||
|
||||
@ -105,12 +103,9 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseObject(JsonVariant variant) {
|
||||
DeserializationError parseObject(CollectionData &object) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
|
||||
JsonObject object = variant.to<JsonObject>();
|
||||
if (object.isNull()) return DeserializationError::NoMemory;
|
||||
|
||||
// Check opening brace
|
||||
if (!eat('{')) return DeserializationError::InvalidInput;
|
||||
|
||||
@ -123,23 +118,24 @@ class JsonDeserializer {
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// Allocate slot in object
|
||||
VariantSlot *slot = object.addSlot(_pool);
|
||||
if (!slot) return DeserializationError::NoMemory;
|
||||
|
||||
// Parse key
|
||||
StringInMemoryPool key;
|
||||
StringType key;
|
||||
err = parseKey(key);
|
||||
if (err) return err;
|
||||
slot->setOwnedKey(key);
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
if (err) return err; // Colon
|
||||
if (!eat(':')) return DeserializationError::InvalidInput;
|
||||
|
||||
// Allocate slot in object
|
||||
JsonVariant value = object.set(key);
|
||||
if (value.isInvalid()) return DeserializationError::NoMemory;
|
||||
|
||||
// Parse value
|
||||
_nestingLimit--;
|
||||
err = parse(value);
|
||||
err = parse(*slot->data());
|
||||
_nestingLimit++;
|
||||
if (err) return err;
|
||||
|
||||
@ -157,7 +153,7 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseValue(JsonVariant variant) {
|
||||
DeserializationError parseValue(VariantData &variant) {
|
||||
if (isQuote(current())) {
|
||||
return parseStringValue(variant);
|
||||
} else {
|
||||
@ -165,7 +161,7 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseKey(StringInMemoryPool &key) {
|
||||
DeserializationError parseKey(StringType &key) {
|
||||
if (isQuote(current())) {
|
||||
return parseQuotedString(key);
|
||||
} else {
|
||||
@ -173,16 +169,16 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseStringValue(JsonVariant variant) {
|
||||
StringInMemoryPool value;
|
||||
DeserializationError parseStringValue(VariantData &variant) {
|
||||
StringType value;
|
||||
DeserializationError err = parseQuotedString(value);
|
||||
if (err) return err;
|
||||
variant.set(value);
|
||||
variant.setOwnedString(value);
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError parseQuotedString(StringInMemoryPool &result) {
|
||||
StringBuilder str = _stringStorage.startString();
|
||||
DeserializationError parseQuotedString(StringType &result) {
|
||||
StringBuilder builder = _stringStorage.startString();
|
||||
const char stopChar = current();
|
||||
|
||||
move();
|
||||
@ -203,16 +199,16 @@ class JsonDeserializer {
|
||||
move();
|
||||
}
|
||||
|
||||
str.append(c);
|
||||
builder.append(c);
|
||||
}
|
||||
|
||||
result = str.complete();
|
||||
if (result.isNull()) return DeserializationError::NoMemory;
|
||||
result = builder.complete();
|
||||
if (!result) return DeserializationError::NoMemory;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError parseNonQuotedString(StringInMemoryPool &result) {
|
||||
StringBuilder str = _stringStorage.startString();
|
||||
DeserializationError parseNonQuotedString(StringType &result) {
|
||||
StringBuilder builder = _stringStorage.startString();
|
||||
|
||||
char c = current();
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
@ -220,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.complete();
|
||||
if (result.isNull()) 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;
|
||||
|
||||
@ -245,13 +241,13 @@ class JsonDeserializer {
|
||||
buffer[n] = 0;
|
||||
|
||||
if (isInteger(buffer)) {
|
||||
result.set(parseInteger<JsonInteger>(buffer));
|
||||
result.setInteger(parseInteger<Integer>(buffer));
|
||||
} else if (isFloat(buffer)) {
|
||||
result.set(parseFloat<JsonFloat>(buffer));
|
||||
result.setFloat(parseFloat<Float>(buffer));
|
||||
} else if (!strcmp(buffer, "true")) {
|
||||
result.set(true);
|
||||
result.setBoolean(true);
|
||||
} else if (!strcmp(buffer, "false")) {
|
||||
result.set(false);
|
||||
result.setBoolean(false);
|
||||
} else if (!strcmp(buffer, "null")) {
|
||||
// already null
|
||||
} else {
|
||||
@ -332,7 +328,7 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
MemoryPool *_memoryPool;
|
||||
MemoryPool *_pool;
|
||||
TReader _reader;
|
||||
TStringStorage _stringStorage;
|
||||
uint8_t _nestingLimit;
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Misc/Visitable.hpp"
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "../Visitable.hpp"
|
||||
#include "JsonWriter.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
@ -16,19 +16,20 @@ class JsonSerializer {
|
||||
public:
|
||||
JsonSerializer(TWriter &writer) : _writer(writer) {}
|
||||
|
||||
void visitFloat(JsonFloat value) {
|
||||
void visitFloat(Float value) {
|
||||
_writer.writeFloat(value);
|
||||
}
|
||||
|
||||
void visitArray(JsonArrayConst array) {
|
||||
void visitArray(const CollectionData &array) {
|
||||
_writer.beginArray();
|
||||
|
||||
JsonArrayConst::iterator it = array.begin();
|
||||
while (it != array.end()) {
|
||||
it->accept(*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 visitObject(JsonObjectConst object) {
|
||||
void visitObject(const CollectionData &object) {
|
||||
_writer.beginObject();
|
||||
|
||||
JsonObjectConst::iterator it = object.begin();
|
||||
while (it != object.end()) {
|
||||
_writer.writeString(it->key());
|
||||
_writer.writeColon();
|
||||
it->value().accept(*this);
|
||||
VariantSlot *slot = object.head();
|
||||
|
||||
++it;
|
||||
if (it == object.end()) break;
|
||||
while (slot != 0) {
|
||||
_writer.writeString(slot->key());
|
||||
_writer.writeColon();
|
||||
slot->data()->accept(*this);
|
||||
|
||||
slot = slot->next();
|
||||
if (slot == 0) break;
|
||||
|
||||
_writer.writeComma();
|
||||
}
|
||||
@ -63,12 +65,12 @@ class JsonSerializer {
|
||||
for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]);
|
||||
}
|
||||
|
||||
void visitNegativeInteger(JsonUInt value) {
|
||||
void visitNegativeInteger(UInt value) {
|
||||
_writer.writeRaw('-');
|
||||
_writer.writeInteger(value);
|
||||
}
|
||||
|
||||
void visitPositiveInteger(JsonUInt value) {
|
||||
void visitPositiveInteger(UInt value) {
|
||||
_writer.writeInteger(value);
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
|
||||
#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 {
|
||||
|
||||
@ -71,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) {
|
||||
@ -82,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);
|
||||
@ -98,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;
|
||||
@ -107,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
|
||||
|
@ -1,251 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/ArrayFunctions.hpp"
|
||||
#include "Data/JsonVariantData.hpp"
|
||||
#include "JsonArrayIterator.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
// Can be very handy to determine the size of a StaticMemoryPool.
|
||||
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::Slot))
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonObject;
|
||||
class JsonArraySubscript;
|
||||
|
||||
template <typename TData>
|
||||
class JsonArrayProxy {
|
||||
public:
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
||||
return JsonVariantConst(arrayGet(_data, index));
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return arraySize(_data);
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonArrayProxy(TData* data) : _data(data) {}
|
||||
TData* _data;
|
||||
};
|
||||
|
||||
class JsonArrayConst : public JsonArrayProxy<const JsonArrayData>,
|
||||
public Visitable {
|
||||
friend class JsonArray;
|
||||
typedef JsonArrayProxy<const JsonArrayData> proxy_type;
|
||||
|
||||
public:
|
||||
typedef JsonArrayConstIterator iterator;
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
if (_data)
|
||||
visitor.visitArray(*this);
|
||||
else
|
||||
visitor.visitNull();
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_data->head);
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonArrayConst() : proxy_type(0) {}
|
||||
FORCE_INLINE JsonArrayConst(const JsonArrayData* data) : proxy_type(data) {}
|
||||
|
||||
FORCE_INLINE bool operator==(JsonArrayConst rhs) const {
|
||||
return arrayEquals(_data, rhs._data);
|
||||
}
|
||||
};
|
||||
|
||||
class JsonArray : public JsonArrayProxy<JsonArrayData>, public Visitable {
|
||||
typedef JsonArrayProxy<JsonArrayData> proxy_type;
|
||||
|
||||
public:
|
||||
typedef JsonArrayIterator iterator;
|
||||
|
||||
FORCE_INLINE JsonArray() : proxy_type(0), _memoryPool(0) {}
|
||||
FORCE_INLINE JsonArray(MemoryPool* pool, JsonArrayData* data)
|
||||
: proxy_type(data), _memoryPool(pool) {}
|
||||
|
||||
operator JsonVariant() {
|
||||
return JsonVariant(_memoryPool, getVariantData(_data));
|
||||
}
|
||||
|
||||
operator JsonArrayConst() const {
|
||||
return JsonArrayConst(_data);
|
||||
}
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
|
||||
// std::string, String, JsonObject
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(const T& value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
// Adds the specified value at the end of the array.
|
||||
FORCE_INLINE bool add(JsonArray value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(T* value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
|
||||
JsonVariant add() const {
|
||||
return JsonVariant(_memoryPool, arrayAdd(_data, _memoryPool));
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_memoryPool, _data->head);
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T, size_t N>
|
||||
FORCE_INLINE bool copyFrom(T (&array)[N]) const {
|
||||
return copyFrom(array, N);
|
||||
}
|
||||
|
||||
// Imports a 1D array
|
||||
template <typename T>
|
||||
bool copyFrom(T* array, size_t len) const {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ok &= add(array[i]);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Imports a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
bool copyFrom(T (&array)[N1][N2]) const {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < N1; i++) {
|
||||
JsonArray nestedArray = createNestedArray();
|
||||
for (size_t j = 0; j < N2; j++) {
|
||||
ok &= nestedArray.add(array[i][j]);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Copy a JsonArray
|
||||
FORCE_INLINE bool copyFrom(JsonArray src) const {
|
||||
return arrayCopy(_data, src._data, _memoryPool);
|
||||
}
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T, size_t N>
|
||||
FORCE_INLINE size_t copyTo(T (&array)[N]) const {
|
||||
return copyTo(array, N);
|
||||
}
|
||||
|
||||
// Exports a 1D array
|
||||
template <typename T>
|
||||
size_t copyTo(T* array, size_t len) const {
|
||||
size_t i = 0;
|
||||
for (iterator it = begin(); it != end() && i < len; ++it) array[i++] = *it;
|
||||
return i;
|
||||
}
|
||||
|
||||
// Exports a 2D array
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
void copyTo(T (&array)[N1][N2]) const {
|
||||
if (!_data) return;
|
||||
size_t i = 0;
|
||||
for (iterator it = begin(); it != end() && i < N1; ++it) {
|
||||
it->as<JsonArray>().copyTo(array[i++]);
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonArray createNestedArray() const;
|
||||
FORCE_INLINE JsonObject createNestedObject() const;
|
||||
|
||||
FORCE_INLINE JsonArraySubscript operator[](size_t index) const;
|
||||
|
||||
FORCE_INLINE bool operator==(JsonArray rhs) const {
|
||||
return arrayEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
// Gets the value at the specified index.
|
||||
template <typename T>
|
||||
FORCE_INLINE typename JsonVariantAs<T>::type get(size_t index) const {
|
||||
return get_impl(index).as<T>();
|
||||
}
|
||||
|
||||
// Check the type of the value at specified index.
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is(size_t index) const {
|
||||
return get_impl(index).is<T>();
|
||||
}
|
||||
|
||||
// Removes element at specified position.
|
||||
FORCE_INLINE void remove(iterator it) const {
|
||||
arrayRemove(_data, it.internal());
|
||||
}
|
||||
|
||||
// Removes element at specified index.
|
||||
FORCE_INLINE void remove(size_t index) const {
|
||||
arrayRemove(_data, 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, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
FORCE_INLINE bool set(size_t index, const T& value) const {
|
||||
if (!_data) return false;
|
||||
return get_impl(index).set(value);
|
||||
}
|
||||
//
|
||||
// bool add(size_t index, TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE bool set(size_t index, T* value) const {
|
||||
if (!_data) return false;
|
||||
return get_impl(index).set(value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
JsonArrayConst(_data).accept(visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TValueRef>
|
||||
FORCE_INLINE bool add_impl(TValueRef value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonVariant get_impl(size_t index) const {
|
||||
return JsonVariant(_memoryPool, arrayGet(_data, index));
|
||||
}
|
||||
|
||||
MemoryPool* _memoryPool;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,19 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline JsonArray JsonArray::createNestedArray() const {
|
||||
return add().to<JsonArray>();
|
||||
}
|
||||
|
||||
inline JsonObject JsonArray::createNestedObject() const {
|
||||
return add().to<JsonObject>();
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,123 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/Slot.hpp"
|
||||
#include "Data/SlotFunctions.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonVariantPtr {
|
||||
public:
|
||||
JsonVariantPtr(MemoryPool *memoryPool, JsonVariantData *data)
|
||||
: _variant(memoryPool, data) {}
|
||||
|
||||
JsonVariant *operator->() {
|
||||
return &_variant;
|
||||
}
|
||||
|
||||
JsonVariant &operator*() {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonVariant _variant;
|
||||
};
|
||||
|
||||
class JsonArrayIterator {
|
||||
public:
|
||||
JsonArrayIterator() : _slot(0) {}
|
||||
explicit JsonArrayIterator(MemoryPool *memoryPool, Slot *slot)
|
||||
: _memoryPool(memoryPool), _slot(slot) {}
|
||||
|
||||
JsonVariant operator*() const {
|
||||
return JsonVariant(_memoryPool, &_slot->value);
|
||||
}
|
||||
JsonVariantPtr operator->() {
|
||||
return JsonVariantPtr(_memoryPool, &_slot->value);
|
||||
}
|
||||
|
||||
bool operator==(const JsonArrayIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const JsonArrayIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
JsonArrayIterator &operator++() {
|
||||
_slot = _slot->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonArrayIterator &operator+=(size_t distance) {
|
||||
_slot = slotAdvance(_slot, distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Slot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool *_memoryPool;
|
||||
Slot *_slot;
|
||||
};
|
||||
|
||||
class JsonVariantConstPtr {
|
||||
public:
|
||||
JsonVariantConstPtr(const JsonVariantData *data) : _variant(data) {}
|
||||
|
||||
JsonVariantConst *operator->() {
|
||||
return &_variant;
|
||||
}
|
||||
|
||||
JsonVariantConst &operator*() {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonVariantConst _variant;
|
||||
};
|
||||
|
||||
class JsonArrayConstIterator {
|
||||
public:
|
||||
JsonArrayConstIterator() : _slot(0) {}
|
||||
explicit JsonArrayConstIterator(const Slot *slot) : _slot(slot) {}
|
||||
|
||||
JsonVariantConst operator*() const {
|
||||
return JsonVariantConst(&_slot->value);
|
||||
}
|
||||
JsonVariantConstPtr operator->() {
|
||||
return JsonVariantConstPtr(&_slot->value);
|
||||
}
|
||||
|
||||
bool operator==(const JsonArrayConstIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const JsonArrayConstIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
JsonArrayConstIterator &operator++() {
|
||||
_slot = _slot->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonArrayConstIterator &operator+=(size_t distance) {
|
||||
_slot = slotAdvance(_slot, distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Slot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
const Slot *_slot;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,131 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantTo.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Memory/DynamicMemoryPool.hpp"
|
||||
#include "Memory/StaticMemoryPool.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TMemoryPool>
|
||||
class JsonDocument : public Visitable {
|
||||
public:
|
||||
uint8_t nestingLimit;
|
||||
|
||||
JsonDocument() : nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor& visitor) const {
|
||||
return getVariant().accept(visitor);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename JsonVariantAs<T>::type as() {
|
||||
return getVariant().template as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename JsonVariantConstAs<T>::type as() const {
|
||||
return getVariant().template as<T>();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_memoryPool.clear();
|
||||
_rootData.type = JSON_NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return getVariant().template is<T>();
|
||||
}
|
||||
|
||||
size_t memoryUsage() const {
|
||||
return _memoryPool.size();
|
||||
}
|
||||
|
||||
TMemoryPool& memoryPool() {
|
||||
return _memoryPool;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename JsonVariantTo<T>::type to() {
|
||||
_memoryPool.clear();
|
||||
return getVariant().template to<T>();
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
void copy(const JsonDocument<T>& src) {
|
||||
nestingLimit = src.nestingLimit;
|
||||
to<JsonVariant>().set(src.template as<JsonVariant>());
|
||||
}
|
||||
|
||||
private:
|
||||
JsonVariant getVariant() {
|
||||
return JsonVariant(&_memoryPool, &_rootData);
|
||||
}
|
||||
|
||||
JsonVariantConst getVariant() const {
|
||||
return JsonVariantConst(&_rootData);
|
||||
}
|
||||
|
||||
TMemoryPool _memoryPool;
|
||||
JsonVariantData _rootData;
|
||||
};
|
||||
|
||||
class DynamicJsonDocument : public JsonDocument<DynamicMemoryPool> {
|
||||
public:
|
||||
DynamicJsonDocument() {}
|
||||
DynamicJsonDocument(size_t capacity) {
|
||||
memoryPool().reserve(capacity);
|
||||
}
|
||||
|
||||
DynamicJsonDocument(const DynamicJsonDocument& src) {
|
||||
memoryPool().reserve(src.memoryUsage());
|
||||
copy(src);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DynamicJsonDocument(const JsonDocument<T>& src) {
|
||||
memoryPool().reserve(src.memoryUsage());
|
||||
copy(src);
|
||||
}
|
||||
|
||||
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
|
||||
copy(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DynamicJsonDocument& operator=(const JsonDocument<T>& src) {
|
||||
copy(src);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t CAPACITY>
|
||||
class StaticJsonDocument : public JsonDocument<StaticMemoryPool<CAPACITY> > {
|
||||
public:
|
||||
StaticJsonDocument() {}
|
||||
|
||||
template <typename T>
|
||||
StaticJsonDocument(const JsonDocument<T>& src) {
|
||||
this->copy(src);
|
||||
}
|
||||
|
||||
StaticMemoryPoolBase& memoryPool() {
|
||||
return JsonDocument<StaticMemoryPool<CAPACITY> >::memoryPool();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
StaticJsonDocument operator=(const JsonDocument<T>& src) {
|
||||
this->copy(src);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,37 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonKey {
|
||||
public:
|
||||
JsonKey(const Slot* slot) : _slot(slot) {}
|
||||
|
||||
operator const char*() const {
|
||||
return c_str();
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
return _slot ? _slot->key : 0;
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return _slot == 0 || _slot->key == 0;
|
||||
}
|
||||
|
||||
bool isStatic() const {
|
||||
return _slot ? _slot->value.keyIsStatic : true;
|
||||
}
|
||||
|
||||
friend bool operator==(JsonKey lhs, const char* rhs) {
|
||||
if (lhs.isNull()) return rhs == 0;
|
||||
return rhs ? !strcmp(lhs, rhs) : false;
|
||||
}
|
||||
|
||||
private:
|
||||
const Slot* _slot;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,343 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/ObjectFunctions.hpp"
|
||||
#include "JsonObjectIterator.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
// Can be very handy to determine the size of a StaticMemoryPool.
|
||||
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::Slot))
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TData>
|
||||
class JsonObjectProxy {
|
||||
public:
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE bool containsKey(const TKey& key) const {
|
||||
return objectContainsKey(_data, makeString(key));
|
||||
}
|
||||
//
|
||||
// bool containsKey(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE bool containsKey(TKey* key) const {
|
||||
return objectContainsKey(_data, makeString(key));
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return objectSize(_data);
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonObjectProxy(TData* data) : _data(data) {}
|
||||
TData* _data;
|
||||
};
|
||||
|
||||
class JsonObjectConst : public JsonObjectProxy<const JsonObjectData>,
|
||||
public Visitable {
|
||||
friend class JsonObject;
|
||||
typedef JsonObjectProxy<const JsonObjectData> proxy_type;
|
||||
|
||||
public:
|
||||
typedef JsonObjectConstIterator iterator;
|
||||
|
||||
JsonObjectConst() : proxy_type(0) {}
|
||||
JsonObjectConst(const JsonObjectData* data) : proxy_type(data) {}
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
if (_data)
|
||||
visitor.visitObject(*this);
|
||||
else
|
||||
visitor.visitNull();
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_data->head);
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArrayConst, JsonObjectConst
|
||||
template <typename TValue, typename TKey>
|
||||
FORCE_INLINE typename JsonVariantAs<TValue>::type get(const TKey& key) const {
|
||||
return get_impl(makeString(key)).template as<TValue>();
|
||||
}
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArrayConst, JsonObjectConst
|
||||
template <typename TValue, typename TKey>
|
||||
FORCE_INLINE typename JsonVariantAs<TValue>::type get(TKey* key) const {
|
||||
return get_impl(makeString(key)).template as<TValue>();
|
||||
}
|
||||
|
||||
//
|
||||
// JsonVariantConst operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE typename enable_if<IsString<TKey>::value, JsonVariantConst>::type
|
||||
operator[](const TKey& key) const {
|
||||
return get_impl(makeString(key));
|
||||
}
|
||||
//
|
||||
// JsonVariantConst operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TKey*>::value, JsonVariantConst>::type
|
||||
operator[](TKey* key) const {
|
||||
return get_impl(makeString(key));
|
||||
}
|
||||
|
||||
FORCE_INLINE bool operator==(JsonObjectConst rhs) const {
|
||||
return objectEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonVariantConst get_impl(TKey key) const {
|
||||
return JsonVariantConst(objectGet(_data, key));
|
||||
}
|
||||
};
|
||||
|
||||
class JsonObject : public JsonObjectProxy<JsonObjectData>, public Visitable {
|
||||
typedef JsonObjectProxy<JsonObjectData> proxy_type;
|
||||
|
||||
public:
|
||||
typedef JsonObjectIterator iterator;
|
||||
|
||||
FORCE_INLINE JsonObject() : proxy_type(0), _memoryPool(0) {}
|
||||
FORCE_INLINE JsonObject(MemoryPool* buf, JsonObjectData* data)
|
||||
: proxy_type(data), _memoryPool(buf) {}
|
||||
|
||||
operator JsonVariant() const {
|
||||
return JsonVariant(_memoryPool, getVariantData(_data));
|
||||
}
|
||||
|
||||
operator JsonObjectConst() const {
|
||||
return JsonObjectConst(_data);
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_memoryPool, _data->head);
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
void clear() const {
|
||||
objectClear(_data);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool copyFrom(JsonObjectConst src) {
|
||||
return objectCopy(_data, src._data, _memoryPool);
|
||||
}
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
//
|
||||
// JsonArray createNestedArray(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonArray createNestedArray(const TKey& key) const;
|
||||
// JsonArray createNestedArray(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonArray createNestedArray(TKey* key) const;
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
//
|
||||
// JsonObject createNestedObject(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonObject createNestedObject(const TKey& key) const {
|
||||
return set(key).template to<JsonObject>();
|
||||
}
|
||||
//
|
||||
// JsonObject createNestedObject(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonObject createNestedObject(TKey* key) const {
|
||||
return set(key).template to<JsonObject>();
|
||||
}
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
//
|
||||
// TValue get<TValue>(TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename TValue, typename TKey>
|
||||
FORCE_INLINE typename JsonVariantAs<TValue>::type get(const TKey& key) const {
|
||||
return get_impl(makeString(key)).template as<TValue>();
|
||||
}
|
||||
//
|
||||
// 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 TKey>
|
||||
FORCE_INLINE typename JsonVariantAs<TValue>::type get(TKey* key) const {
|
||||
return get_impl(makeString(key)).template as<TValue>();
|
||||
}
|
||||
|
||||
// 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 TKey>
|
||||
FORCE_INLINE bool is(const TKey& key) const {
|
||||
return get_impl(makeString(key)).template is<TValue>();
|
||||
}
|
||||
//
|
||||
// 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 TKey>
|
||||
FORCE_INLINE bool is(TKey* key) const {
|
||||
return get_impl(makeString(key)).template is<TValue>();
|
||||
}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonObjectSubscript<const TKey&> operator[](
|
||||
const TKey& key) const {
|
||||
return JsonObjectSubscript<const TKey&>(*this, key);
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey)
|
||||
// TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonObjectSubscript<TKey*> operator[](TKey* key) const {
|
||||
return JsonObjectSubscript<TKey*>(*this, key);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool operator==(JsonObject rhs) const {
|
||||
return objectEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
FORCE_INLINE void remove(iterator it) const {
|
||||
objectRemove(_data, it.internal());
|
||||
}
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TKey>
|
||||
FORCE_INLINE void remove(const TKey& key) const {
|
||||
remove_impl(makeString(key));
|
||||
}
|
||||
//
|
||||
// void remove(TKey);
|
||||
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
|
||||
template <typename TKey>
|
||||
FORCE_INLINE void remove(TKey* key) const {
|
||||
remove_impl(makeString(key));
|
||||
}
|
||||
|
||||
// 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 TKey>
|
||||
FORCE_INLINE bool set(const TKey& key, const TValue& value) const {
|
||||
return set(key).set(value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = const std::string&, const String&
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue, typename TKey>
|
||||
FORCE_INLINE bool set(const TKey& key, TValue* value) const {
|
||||
return set(key).set(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 TKey>
|
||||
FORCE_INLINE bool set(TKey* key, const TValue& value) const {
|
||||
return set(key).set(value);
|
||||
}
|
||||
//
|
||||
// bool set(TKey, TValue);
|
||||
// TKey = char*, const char*, const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename TValue, typename TKey>
|
||||
FORCE_INLINE bool set(TKey* key, TValue* value) const {
|
||||
return set(key).set(value);
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonVariant set(TKey* key) const {
|
||||
return set_impl(makeString(key));
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonVariant set(const TKey& key) const {
|
||||
return set_impl(makeString(key));
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonVariant set(const StringInMemoryPool& key) const {
|
||||
return set_impl(key);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
JsonObjectConst(_data).accept(visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TStringRef>
|
||||
FORCE_INLINE JsonVariant get_impl(TStringRef key) const {
|
||||
return JsonVariant(_memoryPool, objectGet(_data, key));
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
FORCE_INLINE JsonVariant set_impl(TKey key) const {
|
||||
return JsonVariant(_memoryPool, objectSet(_data, key, _memoryPool));
|
||||
}
|
||||
|
||||
template <typename TStringRef>
|
||||
FORCE_INLINE void remove_impl(TStringRef key) const {
|
||||
objectRemove(_data, objectFindSlot(_data, key));
|
||||
}
|
||||
|
||||
MemoryPool* _memoryPool;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,21 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TString>
|
||||
inline JsonArray JsonObject::createNestedArray(const TString& key) const {
|
||||
return set(key).template to<JsonArray>();
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
inline JsonArray JsonObject::createNestedArray(TString* key) const {
|
||||
return set(key).template to<JsonArray>();
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,123 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/SlotFunctions.hpp"
|
||||
#include "JsonPair.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonPairPtr {
|
||||
public:
|
||||
JsonPairPtr(MemoryPool *memoryPool, Slot *slot) : _pair(memoryPool, slot) {}
|
||||
|
||||
const JsonPair *operator->() const {
|
||||
return &_pair;
|
||||
}
|
||||
|
||||
const JsonPair &operator*() const {
|
||||
return _pair;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonPair _pair;
|
||||
};
|
||||
|
||||
class JsonObjectIterator {
|
||||
public:
|
||||
JsonObjectIterator() : _slot(0) {}
|
||||
|
||||
explicit JsonObjectIterator(MemoryPool *memoryPool, Slot *slot)
|
||||
: _memoryPool(memoryPool), _slot(slot) {}
|
||||
|
||||
JsonPair operator*() const {
|
||||
return JsonPair(_memoryPool, _slot);
|
||||
}
|
||||
JsonPairPtr operator->() {
|
||||
return JsonPairPtr(_memoryPool, _slot);
|
||||
}
|
||||
|
||||
bool operator==(const JsonObjectIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const JsonObjectIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
JsonObjectIterator &operator++() {
|
||||
if (_slot) _slot = _slot->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonObjectIterator &operator+=(size_t distance) {
|
||||
_slot = slotAdvance(_slot, distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Slot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool *_memoryPool;
|
||||
Slot *_slot;
|
||||
};
|
||||
|
||||
class JsonPairConstPtr {
|
||||
public:
|
||||
JsonPairConstPtr(const Slot *slot) : _pair(slot) {}
|
||||
|
||||
const JsonPairConst *operator->() const {
|
||||
return &_pair;
|
||||
}
|
||||
|
||||
const JsonPairConst &operator*() const {
|
||||
return _pair;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonPairConst _pair;
|
||||
};
|
||||
|
||||
class JsonObjectConstIterator {
|
||||
public:
|
||||
JsonObjectConstIterator() : _slot(0) {}
|
||||
|
||||
explicit JsonObjectConstIterator(const Slot *slot) : _slot(slot) {}
|
||||
|
||||
JsonPairConst operator*() const {
|
||||
return JsonPairConst(_slot);
|
||||
}
|
||||
JsonPairConstPtr operator->() {
|
||||
return JsonPairConstPtr(_slot);
|
||||
}
|
||||
|
||||
bool operator==(const JsonObjectConstIterator &other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const JsonObjectConstIterator &other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
JsonObjectConstIterator &operator++() {
|
||||
if (_slot) _slot = _slot->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonObjectConstIterator &operator+=(size_t distance) {
|
||||
_slot = slotAdvance(_slot, distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Slot *internal() {
|
||||
return _slot;
|
||||
}
|
||||
|
||||
private:
|
||||
const Slot *_slot;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,53 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonKey.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
// A key value pair for JsonObjectData.
|
||||
class JsonPair {
|
||||
public:
|
||||
JsonPair(MemoryPool* memoryPool, Slot* slot) : _key(slot) {
|
||||
if (slot) {
|
||||
_value = JsonVariant(memoryPool, &slot->value);
|
||||
}
|
||||
}
|
||||
|
||||
JsonKey key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
JsonVariant value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonKey _key;
|
||||
JsonVariant _value;
|
||||
};
|
||||
|
||||
class JsonPairConst {
|
||||
public:
|
||||
JsonPairConst(const Slot* slot) : _key(slot) {
|
||||
if (slot) {
|
||||
_value = JsonVariantConst(&slot->value);
|
||||
}
|
||||
}
|
||||
|
||||
JsonKey key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
JsonVariantConst value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonKey _key;
|
||||
JsonVariantConst _value;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,19 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantCasts.hpp"
|
||||
#include "JsonVariantComparisons.hpp"
|
||||
#include "JsonVariantOr.hpp"
|
||||
#include "JsonVariantSubscripts.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantBase : public JsonVariantCasts<TImpl>,
|
||||
public JsonVariantComparisons<TImpl>,
|
||||
public JsonVariantOr<TImpl>,
|
||||
public JsonVariantSubscripts<TImpl> {};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,118 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Numbers/parseFloat.hpp"
|
||||
#include "Numbers/parseInteger.hpp"
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline bool JsonVariant::set(JsonArray array) const {
|
||||
return to<JsonArray>().copyFrom(array);
|
||||
}
|
||||
|
||||
inline bool JsonVariant::set(const JsonArraySubscript& value) const {
|
||||
return set(value.as<JsonVariant>());
|
||||
}
|
||||
|
||||
inline bool JsonVariant::set(JsonObject object) const {
|
||||
return to<JsonObject>().copyFrom(object);
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
inline bool JsonVariant::set(const JsonObjectSubscript<TString>& value) const {
|
||||
return set(value.template as<JsonVariant>());
|
||||
}
|
||||
|
||||
inline bool JsonVariant::set(JsonVariantConst value) const {
|
||||
return variantCopy(_data, value._data, _memoryPool);
|
||||
}
|
||||
|
||||
inline bool JsonVariant::set(JsonVariant value) const {
|
||||
return variantCopy(_data, value._data, _memoryPool);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, JsonArray>::value, T>::type
|
||||
JsonVariant::as() const {
|
||||
return JsonArray(_memoryPool, variantAsArray(_data));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, JsonObject>::value, T>::type
|
||||
JsonVariant::as() const {
|
||||
return JsonObject(_memoryPool, variantAsObject(_data));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type
|
||||
JsonVariant::to() const {
|
||||
return JsonArray(_memoryPool, variantToArray(_data));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type
|
||||
JsonVariant::to() const {
|
||||
return JsonObject(_memoryPool, variantToObject(_data));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type
|
||||
JsonVariant::to() const {
|
||||
variantSetNull(_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
inline void JsonVariant::accept(Visitor& visitor) const {
|
||||
return JsonVariantConst(_data).accept(visitor);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
inline void JsonVariantConst::accept(Visitor& visitor) const {
|
||||
if (!_data) return visitor.visitNull();
|
||||
|
||||
switch (_data->type) {
|
||||
case JSON_FLOAT:
|
||||
return visitor.visitFloat(_data->content.asFloat);
|
||||
|
||||
case JSON_ARRAY:
|
||||
return visitor.visitArray(JsonArrayConst(&_data->content.asArray));
|
||||
|
||||
case JSON_OBJECT:
|
||||
return visitor.visitObject(JsonObjectConst(&_data->content.asObject));
|
||||
|
||||
case JSON_LINKED_STRING:
|
||||
case JSON_OWNED_STRING:
|
||||
return visitor.visitString(_data->content.asString);
|
||||
|
||||
case JSON_LINKED_RAW:
|
||||
case JSON_OWNED_RAW:
|
||||
return visitor.visitRawJson(_data->content.asRaw.data,
|
||||
_data->content.asRaw.size);
|
||||
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return visitor.visitNegativeInteger(_data->content.asInteger);
|
||||
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
return visitor.visitPositiveInteger(_data->content.asInteger);
|
||||
|
||||
case JSON_BOOLEAN:
|
||||
return visitor.visitBoolean(_data->content.asInteger != 0);
|
||||
|
||||
default:
|
||||
return visitor.visitNull();
|
||||
}
|
||||
}
|
||||
|
||||
inline JsonVariantConst JsonVariantConst::operator[](size_t index) const {
|
||||
return JsonArrayConst(variantAsArray(_data))[index];
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
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,19 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "MemoryPool.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class AllocableInMemoryPool {
|
||||
public:
|
||||
void *operator new(size_t n, MemoryPool *memoryPool) NOEXCEPT {
|
||||
return memoryPool->alloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *, MemoryPool *)NOEXCEPT {}
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,171 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Strings/StringInMemoryPool.hpp"
|
||||
#include "MemoryPool.hpp"
|
||||
|
||||
#include <stdlib.h> // malloc, free
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#endif
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class DefaultAllocator {
|
||||
public:
|
||||
void* allocate(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
void deallocate(void* pointer) {
|
||||
free(pointer);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TAllocator>
|
||||
class DynamicMemoryPoolBase : public MemoryPool {
|
||||
struct Block;
|
||||
struct EmptyBlock {
|
||||
Block* next;
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
};
|
||||
struct Block : EmptyBlock {
|
||||
uint8_t data[1];
|
||||
};
|
||||
|
||||
public:
|
||||
enum { EmptyBlockSize = sizeof(EmptyBlock) };
|
||||
|
||||
DynamicMemoryPoolBase(size_t initialSize = ARDUINOJSON_DEFAULT_POOL_SIZE)
|
||||
: _head(NULL), _nextBlockCapacity(initialSize) {}
|
||||
|
||||
~DynamicMemoryPoolBase() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void reserve(size_t capacity) {
|
||||
_nextBlockCapacity = capacity;
|
||||
}
|
||||
|
||||
// Gets the number of bytes occupied in the memoryPool
|
||||
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 memoryPool
|
||||
virtual void* alloc(size_t bytes) {
|
||||
alignNextAlloc();
|
||||
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
|
||||
}
|
||||
|
||||
// Resets the memoryPool.
|
||||
// USE WITH CAUTION: this invalidates all previously allocated data
|
||||
void clear() {
|
||||
Block* currentBlock = _head;
|
||||
while (currentBlock != NULL) {
|
||||
_nextBlockCapacity = currentBlock->capacity;
|
||||
Block* nextBlock = currentBlock->next;
|
||||
_allocator.deallocate(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
}
|
||||
_head = 0;
|
||||
}
|
||||
|
||||
class StringBuilder {
|
||||
public:
|
||||
explicit StringBuilder(DynamicMemoryPoolBase* 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++;
|
||||
}
|
||||
|
||||
StringInMemoryPool complete() {
|
||||
append(0);
|
||||
return _start;
|
||||
}
|
||||
|
||||
private:
|
||||
DynamicMemoryPoolBase* _parent;
|
||||
char* _start;
|
||||
size_t _length;
|
||||
};
|
||||
|
||||
StringBuilder startString() {
|
||||
return StringBuilder(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 MemoryPool with dynamic memory allocation.
|
||||
// You are strongly encouraged to consider using StaticMemoryPool which is much
|
||||
// more suitable for embedded systems.
|
||||
typedef DynamicMemoryPoolBase<DefaultAllocator> DynamicMemoryPool;
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
@ -4,37 +4,117 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <string.h>
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
#include "../Polyfills/assert.hpp"
|
||||
#include "../Polyfills/mpl/max.hpp"
|
||||
#include "../Variant/VariantSlot.hpp"
|
||||
#include "Alignment.hpp"
|
||||
#include "MemoryPool.hpp"
|
||||
#include "StringSlot.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
// Handle the memory management (done in derived classes) and calls the parser.
|
||||
// This abstract class is implemented by StaticMemoryPool which implements a
|
||||
// fixed memory allocation.
|
||||
|
||||
// _begin _end
|
||||
// v v
|
||||
// +-------------+--------------+-----------+
|
||||
// | strings... | (free) | ...slots |
|
||||
// +-------------+--------------+-----------+
|
||||
// ^ ^
|
||||
// _left _right
|
||||
|
||||
class MemoryPool {
|
||||
public:
|
||||
// Allocates n bytes in the MemoryPool.
|
||||
// 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.
|
||||
~MemoryPool() {}
|
||||
|
||||
// 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
|
||||
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,128 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Polyfills/mpl/max.hpp"
|
||||
#include "../Strings/StringInMemoryPool.hpp"
|
||||
#include "MemoryPool.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StaticMemoryPoolBase : public MemoryPool {
|
||||
public:
|
||||
class StringBuilder {
|
||||
public:
|
||||
explicit StringBuilder(StaticMemoryPoolBase* 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;
|
||||
}
|
||||
}
|
||||
|
||||
StringInMemoryPool complete() const {
|
||||
if (_parent->canAlloc(1)) {
|
||||
char* last = static_cast<char*>(_parent->doAlloc(1));
|
||||
*last = '\0';
|
||||
return _start;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
StaticMemoryPoolBase* _parent;
|
||||
char* _start;
|
||||
};
|
||||
|
||||
// Gets the capacity of the memoryPool in bytes
|
||||
size_t capacity() const {
|
||||
return _capacity;
|
||||
}
|
||||
|
||||
// Gets the current usage of the memoryPool in bytes
|
||||
size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
// Allocates the specified amount of bytes in the memoryPool
|
||||
virtual void* alloc(size_t bytes) {
|
||||
alignNextAlloc();
|
||||
if (!canAlloc(bytes)) return NULL;
|
||||
return doAlloc(bytes);
|
||||
}
|
||||
|
||||
// Resets the memoryPool.
|
||||
// USE WITH CAUTION: this invalidates all previously allocated data
|
||||
void clear() {
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
StringBuilder startString() {
|
||||
return StringBuilder(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
StaticMemoryPoolBase(char* memoryPool, size_t capa)
|
||||
: _buffer(memoryPool), _capacity(capa), _size(0) {}
|
||||
|
||||
~StaticMemoryPoolBase() {}
|
||||
|
||||
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 MemoryPool with fixed memory allocation.
|
||||
// The template paramenter CAPACITY specifies the capacity of the memoryPool in
|
||||
// bytes.
|
||||
template <size_t CAPACITY>
|
||||
class StaticMemoryPool : public StaticMemoryPoolBase {
|
||||
static const size_t ACTUAL_CAPACITY = Max<1, CAPACITY>::value;
|
||||
|
||||
public:
|
||||
explicit StaticMemoryPool()
|
||||
: StaticMemoryPoolBase(_buffer, ACTUAL_CAPACITY) {}
|
||||
|
||||
private:
|
||||
char _buffer[ACTUAL_CAPACITY];
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
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,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Strings/StringTypes.hpp"
|
||||
#include "../Strings/StringWrappers.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
@ -58,7 +58,7 @@ inline SerializedValue<T> serialized(T str) {
|
||||
|
||||
template <typename TChar>
|
||||
inline SerializedValue<TChar*> serialized(TChar* p) {
|
||||
return SerializedValue<TChar*>(p, makeString(p).size());
|
||||
return SerializedValue<TChar*>(p, wrapString(p).size());
|
||||
}
|
||||
|
||||
template <typename TChar>
|
@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
@ -5,11 +5,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Deserialization/deserialize.hpp"
|
||||
#include "../JsonVariant.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 {
|
||||
|
||||
@ -17,26 +17,28 @@ template <typename TReader, typename TStringStorage>
|
||||
class MsgPackDeserializer {
|
||||
typedef typename remove_reference<TStringStorage>::type::StringBuilder
|
||||
StringBuilder;
|
||||
typedef const char *StringType;
|
||||
|
||||
public:
|
||||
MsgPackDeserializer(MemoryPool &memoryPool, TReader reader,
|
||||
MsgPackDeserializer(MemoryPool &pool, TReader reader,
|
||||
TStringStorage stringStorage, uint8_t nestingLimit)
|
||||
: _memoryPool(&memoryPool),
|
||||
: _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.set(code);
|
||||
variant.setUnsignedInteger(code);
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
if ((code & 0xe0) == 0xe0) {
|
||||
variant.set(static_cast<int8_t>(code));
|
||||
// TODO: add setNegativeInteger()
|
||||
variant.setSignedInteger(static_cast<int8_t>(code));
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
@ -44,9 +46,13 @@ 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:
|
||||
@ -54,11 +60,11 @@ class MsgPackDeserializer {
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc2:
|
||||
variant.set(false);
|
||||
variant.setBoolean(false);
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc3:
|
||||
variant.set(true);
|
||||
variant.setBoolean(true);
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xcc:
|
||||
@ -111,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;
|
||||
@ -173,87 +179,94 @@ class MsgPackDeserializer {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DeserializationError readInteger(JsonVariant variant) {
|
||||
DeserializationError readInteger(VariantData &variant) {
|
||||
T value;
|
||||
if (!readInteger(value)) return DeserializationError::IncompleteInput;
|
||||
variant.set(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.set(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.set(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.set(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) {
|
||||
StringBuilder 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));
|
||||
}
|
||||
StringInMemoryPool s = str.complete();
|
||||
if (s.isNull()) return DeserializationError::NoMemory;
|
||||
variant.set(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 = variant.to<JsonArray>();
|
||||
if (array.isNull()) return DeserializationError::NoMemory;
|
||||
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 value = array.add();
|
||||
if (value.isInvalid()) return DeserializationError::NoMemory;
|
||||
VariantData *value = array.add(_pool);
|
||||
if (!value) return DeserializationError::NoMemory;
|
||||
|
||||
DeserializationError err = parse(value);
|
||||
DeserializationError err = parse(*value);
|
||||
if (err) return err;
|
||||
}
|
||||
++_nestingLimit;
|
||||
@ -261,39 +274,53 @@ class MsgPackDeserializer {
|
||||
}
|
||||
|
||||
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 = variant.to<JsonObject>();
|
||||
if (object.isNull()) return DeserializationError::NoMemory;
|
||||
|
||||
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) {
|
||||
JsonVariantLocal key(_memoryPool);
|
||||
DeserializationError err = parse(key);
|
||||
VariantSlot *slot = object.addSlot(_pool);
|
||||
if (!slot) return DeserializationError::NoMemory;
|
||||
|
||||
StringType key;
|
||||
DeserializationError err = parseKey(key);
|
||||
if (err) return err;
|
||||
if (!key.is<char *>()) return DeserializationError::NotSupported;
|
||||
slot->setOwnedKey(key);
|
||||
|
||||
JsonVariant value = object.set(StringInMemoryPool(key.as<char *>()));
|
||||
if (value.isInvalid()) return DeserializationError::NoMemory;
|
||||
|
||||
err = parse(value);
|
||||
err = parse(*slot->data());
|
||||
if (err) return err;
|
||||
}
|
||||
++_nestingLimit;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
MemoryPool *_memoryPool;
|
||||
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;
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
#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 {
|
||||
|
||||
@ -35,7 +35,7 @@ class MsgPackSerializer {
|
||||
}
|
||||
}
|
||||
|
||||
void visitArray(JsonArrayConst array) {
|
||||
void visitArray(const CollectionData& array) {
|
||||
size_t n = array.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x90 + array.size()));
|
||||
@ -46,12 +46,12 @@ class MsgPackSerializer {
|
||||
writeByte(0xDD);
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
for (JsonArrayConst::iterator it = array.begin(); it != array.end(); ++it) {
|
||||
it->accept(*this);
|
||||
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
|
||||
slot->data()->accept(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void visitObject(JsonObjectConst object) {
|
||||
void visitObject(const CollectionData& object) {
|
||||
size_t n = object.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x80 + n));
|
||||
@ -62,10 +62,9 @@ class MsgPackSerializer {
|
||||
writeByte(0xDF);
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
for (JsonObjectConst::iterator it = object.begin(); it != object.end();
|
||||
++it) {
|
||||
visitString(it->key());
|
||||
it->value().accept(*this);
|
||||
for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
|
||||
visitString(slot->key());
|
||||
slot->data()->accept(*this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,8 +92,8 @@ class MsgPackSerializer {
|
||||
writeBytes(reinterpret_cast<const uint8_t*>(data), size);
|
||||
}
|
||||
|
||||
void visitNegativeInteger(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) {
|
||||
@ -115,7 +114,7 @@ class MsgPackSerializer {
|
||||
#endif
|
||||
}
|
||||
|
||||
void visitPositiveInteger(JsonUInt value) {
|
||||
void visitPositiveInteger(UInt value) {
|
||||
if (value <= 0x7F) {
|
||||
writeInteger(uint8_t(value));
|
||||
} else if (value <= 0xFF) {
|
||||
|
@ -9,8 +9,8 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
typedef double JsonFloat;
|
||||
typedef double Float;
|
||||
#else
|
||||
typedef float JsonFloat;
|
||||
typedef float Float;
|
||||
#endif
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -11,10 +11,10 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
typedef int64_t JsonInteger;
|
||||
typedef uint64_t JsonUInt;
|
||||
typedef int64_t Integer;
|
||||
typedef uint64_t UInt;
|
||||
#else
|
||||
typedef long JsonInteger;
|
||||
typedef unsigned long JsonUInt;
|
||||
typedef long Integer;
|
||||
typedef unsigned long UInt;
|
||||
#endif
|
||||
} // 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
|
@ -4,9 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Operators/VariantOperators.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
@ -16,16 +16,15 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TStringRef>
|
||||
class JsonObjectSubscript
|
||||
: public JsonVariantBase<JsonObjectSubscript<TStringRef> >,
|
||||
public Visitable {
|
||||
typedef JsonObjectSubscript<TStringRef> this_type;
|
||||
class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >,
|
||||
public Visitable {
|
||||
typedef ObjectSubscript<TStringRef> this_type;
|
||||
|
||||
public:
|
||||
FORCE_INLINE JsonObjectSubscript(JsonObject object, TStringRef key)
|
||||
FORCE_INLINE ObjectSubscript(ObjectRef object, TStringRef key)
|
||||
: _object(object), _key(key) {}
|
||||
|
||||
operator JsonVariantConst() const {
|
||||
operator VariantConstRef() const {
|
||||
return get_impl();
|
||||
}
|
||||
|
||||
@ -38,7 +37,7 @@ class JsonObjectSubscript
|
||||
//
|
||||
// operator=(const TValue&);
|
||||
// TValue = bool, char, long, int, short, float, double,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
|
||||
operator=(const TValue &src) {
|
||||
@ -47,7 +46,7 @@ class JsonObjectSubscript
|
||||
}
|
||||
//
|
||||
// operator=(TValue);
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE this_type &operator=(TValue *src) {
|
||||
set_impl().set(src);
|
||||
@ -59,7 +58,7 @@ class JsonObjectSubscript
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename JsonVariantAs<TValue>::type as() const {
|
||||
FORCE_INLINE typename VariantAs<TValue>::type as() const {
|
||||
return get_impl().template as<TValue>();
|
||||
}
|
||||
|
||||
@ -69,7 +68,7 @@ class JsonObjectSubscript
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename JsonVariantTo<TValue>::type to() {
|
||||
FORCE_INLINE typename VariantTo<TValue>::type to() {
|
||||
return set_impl().template to<TValue>();
|
||||
}
|
||||
|
||||
@ -77,8 +76,8 @@ class JsonObjectSubscript
|
||||
//
|
||||
// bool set(const TValue&);
|
||||
// TValue = bool, char, long, int, short, float, double, serialized,
|
||||
// JsonVariant,
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
// VariantRef,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename TValue>
|
||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
|
||||
const TValue &value) {
|
||||
@ -86,7 +85,7 @@ class JsonObjectSubscript
|
||||
}
|
||||
//
|
||||
// bool set(TValue);
|
||||
// TValue = char*, const char, const FlashStringHelper*
|
||||
// TValue = char*, const char, const __FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue *value) {
|
||||
return set_impl().set(value);
|
||||
@ -98,32 +97,32 @@ class JsonObjectSubscript
|
||||
}
|
||||
|
||||
private:
|
||||
JsonVariant get_impl() const {
|
||||
return _object.get<JsonVariant>(_key);
|
||||
FORCE_INLINE VariantRef get_impl() const {
|
||||
return _object.get(_key);
|
||||
}
|
||||
|
||||
JsonVariant set_impl() const {
|
||||
FORCE_INLINE VariantRef set_impl() const {
|
||||
return _object.set(_key);
|
||||
}
|
||||
|
||||
JsonObject _object;
|
||||
ObjectRef _object;
|
||||
TStringRef _key;
|
||||
};
|
||||
|
||||
template <typename TImpl>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString>::value,
|
||||
JsonObjectSubscript<const TString &> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](const TString &key) const {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
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,
|
||||
JsonObjectSubscript<TString *> >::type
|
||||
JsonVariantSubscripts<TImpl>::operator[](TString *key) const {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
ObjectSubscript<TString *> >::type
|
||||
VariantSubscripts<TImpl>::operator[](TString *key) const {
|
||||
return impl()->template as<ObjectRef>()[key];
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
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
|
@ -4,13 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantCasts {
|
||||
class VariantCasts {
|
||||
public:
|
||||
template <typename T>
|
||||
FORCE_INLINE operator T() const {
|
@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariant.hpp"
|
||||
#include "../Variant/VariantRef.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
template <typename T>
|
||||
@ -15,34 +15,34 @@ struct is_simple_value {
|
||||
};
|
||||
|
||||
template <typename TVariant>
|
||||
class JsonVariantComparisons {
|
||||
class VariantComparisons {
|
||||
public:
|
||||
// const char* == TVariant
|
||||
template <typename T>
|
||||
friend typename enable_if<IsString<T *>::value, bool>::type operator==(
|
||||
T *lhs, TVariant rhs) {
|
||||
return makeString(lhs).equals(rhs.template as<const char *>());
|
||||
return wrapString(lhs).equals(rhs.template as<const char *>());
|
||||
}
|
||||
|
||||
// std::string == TVariant
|
||||
template <typename T>
|
||||
friend typename enable_if<IsString<T>::value, bool>::type operator==(
|
||||
const T &lhs, TVariant rhs) {
|
||||
return makeString(lhs).equals(rhs.template as<const char *>());
|
||||
return wrapString(lhs).equals(rhs.template as<const char *>());
|
||||
}
|
||||
|
||||
// TVariant == const char*
|
||||
template <typename T>
|
||||
friend typename enable_if<IsString<T *>::value, bool>::type operator==(
|
||||
TVariant lhs, T *rhs) {
|
||||
return makeString(rhs).equals(lhs.template as<const char *>());
|
||||
return wrapString(rhs).equals(lhs.template as<const char *>());
|
||||
}
|
||||
|
||||
// TVariant == std::string
|
||||
template <typename T>
|
||||
friend typename enable_if<IsString<T>::value, bool>::type operator==(
|
||||
TVariant lhs, const T &rhs) {
|
||||
return makeString(rhs).equals(lhs.template as<const char *>());
|
||||
return wrapString(rhs).equals(lhs.template as<const char *>());
|
||||
}
|
||||
|
||||
// bool/int/float == TVariant
|
||||
@ -63,28 +63,28 @@ class JsonVariantComparisons {
|
||||
template <typename T>
|
||||
friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
|
||||
T *lhs, TVariant rhs) {
|
||||
return !makeString(lhs).equals(rhs.template as<const char *>());
|
||||
return !wrapString(lhs).equals(rhs.template as<const char *>());
|
||||
}
|
||||
|
||||
// std::string != TVariant
|
||||
template <typename T>
|
||||
friend typename enable_if<IsString<T>::value, bool>::type operator!=(
|
||||
const T &lhs, TVariant rhs) {
|
||||
return !makeString(lhs).equals(rhs.template as<const char *>());
|
||||
return !wrapString(lhs).equals(rhs.template as<const char *>());
|
||||
}
|
||||
|
||||
// TVariant != const char*
|
||||
template <typename T>
|
||||
friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
|
||||
TVariant lhs, T *rhs) {
|
||||
return !makeString(rhs).equals(lhs.template as<const char *>());
|
||||
return !wrapString(rhs).equals(lhs.template as<const char *>());
|
||||
}
|
||||
|
||||
// TVariant != std::string
|
||||
template <typename T>
|
||||
friend typename enable_if<IsString<T>::value, bool>::type operator!=(
|
||||
TVariant lhs, const T &rhs) {
|
||||
return !makeString(rhs).equals(lhs.template as<const char *>());
|
||||
return !wrapString(rhs).equals(lhs.template as<const char *>());
|
||||
}
|
||||
|
||||
// bool/int/float != TVariant
|
19
src/ArduinoJson/Operators/VariantOperators.hpp
Normal file
19
src/ArduinoJson/Operators/VariantOperators.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VariantCasts.hpp"
|
||||
#include "VariantComparisons.hpp"
|
||||
#include "VariantOr.hpp"
|
||||
#include "VariantSubscripts.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TImpl>
|
||||
class VariantOperators : public VariantCasts<TImpl>,
|
||||
public VariantComparisons<TImpl>,
|
||||
public VariantOr<TImpl>,
|
||||
public VariantSubscripts<TImpl> {};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -4,16 +4,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Variant/VariantAs.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantOr {
|
||||
class VariantOr {
|
||||
public:
|
||||
// Returns the default value if the JsonVariant is undefined of incompatible
|
||||
// Returns the default value if the VariantRef is undefined of incompatible
|
||||
template <typename T>
|
||||
typename enable_if<!is_integral<T>::value, T>::type operator|(
|
||||
const T &defaultValue) const {
|
||||
@ -23,14 +23,14 @@ class JsonVariantOr {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Returns the default value if the JsonVariant is undefined of incompatible
|
||||
// Returns the default value if the VariantRef is undefined of incompatible
|
||||
// Special case for string: null is treated as undefined
|
||||
const char *operator|(const char *defaultValue) const {
|
||||
const char *value = impl()->template as<const char *>();
|
||||
return value ? value : defaultValue;
|
||||
}
|
||||
|
||||
// Returns the default value if the JsonVariant is undefined of incompatible
|
||||
// Returns the default value if the VariantRef is undefined of incompatible
|
||||
// Special case for integers: we also accept double
|
||||
template <typename Integer>
|
||||
typename enable_if<is_integral<Integer>::value, Integer>::type operator|(
|
@ -4,43 +4,43 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "Strings/StringTypes.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Strings/StringWrappers.hpp"
|
||||
#include "../Variant/VariantAs.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
class ArrayRef;
|
||||
class ObjectRef;
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArraySubscript;
|
||||
class ArraySubscript;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
class ObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantSubscripts {
|
||||
class VariantSubscripts {
|
||||
public:
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
FORCE_INLINE JsonArraySubscript operator[](size_t index) const;
|
||||
FORCE_INLINE ArraySubscript operator[](size_t index) const;
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is
|
||||
// an object.
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey) const;
|
||||
// ObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value,
|
||||
JsonObjectSubscript<const TString &> >::type
|
||||
ObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) const;
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
// ObjectSubscript operator[](TKey) const;
|
||||
// TKey = const char*, const char[N], const __FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString *>::value,
|
||||
JsonObjectSubscript<TString *> >::type
|
||||
ObjectSubscript<TString *> >::type
|
||||
operator[](TString *key) const;
|
||||
|
||||
private:
|
12
src/ArduinoJson/Polyfills/assert.hpp
Normal file
12
src/ArduinoJson/Polyfills/assert.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef ARDUINOJSON_DEBUG
|
||||
#include <assert.h>
|
||||
#define ARDUINOJSON_ASSERT(X) assert(X)
|
||||
#else
|
||||
#define ARDUINOJSON_ASSERT(X) ((void)0)
|
||||
#endif
|
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "type_traits/conditional.hpp"
|
||||
#include "type_traits/enable_if.hpp"
|
||||
#include "type_traits/integral_constant.hpp"
|
||||
#include "type_traits/is_array.hpp"
|
||||
|
18
src/ArduinoJson/Polyfills/type_traits/conditional.hpp
Normal file
18
src/ArduinoJson/Polyfills/type_traits/conditional.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <bool Condition, class TrueType, class FalseType>
|
||||
struct conditional {
|
||||
typedef TrueType type;
|
||||
};
|
||||
|
||||
template <class TrueType, class FalseType>
|
||||
struct conditional<false, TrueType, FalseType> {
|
||||
typedef FalseType type;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T>
|
||||
|
@ -4,20 +4,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Memory/MemoryPool.hpp"
|
||||
#include "../Memory/StringBuilder.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TMemoryPool>
|
||||
class StringCopier {
|
||||
public:
|
||||
StringCopier(TMemoryPool& memoryPool) : _memoryPool(&memoryPool) {}
|
||||
typedef ARDUINOJSON_NAMESPACE::StringBuilder StringBuilder;
|
||||
|
||||
typedef typename TMemoryPool::StringBuilder StringBuilder;
|
||||
StringCopier(MemoryPool* pool) : _pool(pool) {}
|
||||
|
||||
StringBuilder startString() {
|
||||
return _memoryPool->startString();
|
||||
return StringBuilder(_pool);
|
||||
}
|
||||
|
||||
private:
|
||||
TMemoryPool* _memoryPool;
|
||||
MemoryPool* _pool;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -6,34 +6,33 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TChar>
|
||||
class StringMover {
|
||||
public:
|
||||
class StringBuilder {
|
||||
public:
|
||||
StringBuilder(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
|
||||
StringBuilder(char** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
|
||||
|
||||
void append(char c) {
|
||||
*(*_writePtr)++ = TChar(c);
|
||||
*(*_writePtr)++ = char(c);
|
||||
}
|
||||
|
||||
StringInMemoryPool complete() const {
|
||||
char* complete() const {
|
||||
*(*_writePtr)++ = 0;
|
||||
return reinterpret_cast<const char*>(_startPtr);
|
||||
return _startPtr;
|
||||
}
|
||||
|
||||
private:
|
||||
TChar** _writePtr;
|
||||
TChar* _startPtr;
|
||||
char** _writePtr;
|
||||
char* _startPtr;
|
||||
};
|
||||
|
||||
StringMover(TChar* ptr) : _ptr(ptr) {}
|
||||
StringMover(char* ptr) : _ptr(ptr) {}
|
||||
|
||||
StringBuilder startString() {
|
||||
return StringBuilder(&_ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
TChar* _ptr;
|
||||
char* _ptr;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -9,34 +9,34 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TMemoryPool, typename TInput, typename Enable = void>
|
||||
template <typename TInput, typename Enable = void>
|
||||
struct StringStorage {
|
||||
typedef StringCopier<TMemoryPool> type;
|
||||
typedef StringCopier type;
|
||||
|
||||
static type create(TMemoryPool& jb, TInput&) {
|
||||
return type(jb);
|
||||
static type create(MemoryPool& pool, TInput&) {
|
||||
return type(&pool);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TMemoryPool, typename TChar>
|
||||
struct StringStorage<TMemoryPool, TChar*,
|
||||
template <typename TChar>
|
||||
struct StringStorage<TChar*,
|
||||
typename enable_if<!is_const<TChar>::value>::type> {
|
||||
typedef StringMover<TChar> type;
|
||||
typedef StringMover type;
|
||||
|
||||
static type create(TMemoryPool&, TChar* input) {
|
||||
return type(input);
|
||||
static type create(MemoryPool&, TChar* input) {
|
||||
return type(reinterpret_cast<char*>(input));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TMemoryPool, typename TInput>
|
||||
typename StringStorage<TMemoryPool, TInput>::type makeStringStorage(
|
||||
TMemoryPool& jb, TInput& input) {
|
||||
return StringStorage<TMemoryPool, TInput>::create(jb, input);
|
||||
template <typename TInput>
|
||||
typename StringStorage<TInput>::type makeStringStorage(MemoryPool& pool,
|
||||
TInput& input) {
|
||||
return StringStorage<TInput>::create(pool, input);
|
||||
}
|
||||
|
||||
template <typename TMemoryPool, typename TChar>
|
||||
typename StringStorage<TMemoryPool, TChar*>::type makeStringStorage(
|
||||
TMemoryPool& jb, TChar* input) {
|
||||
return StringStorage<TMemoryPool, TChar*>::create(jb, input);
|
||||
template <typename TChar>
|
||||
typename StringStorage<TChar*>::type makeStringStorage(MemoryPool& pool,
|
||||
TChar* input) {
|
||||
return StringStorage<TChar*>::create(pool, input);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -8,17 +8,16 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class ArduinoString {
|
||||
class ArduinoStringWrapper {
|
||||
public:
|
||||
ArduinoString(const ::String& str) : _str(&str) {}
|
||||
ArduinoStringWrapper(const ::String& str) : _str(&str) {}
|
||||
|
||||
template <typename TMemoryPool>
|
||||
const char* save(TMemoryPool* memoryPool) const {
|
||||
char* save(MemoryPool* pool) const {
|
||||
if (isNull()) return NULL;
|
||||
size_t n = _str->length() + 1;
|
||||
void* dup = memoryPool->alloc(n);
|
||||
if (dup != NULL) memcpy(dup, _str->c_str(), n);
|
||||
return static_cast<const char*>(dup);
|
||||
char* dup = pool->allocFrozenString(n);
|
||||
if (dup) memcpy(dup, _str->c_str(), n);
|
||||
return dup;
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
@ -51,8 +50,8 @@ struct IsString< ::String> : true_type {};
|
||||
template <>
|
||||
struct IsString< ::StringSumHelper> : true_type {};
|
||||
|
||||
inline ArduinoString makeString(const ::String& str) {
|
||||
return ArduinoString(str);
|
||||
inline ArduinoStringWrapper wrapString(const ::String& str) {
|
||||
return ArduinoStringWrapper(str);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -9,9 +9,9 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class ZeroTerminatedRamStringConst {
|
||||
class ConstRamStringWrapper {
|
||||
public:
|
||||
ZeroTerminatedRamStringConst(const char* str) : _str(str) {}
|
||||
ConstRamStringWrapper(const char* str = 0) : _str(str) {}
|
||||
|
||||
bool equals(const char* expected) const {
|
||||
const char* actual = _str;
|
||||
@ -23,21 +23,25 @@ class ZeroTerminatedRamStringConst {
|
||||
return !_str;
|
||||
}
|
||||
|
||||
template <typename TMemoryPool>
|
||||
const char* save(TMemoryPool*) const {
|
||||
return _str;
|
||||
}
|
||||
// template <typename TMemoryPool>
|
||||
// const char* save(TMemoryPool*) const {
|
||||
// return _str;
|
||||
// }
|
||||
|
||||
size_t size() const {
|
||||
return strlen(_str);
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* _str;
|
||||
};
|
||||
|
||||
inline ZeroTerminatedRamStringConst makeString(const char* str) {
|
||||
return ZeroTerminatedRamStringConst(str);
|
||||
inline ConstRamStringWrapper wrapString(const char* str) {
|
||||
return ConstRamStringWrapper(str);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -6,9 +6,9 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class ZeroTerminatedFlashString {
|
||||
class FlashStringWrapper {
|
||||
public:
|
||||
ZeroTerminatedFlashString(const __FlashStringHelper* str) : _str(str) {}
|
||||
FlashStringWrapper(const __FlashStringHelper* str) : _str(str) {}
|
||||
|
||||
bool equals(const char* expected) const {
|
||||
const char* actual = reinterpret_cast<const char*>(_str);
|
||||
@ -20,13 +20,12 @@ class ZeroTerminatedFlashString {
|
||||
return !_str;
|
||||
}
|
||||
|
||||
template <typename TMemoryPool>
|
||||
const char* save(TMemoryPool* memoryPool) const {
|
||||
char* save(MemoryPool* pool) const {
|
||||
if (!_str) return NULL;
|
||||
size_t n = size() + 1; // copy the terminator
|
||||
void* dup = memoryPool->alloc(n);
|
||||
if (dup != NULL) memcpy_P(dup, (const char*)_str, n);
|
||||
return static_cast<const char*>(dup);
|
||||
char* dup = pool->allocFrozenString(n);
|
||||
if (dup) memcpy_P(dup, reinterpret_cast<const char*>(_str), n);
|
||||
return dup;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
@ -37,8 +36,8 @@ class ZeroTerminatedFlashString {
|
||||
const __FlashStringHelper* _str;
|
||||
};
|
||||
|
||||
inline ZeroTerminatedFlashString makeString(const __FlashStringHelper* str) {
|
||||
return ZeroTerminatedFlashString(str);
|
||||
inline FlashStringWrapper wrapString(const __FlashStringHelper* str) {
|
||||
return FlashStringWrapper(str);
|
||||
}
|
||||
|
||||
template <>
|
43
src/ArduinoJson/Strings/RamStringWrapper.hpp
Normal file
43
src/ArduinoJson/Strings/RamStringWrapper.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ConstRamStringWrapper.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class RamStringWrapper : public ConstRamStringWrapper {
|
||||
public:
|
||||
RamStringWrapper(const char* str) : ConstRamStringWrapper(str) {}
|
||||
|
||||
char* save(MemoryPool* pool) const {
|
||||
if (!_str) return NULL;
|
||||
size_t n = size() + 1;
|
||||
char* dup = pool->allocFrozenString(n);
|
||||
if (dup) memcpy(dup, _str, n);
|
||||
return dup;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
inline RamStringWrapper wrapString(const TChar* str) {
|
||||
return RamStringWrapper(reinterpret_cast<const char*>(str));
|
||||
}
|
||||
|
||||
inline RamStringWrapper wrapString(char* str) {
|
||||
return RamStringWrapper(str);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
struct IsString<TChar*> {
|
||||
static const bool value = sizeof(TChar) == 1;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsString<void*> {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -6,9 +6,9 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class FixedSizeFlashString {
|
||||
class SizedFlashStringWrapper {
|
||||
public:
|
||||
FixedSizeFlashString(const __FlashStringHelper* str, size_t sz)
|
||||
SizedFlashStringWrapper(const __FlashStringHelper* str, size_t sz)
|
||||
: _str(str), _size(sz) {}
|
||||
|
||||
bool equals(const char* expected) const {
|
||||
@ -21,12 +21,11 @@ class FixedSizeFlashString {
|
||||
return !_str;
|
||||
}
|
||||
|
||||
template <typename TMemoryPool>
|
||||
const char* save(TMemoryPool* memoryPool) const {
|
||||
char* save(MemoryPool* pool) const {
|
||||
if (!_str) return NULL;
|
||||
void* dup = memoryPool->alloc(_size);
|
||||
if (dup != NULL) memcpy_P(dup, (const char*)_str, _size);
|
||||
return static_cast<const char*>(dup);
|
||||
char* dup = pool->allocFrozenString(_size);
|
||||
if (!dup) memcpy_P(dup, (const char*)_str, _size);
|
||||
return dup;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
@ -38,8 +37,8 @@ class FixedSizeFlashString {
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
inline FixedSizeFlashString makeString(const __FlashStringHelper* str,
|
||||
size_t sz) {
|
||||
return FixedSizeFlashString(str, sz);
|
||||
inline SizedFlashStringWrapper wrapString(const __FlashStringHelper* str,
|
||||
size_t sz) {
|
||||
return SizedFlashStringWrapper(str, sz);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -8,9 +8,9 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class FixedSizeRamString {
|
||||
class SizedRamStringWrapper {
|
||||
public:
|
||||
FixedSizeRamString(const char* str, size_t n) : _str(str), _size(n) {}
|
||||
SizedRamStringWrapper(const char* str, size_t n) : _str(str), _size(n) {}
|
||||
|
||||
bool equals(const char* expected) const {
|
||||
const char* actual = reinterpret_cast<const char*>(_str);
|
||||
@ -22,13 +22,11 @@ class FixedSizeRamString {
|
||||
return !_str;
|
||||
}
|
||||
|
||||
template <typename TMemoryPool>
|
||||
const char* save(TMemoryPool* memoryPool) const {
|
||||
char* save(MemoryPool* pool) const {
|
||||
if (!_str) return NULL;
|
||||
void* dup = memoryPool->alloc(_size);
|
||||
if (!dup) return NULL;
|
||||
memcpy(dup, _str, _size);
|
||||
return static_cast<const char*>(dup);
|
||||
char* dup = pool->allocFrozenString(_size);
|
||||
if (dup) memcpy(dup, _str, _size);
|
||||
return dup;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
@ -41,8 +39,8 @@ class FixedSizeRamString {
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
inline FixedSizeRamString makeString(const TChar* str, size_t size) {
|
||||
return FixedSizeRamString(reinterpret_cast<const char*>(str), size);
|
||||
inline SizedRamStringWrapper wrapString(const TChar* str, size_t size) {
|
||||
return SizedRamStringWrapper(reinterpret_cast<const char*>(str), size);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -8,16 +8,15 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StlString {
|
||||
class StlStringWrapper {
|
||||
public:
|
||||
StlString(const std::string& str) : _str(&str) {}
|
||||
StlStringWrapper(const std::string& str) : _str(&str) {}
|
||||
|
||||
template <typename TMemoryPool>
|
||||
const char* save(TMemoryPool* memoryPool) const {
|
||||
char* save(MemoryPool* pool) const {
|
||||
size_t n = _str->length() + 1;
|
||||
void* dup = memoryPool->alloc(n);
|
||||
if (dup != NULL) memcpy(dup, _str->c_str(), n);
|
||||
return static_cast<const char*>(dup);
|
||||
char* dup = pool->allocFrozenString(n);
|
||||
if (dup) memcpy(dup, _str->c_str(), n);
|
||||
return dup;
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
@ -44,8 +43,8 @@ class StlString {
|
||||
template <>
|
||||
struct IsString<std::string> : true_type {};
|
||||
|
||||
inline StlString makeString(const std::string& str) {
|
||||
return StlString(str);
|
||||
inline StlStringWrapper wrapString(const std::string& str) {
|
||||
return StlStringWrapper(str);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
32
src/ArduinoJson/Strings/String.hpp
Normal file
32
src/ArduinoJson/Strings/String.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class String {
|
||||
public:
|
||||
String() : _data(0) {}
|
||||
String(const char* slot) : _data(slot) {}
|
||||
|
||||
const char* c_str() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return !_data;
|
||||
}
|
||||
|
||||
friend bool operator==(String lhs, String rhs) {
|
||||
if (lhs._data == rhs._data) return true;
|
||||
if (!lhs._data) return false;
|
||||
if (!rhs._data) return false;
|
||||
return strcmp(lhs._data, rhs._data) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* _data;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,16 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ZeroTerminatedRamStringConst.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StringInMemoryPool : public ZeroTerminatedRamStringConst {
|
||||
public:
|
||||
StringInMemoryPool(const char* str = 0) : ZeroTerminatedRamStringConst(str) {}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Memory/MemoryPool.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
@ -17,20 +18,19 @@ template <typename T>
|
||||
struct IsString<T&> : IsString<T> {};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#include "FixedSizeRamString.hpp"
|
||||
#include "StringInMemoryPool.hpp"
|
||||
#include "ZeroTerminatedRamString.hpp"
|
||||
#include "ZeroTerminatedRamStringConst.hpp"
|
||||
#include "ConstRamStringWrapper.hpp"
|
||||
#include "RamStringWrapper.hpp"
|
||||
#include "SizedRamStringWrapper.hpp"
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||
#include "StlString.hpp"
|
||||
#include "StlStringWrapper.hpp"
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#include "ArduinoString.hpp"
|
||||
#include "ArduinoStringWrapper.hpp"
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||
#include "FixedSizeFlashString.hpp"
|
||||
#include "ZeroTerminatedFlashString.hpp"
|
||||
#include "FlashStringWrapper.hpp"
|
||||
#include "SizedFlashStringWrapper.hpp"
|
||||
#endif
|
@ -1,46 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ZeroTerminatedRamStringConst.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class ZeroTerminatedRamString : public ZeroTerminatedRamStringConst {
|
||||
public:
|
||||
ZeroTerminatedRamString(const char* str)
|
||||
: ZeroTerminatedRamStringConst(str) {}
|
||||
|
||||
template <typename TMemoryPool>
|
||||
const char* save(TMemoryPool* memoryPool) const {
|
||||
if (!_str) return NULL;
|
||||
size_t n = size() + 1;
|
||||
void* dup = memoryPool->alloc(n);
|
||||
if (!dup) return NULL;
|
||||
memcpy(dup, _str, n);
|
||||
return static_cast<const char*>(dup);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
inline ZeroTerminatedRamString makeString(const TChar* str) {
|
||||
return ZeroTerminatedRamString(reinterpret_cast<const char*>(str));
|
||||
}
|
||||
|
||||
inline ZeroTerminatedRamString makeString(char* str) {
|
||||
return ZeroTerminatedRamString(str);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
struct IsString<TChar*> {
|
||||
static const bool value = sizeof(TChar) == 1;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsString<void*> {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
38
src/ArduinoJson/Variant/SlotFunctions.hpp
Normal file
38
src/ArduinoJson/Variant/SlotFunctions.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Memory/MemoryPool.hpp"
|
||||
#include "../Polyfills/assert.hpp"
|
||||
#include "../Strings/StringWrappers.hpp"
|
||||
#include "VariantData.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TKey>
|
||||
inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) {
|
||||
if (!var) return false;
|
||||
char* dup = key.save(pool);
|
||||
if (!dup) return false;
|
||||
var->setOwnedKey(dup);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool slotSetKey(VariantSlot* var, ConstRamStringWrapper key,
|
||||
MemoryPool*) {
|
||||
if (!var) return false;
|
||||
var->setLinkedKey(key.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
inline size_t slotSize(const VariantSlot* var) {
|
||||
size_t n = 0;
|
||||
while (var) {
|
||||
n++;
|
||||
var = var->next();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
88
src/ArduinoJson/Variant/VariantAs.hpp
Normal file
88
src/ArduinoJson/Variant/VariantAs.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Serialization/DynamicStringWriter.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class ArrayRef;
|
||||
class ArrayConstRef;
|
||||
class ObjectRef;
|
||||
class ObjectConstRef;
|
||||
class VariantRef;
|
||||
class VariantConstRef;
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// VariantRef::as<T>()
|
||||
template <typename T>
|
||||
struct VariantAs {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VariantAs<char*> {
|
||||
typedef const char* type;
|
||||
};
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// VariantRef::as<T>()
|
||||
template <typename T>
|
||||
struct VariantConstAs {
|
||||
typedef typename VariantAs<T>::type type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VariantConstAs<VariantRef> {
|
||||
typedef VariantConstRef type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VariantConstAs<ObjectRef> {
|
||||
typedef ObjectConstRef type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct VariantConstAs<ArrayRef> {
|
||||
typedef ArrayConstRef type;
|
||||
};
|
||||
|
||||
// ---
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_integral<T>::value, T>::type variantAs(
|
||||
const VariantData* _data) {
|
||||
return _data != 0 ? _data->asIntegral<T>() : T(0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, bool>::value, T>::type variantAs(
|
||||
const VariantData* _data) {
|
||||
return _data != 0 ? _data->asBoolean() : false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_floating_point<T>::value, T>::type variantAs(
|
||||
const VariantData* _data) {
|
||||
return _data != 0 ? _data->asFloat<T>() : T(0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, const char*>::value ||
|
||||
is_same<T, char*>::value,
|
||||
const char*>::type
|
||||
variantAs(const VariantData* _data) {
|
||||
return _data != 0 ? _data->asString() : 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
|
||||
variantAs(const VariantData* _data);
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
|
||||
const VariantData* _data);
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -4,25 +4,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Serialization/DynamicStringWriter.hpp"
|
||||
#include "VariantFunctions.hpp"
|
||||
#include "VariantRef.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<JsonVariantConst, T>::value, T>::type
|
||||
variantAs(const JsonVariantData* _data) {
|
||||
return JsonVariantConst(_data);
|
||||
inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
|
||||
variantAs(const VariantData* _data) {
|
||||
return VariantConstRef(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data) {
|
||||
const char* cstr = variantAsString(_data);
|
||||
const VariantData* _data) {
|
||||
const char* cstr = _data != 0 ? _data->asString() : 0;
|
||||
if (cstr) return T(cstr);
|
||||
T s;
|
||||
serializeJson(JsonVariantConst(_data), s);
|
||||
serializeJson(VariantConstRef(_data), s);
|
||||
return s;
|
||||
}
|
||||
|
46
src/ArduinoJson/Variant/VariantContent.hpp
Normal file
46
src/ArduinoJson/Variant/VariantContent.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#include "../Collection/CollectionData.hpp"
|
||||
#include "../Numbers/Float.hpp"
|
||||
#include "../Numbers/Integer.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
enum {
|
||||
VALUE_IS_NULL = 0,
|
||||
VALUE_IS_LINKED_RAW,
|
||||
VALUE_IS_OWNED_RAW,
|
||||
VALUE_IS_LINKED_STRING,
|
||||
VALUE_IS_OWNED_STRING,
|
||||
VALUE_IS_BOOLEAN,
|
||||
VALUE_IS_POSITIVE_INTEGER,
|
||||
VALUE_IS_NEGATIVE_INTEGER,
|
||||
VALUE_IS_ARRAY,
|
||||
VALUE_IS_OBJECT,
|
||||
VALUE_IS_FLOAT,
|
||||
VALUE_MASK = 0x7F,
|
||||
KEY_IS_OWNED = 0x80
|
||||
};
|
||||
|
||||
struct RawData {
|
||||
const char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
union VariantContent {
|
||||
Float asFloat;
|
||||
UInt asInteger;
|
||||
CollectionData asCollection;
|
||||
const char *asString;
|
||||
struct {
|
||||
const char *data;
|
||||
size_t size;
|
||||
} asRaw;
|
||||
};
|
||||
} // 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