Compare commits

..

19 Commits

Author SHA1 Message Date
a5cd1b1693 Set version to 6.7.0-beta 2018-12-07 12:23:02 +01:00
d8a1eec530 Renamed JsonKey to JsonString 2018-12-07 12:08:30 +01:00
e20c47c57b DynamicJsonDocument reallocates memory pool is it's too small 2018-12-07 10:38:58 +01:00
b77b203935 Extracted VariantData and CollectionData classes 2018-12-07 09:16:58 +01:00
1ad97ebf85 Merge branch 'master' into 6.x 2018-12-04 16:52:15 +01:00
ef12c74771 Set version to 5.13.4 2018-12-04 11:36:16 +01:00
0bc03e8071 Removed spurious files in the Particle library 2018-12-04 11:19:22 +01:00
04286f3228 Moved size measurements to github.com/bblanchon/ArduinoJson-size 2018-12-04 10:50:45 +01:00
1d942cdf41 Use singly-linked list to reduce memory usage 2018-12-01 12:05:51 +01:00
aaf0d5c3c5 Renamed and moved internal files 2018-11-30 17:53:54 +01:00
04e8acd844 Store offset between slots to reduce memory usage 2018-11-30 14:28:00 +01:00
8ff48dde73 Moved size measurements to github.com/bblanchon/ArduinoJson-size 2018-11-30 14:27:35 +01:00
41b2e629f7 Increased test coverage 2018-11-30 14:27:35 +01:00
a60162ba76 Removed the indirection via StringSlot 2018-11-30 14:27:35 +01:00
45f4e5ac20 Restored the monotonic allocator 2018-11-30 14:27:33 +01:00
637f7a5bfa Removed template parameter of CharPointerReader and StringMover 2018-11-16 16:24:36 +01:00
399ccec645 Added a CSV showing the evolution of the size of the sample programs 2018-11-16 15:08:53 +01:00
2bd280df80 Removed the automatic expansion of DynamicJsonDocument 2018-11-16 10:26:59 +01:00
c832edbda3 Added script to compile samples on wandbox.org 2018-11-14 18:02:01 +01:00
135 changed files with 3564 additions and 4216 deletions

View File

@ -1,6 +1,16 @@
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)
-----------
@ -9,7 +19,7 @@ v6.6.0-beta (2018-11-13)
* 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
* ~~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)

View File

@ -7,8 +7,8 @@ project(ArduinoJson)
enable_testing()
add_definitions(-DARDUINOJSON_DEBUG)
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_definitions(-DARDUINOJSON_DEBUG)
add_compile_options(-g -O0)
endif()

View File

@ -2,6 +2,10 @@
# 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

View File

@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"version": "6.6.0-beta",
"version": "6.7.0-beta",
"authors": {
"name": "Benoit Blanchon",
"url": "https://blog.benoitblanchon.fr"

View File

@ -1,5 +1,5 @@
name=ArduinoJson
version=6.6.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.

View File

@ -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

View 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

View File

@ -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"

View 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;
}

View 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;
}

View 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;
}

View 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"

View File

@ -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

View 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

View 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

View 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

View File

@ -4,9 +4,9 @@
#pragma once
#include "Data/ArrayFunctions.hpp"
#include "Data/JsonVariantData.hpp"
#include "JsonArrayIterator.hpp"
#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.
@ -15,108 +15,105 @@
namespace ARDUINOJSON_NAMESPACE {
class JsonObject;
class JsonArraySubscript;
class ObjectRef;
class ArraySubscript;
template <typename TData>
class JsonArrayProxy {
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 JsonVariantConst operator[](size_t index) const {
return JsonVariantConst(arrayGet(_data, index));
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return VariantConstRef(_data ? _data->get(index) : 0);
}
FORCE_INLINE size_t size() const {
return arraySize(_data);
return _data ? _data->size() : 0;
}
protected:
JsonArrayProxy(TData* data) : _data(data) {}
ArrayRefBase(TData* data) : _data(data) {}
TData* _data;
};
class JsonArrayConst : public JsonArrayProxy<const JsonArrayData>,
public Visitable {
friend class JsonArray;
typedef JsonArrayProxy<const JsonArrayData> proxy_type;
class ArrayConstRef : public ArrayRefBase<const CollectionData>,
public Visitable {
friend class ArrayRef;
typedef ArrayRefBase<const CollectionData> base_type;
public:
typedef JsonArrayConstIterator iterator;
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
if (_data)
visitor.visitArray(*this);
else
visitor.visitNull();
}
typedef ArrayConstRefIterator iterator;
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_data->head);
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 ArrayConstRef() : base_type(0) {}
FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {}
FORCE_INLINE bool operator==(JsonArrayConst rhs) const {
FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
return arrayEquals(_data, rhs._data);
}
};
class JsonArray : public JsonArrayProxy<JsonArrayData>, public Visitable {
typedef JsonArrayProxy<JsonArrayData> proxy_type;
class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
typedef ArrayRefBase<CollectionData> base_type;
public:
typedef JsonArrayIterator iterator;
typedef ArrayIterator iterator;
FORCE_INLINE JsonArray() : proxy_type(0), _memoryPool(0) {}
FORCE_INLINE JsonArray(MemoryPool* pool, JsonArrayData* data)
: proxy_type(data), _memoryPool(pool) {}
FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {}
FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data)
: base_type(data), _pool(pool) {}
operator JsonVariant() {
return JsonVariant(_memoryPool, getVariantData(_data));
operator VariantRef() {
return VariantRef(_pool, reinterpret_cast<VariantData*>(_data));
}
operator JsonArrayConst() const {
return JsonArrayConst(_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, JsonVariant,
// std::string, String, JsonObject
// 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(JsonArray value) const {
FORCE_INLINE bool add(ArrayRef value) const {
return add().set(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const FlashStringHelper*
// 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));
VariantRef add() const {
return VariantRef(_pool, arrayAdd(_data, _pool));
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_memoryPool, _data->head);
return iterator(_pool, _data->head());
}
FORCE_INLINE iterator end() const {
@ -144,7 +141,7 @@ class JsonArray : public JsonArrayProxy<JsonArrayData>, public Visitable {
bool copyFrom(T (&array)[N1][N2]) const {
bool ok = true;
for (size_t i = 0; i < N1; i++) {
JsonArray nestedArray = createNestedArray();
ArrayRef nestedArray = createNestedArray();
for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(array[i][j]);
}
@ -152,9 +149,10 @@ class JsonArray : public JsonArrayProxy<JsonArrayData>, public Visitable {
return ok;
}
// Copy a JsonArray
FORCE_INLINE bool copyFrom(JsonArray src) const {
return arrayCopy(_data, src._data, _memoryPool);
// 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
@ -177,45 +175,37 @@ class JsonArray : public JsonArrayProxy<JsonArrayData>, public Visitable {
if (!_data) return;
size_t i = 0;
for (iterator it = begin(); it != end() && i < N1; ++it) {
it->as<JsonArray>().copyTo(array[i++]);
it->as<ArrayRef>().copyTo(array[i++]);
}
}
FORCE_INLINE JsonArray createNestedArray() const;
FORCE_INLINE JsonObject createNestedObject() const;
FORCE_INLINE ArrayRef createNestedArray() const;
FORCE_INLINE ObjectRef createNestedObject() const;
FORCE_INLINE JsonArraySubscript operator[](size_t index) const;
FORCE_INLINE ArraySubscript operator[](size_t index) const;
FORCE_INLINE bool operator==(JsonArray rhs) const {
FORCE_INLINE bool operator==(ArrayRef rhs) const {
return arrayEquals(_data, rhs._data);
}
// Gets the value at the specified index.
FORCE_INLINE JsonVariant get(size_t index) const {
return JsonVariant(_memoryPool, arrayGet(_data, 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 {
arrayRemove(_data, it.internal(), _memoryPool);
if (!_data) return;
_data->remove(it.internal());
}
// Removes element at specified index.
FORCE_INLINE void remove(size_t index) const {
arrayRemove(_data, index, _memoryPool);
}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
JsonArrayConst(_data).accept(visitor);
if (!_data) return;
_data->remove(index);
}
private:
template <typename TValueRef>
FORCE_INLINE bool add_impl(TValueRef value) const {
return add().set(value);
}
MemoryPool* _memoryPool;
MemoryPool* _pool;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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,32 +13,32 @@
#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;
}
@ -48,7 +48,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript>,
}
template <typename T>
FORCE_INLINE typename JsonVariantAs<T>::type as() const {
FORCE_INLINE typename VariantAs<T>::type as() const {
return get_impl().as<T>();
}
@ -58,22 +58,22 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript>,
}
template <typename T>
FORCE_INLINE typename JsonVariantTo<T>::type to() const {
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:
FORCE_INLINE JsonVariant get_impl() const {
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

View 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

View 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

View File

@ -1,114 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariantData.hpp"
#include "SlotFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline JsonVariantData* arrayAdd(JsonArrayData* arr, MemoryPool* pool) {
if (!arr) return 0;
VariantSlot* slot = pool->allocVariant();
if (!slot) return 0;
slot->next = 0;
slot->value.type = JSON_NULL;
if (arr->tail) {
slot->prev = arr->tail;
arr->tail->next = slot;
arr->tail = slot;
} else {
slot->prev = 0;
arr->head = slot;
arr->tail = slot;
}
slot->value.keyIsOwned = false;
return &slot->value;
}
inline VariantSlot* 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) {
VariantSlot* slot = arrayGetSlot(arr, index);
return slot ? &slot->value : 0;
}
inline void arrayRemove(JsonArrayData* arr, VariantSlot* slot,
MemoryPool* pool) {
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;
slotFree(slot, pool);
}
inline void arrayRemove(JsonArrayData* arr, size_t index, MemoryPool* pool) {
arrayRemove(arr, arrayGetSlot(arr, index), pool);
}
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 (VariantSlot* 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;
VariantSlot* s1 = a1->head;
VariantSlot* 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);
}
inline void arrayFree(JsonArrayData* arr, MemoryPool* pool) {
ARDUINOJSON_ASSERT(arr);
VariantSlot* cur = arr->head;
while (cur) {
VariantSlot* next = cur->next;
slotFree(cur, pool);
cur = next;
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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

View File

@ -1,81 +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 VariantSlot *head;
struct VariantSlot *tail;
};
struct JsonArrayData {
struct VariantSlot *head;
struct VariantSlot *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 StringSlot *asOwnedString;
struct StringSlot *asOwnedRaw;
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 keyIsOwned : 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

View File

@ -1,128 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Memory/MemoryPool.hpp"
#include "JsonVariantData.hpp"
#include "SlotFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline VariantSlot* objectFindSlot(const JsonObjectData* obj, TKey key) {
if (!obj) return 0;
VariantSlot* slot = obj->head;
while (slot) {
if (key.equals(slotGetKey(slot))) 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) {
VariantSlot* slot = pool->allocVariant();
if (!slot) return 0;
slot->next = 0;
slot->value.type = JSON_NULL;
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
VariantSlot* 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) {
VariantSlot* 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, VariantSlot* slot,
MemoryPool* pool) {
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;
slotFree(slot, pool);
}
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 (VariantSlot* s = src->head; s; s = s->next) {
JsonVariantData* var;
if (s->value.keyIsOwned)
var = objectAdd(dst, ZeroTerminatedRamString(s->ownedKey->value), pool);
else
var = objectAdd(dst, ZeroTerminatedRamStringConst(s->linkedKey), 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 (VariantSlot* s = o1->head; s; s = s->next) {
JsonVariantData* v1 = &s->value;
JsonVariantData* v2 = objectGet(o2, makeString(slotGetKey(s)));
if (!variantEquals(v1, v2)) return false;
}
return true;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,77 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Memory/MemoryPool.hpp"
#include "../Polyfills/assert.hpp"
#include "../Strings/StringTypes.hpp"
#include "JsonVariantData.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) {
StringSlot* slot = key.save(pool);
if (!slot) return false;
var->ownedKey = slot;
var->value.keyIsOwned = true;
return true;
}
inline bool slotSetKey(VariantSlot* var, ZeroTerminatedRamStringConst key,
MemoryPool*) {
var->linkedKey = key.c_str();
var->value.keyIsOwned = false;
return true;
}
inline bool slotSetKey(VariantSlot* var, StringInMemoryPool key, MemoryPool*) {
var->ownedKey = key.slot();
var->value.keyIsOwned = true;
return true;
}
inline const char* slotGetKey(const VariantSlot* var) {
return var->value.keyIsOwned ? var->ownedKey->value : var->linkedKey;
}
inline const VariantSlot* slotAdvance(const VariantSlot* var, size_t distance) {
while (distance && var) {
var = var->next;
distance--;
}
return var;
}
inline VariantSlot* slotAdvance(VariantSlot* var, size_t distance) {
while (distance && var) {
var = var->next;
distance--;
}
return var;
}
inline size_t slotSize(const VariantSlot* var) {
size_t n = 0;
while (var) {
n++;
var = var->next;
}
return n;
}
void variantFree(JsonVariantData* var, MemoryPool* pool);
inline void slotFree(VariantSlot* var, MemoryPool* pool) {
ARDUINOJSON_ASSERT(var != 0);
ARDUINOJSON_ASSERT(pool != 0);
variantFree(&var->value, pool);
if (var->value.keyIsOwned) pool->freeString(var->ownedKey);
pool->freeVariant(var);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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

View File

@ -1,341 +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"
namespace ARDUINOJSON_NAMESPACE {
inline void variantFree(JsonVariantData* var, MemoryPool* pool) {
ARDUINOJSON_ASSERT(var != 0);
ARDUINOJSON_ASSERT(pool != 0);
switch (var->type) {
case JSON_ARRAY:
case JSON_OBJECT:
arrayFree(&var->content.asArray, pool);
break;
case JSON_OWNED_STRING:
case JSON_OWNED_RAW:
pool->freeString(var->content.asOwnedString);
break;
default:
break;
}
}
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:
return parseInteger<T>(var->content.asString);
case JSON_OWNED_STRING:
return parseInteger<T>(var->content.asOwnedString->value);
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:
return parseFloat<T>(var->content.asString);
case JSON_OWNED_STRING:
return parseFloat<T>(var->content.asOwnedString->value);
case JSON_FLOAT:
return static_cast<T>(var->content.asFloat);
default:
return 0;
}
}
inline const char* variantAsString(const JsonVariantData* var) {
if (!var) return 0;
switch (var->type) {
case JSON_LINKED_STRING:
return var->content.asString;
case JSON_OWNED_STRING:
return var->content.asOwnedString->value;
default:
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,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_BOOLEAN;
var->content.asInteger = static_cast<JsonUInt>(value);
return true;
}
inline bool variantSetFloat(JsonVariantData* var, JsonFloat value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_FLOAT;
var->content.asFloat = value;
return true;
}
template <typename T>
inline bool variantSetSignedInteger(JsonVariantData* var, T value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
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 variantSetUnsignedInteger(JsonVariantData* var, JsonUInt value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_POSITIVE_INTEGER;
var->content.asInteger = static_cast<JsonUInt>(value);
return true;
}
inline bool variantSetLinkedRaw(JsonVariantData* var,
SerializedValue<const char*> value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
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;
variantFree(var, pool);
StringSlot* slot = makeString(value.data(), value.size()).save(pool);
if (slot) {
var->type = JSON_OWNED_RAW;
var->content.asOwnedRaw = slot;
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;
variantFree(var, pool);
StringSlot* slot = value.save(pool);
if (slot) {
var->type = JSON_OWNED_STRING;
var->content.asOwnedString = slot;
return true;
} else {
var->type = JSON_NULL;
return false;
}
}
inline bool variantSetOwnedString(JsonVariantData* var, StringSlot* slot,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_OWNED_STRING;
var->content.asOwnedString = slot;
return true;
}
inline bool variantSetString(JsonVariantData* var, const char* value,
MemoryPool* pool) {
if (!var) return false;
variantFree(var, pool);
var->type = JSON_LINKED_STRING;
var->content.asString = value;
return true;
}
inline void variantSetNull(JsonVariantData* var, MemoryPool* pool) {
if (!var) return;
variantFree(var, pool);
var->type = JSON_NULL;
}
inline JsonArrayData* variantToArray(JsonVariantData* var, MemoryPool* pool) {
if (!var) return 0;
variantFree(var, pool);
var->type = JSON_ARRAY;
var->content.asArray.head = 0;
var->content.asArray.tail = 0;
return &var->content.asArray;
}
inline JsonObjectData* variantToObject(JsonVariantData* var, MemoryPool* pool) {
if (!var) return 0;
variantFree(var, pool);
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) {
variantFree(dst, pool);
dst->type = JSON_NULL;
return true;
}
switch (src->type) {
case JSON_ARRAY:
return arrayCopy(variantToArray(dst, pool), &src->content.asArray, pool);
case JSON_OBJECT:
return objectCopy(variantToObject(dst, pool), &src->content.asObject,
pool);
case JSON_OWNED_STRING:
return variantSetString(
dst, makeString(src->content.asOwnedString->value), pool);
case JSON_OWNED_RAW:
return variantSetOwnedRaw(dst,
serialized(src->content.asOwnedRaw->value,
src->content.asOwnedRaw->size),
pool);
default:
variantFree(dst, pool);
// caution: don't override keyIsOwned
dst->type = src->type;
dst->content = src->content;
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_LINKED_STRING:
return !strcmp(a->content.asString, b->content.asString);
case JSON_OWNED_RAW:
case JSON_OWNED_STRING:
return a->content.asOwnedString->size == b->content.asOwnedString->size &&
!memcmp(a->content.asOwnedString->value,
b->content.asOwnedString->value,
a->content.asOwnedString->size);
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

View File

@ -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

View File

@ -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

View 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

View 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

View 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

View File

@ -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,26 +18,26 @@ template <typename TReader, typename TStringStorage>
class JsonDeserializer {
typedef typename remove_reference<TStringStorage>::type::StringBuilder
StringBuilder;
typedef typename StringBuilder::StringType StringType;
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);
@ -68,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;
@ -87,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;
@ -106,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;
@ -124,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
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;
@ -158,7 +153,7 @@ class JsonDeserializer {
}
}
DeserializationError parseValue(JsonVariant variant) {
DeserializationError parseValue(VariantData &variant) {
if (isQuote(current())) {
return parseStringValue(variant);
} else {
@ -174,11 +169,11 @@ class JsonDeserializer {
}
}
DeserializationError parseStringValue(JsonVariant variant) {
DeserializationError parseStringValue(VariantData &variant) {
StringType value;
DeserializationError err = parseQuotedString(value);
if (err) return err;
variant.set(value);
variant.setOwnedString(value);
return DeserializationError::Ok;
}
@ -208,7 +203,7 @@ class JsonDeserializer {
}
result = builder.complete();
if (result.isNull()) return DeserializationError::NoMemory;
if (!result) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
@ -229,11 +224,11 @@ class JsonDeserializer {
}
result = builder.complete();
if (result.isNull()) return DeserializationError::NoMemory;
if (!result) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
DeserializationError parseNumericValue(JsonVariant result) {
DeserializationError parseNumericValue(VariantData &result) {
char buffer[64];
uint8_t n = 0;
@ -246,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 {
@ -333,7 +328,7 @@ class JsonDeserializer {
}
}
MemoryPool *_memoryPool;
MemoryPool *_pool;
TReader _reader;
TStringStorage _stringStorage;
uint8_t _nestingLimit;

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -1,122 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#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, VariantSlot *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;
}
VariantSlot *internal() {
return _slot;
}
private:
MemoryPool *_memoryPool;
VariantSlot *_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 VariantSlot *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 VariantSlot *internal() {
return _slot;
}
private:
const VariantSlot *_slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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() {
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

View File

@ -1,33 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class JsonKey {
public:
JsonKey(const VariantSlot* slot) : _slot(slot) {}
operator const char*() const {
return c_str();
}
const char* c_str() const {
return _slot ? slotGetKey(_slot) : 0;
}
bool isNull() const {
return _slot == 0 || _slot->linkedKey == 0;
}
friend bool operator==(JsonKey lhs, const char* rhs) {
if (lhs.isNull()) return rhs == 0;
return rhs ? !strcmp(lhs, rhs) : false;
}
private:
const VariantSlot* _slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,290 +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::VariantSlot))
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 TKey>
FORCE_INLINE JsonVariantConst get(const TKey& key) const {
return get_impl(makeString(key));
}
//
// 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 TKey>
FORCE_INLINE JsonVariantConst get(TKey* key) const {
return get_impl(makeString(key));
}
//
// 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 TKey>
FORCE_INLINE JsonVariant get(const TKey& key) const {
return get_impl(makeString(key));
}
//
// TValue get<TValue>(TKey) const;
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TKey>
FORCE_INLINE JsonVariant get(TKey* key) const {
return get_impl(makeString(key));
}
// 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(), _memoryPool);
}
// 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));
}
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(StringInMemoryPool key) const {
return set_impl(key);
}
FORCE_INLINE JsonVariant set(ZeroTerminatedRamStringConst 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* _memoryPool;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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

View File

@ -1,124 +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, VariantSlot *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, VariantSlot *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;
}
VariantSlot *internal() {
return _slot;
}
private:
MemoryPool *_memoryPool;
VariantSlot *_slot;
};
class JsonPairConstPtr {
public:
JsonPairConstPtr(const VariantSlot *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 VariantSlot *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 VariantSlot *internal() {
return _slot;
}
private:
const VariantSlot *_slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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, VariantSlot* 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 VariantSlot* 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

View File

@ -1,330 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include "Data/JsonVariantData.hpp"
#include "Data/VariantAs.hpp"
#include "Data/VariantFunctions.hpp"
#include "JsonVariant.hpp"
#include "JsonVariantBase.hpp"
#include "Memory/MemoryPool.hpp"
#include "Numbers/parseFloat.hpp"
#include "Numbers/parseInteger.hpp"
#include "Polyfills/type_traits.hpp"
#include "Visitable.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Forward declarations.
class JsonArray;
class JsonObject;
// Contains the methods shared by JsonVariant and JsonVariantConst
template <typename TData>
class JsonVariantProxy {
public:
// Tells wether the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
//
// bool is<char>() const;
// bool is<signed char>() const;
// bool is<signed short>() const;
// bool is<signed int>() const;
// bool is<signed long>() const;
// bool is<unsigned char>() const;
// bool is<unsigned short>() const;
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_integral<T>::value, bool>::type is()
const {
return variantIsInteger(_data);
}
//
// bool is<double>() const;
// bool is<float>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
const {
return variantIsFloat(_data);
}
//
// bool is<bool>() const
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, bool>::value, bool>::type is()
const {
return _data && _data->type == JSON_BOOLEAN;
}
//
// bool is<const char*>() const;
// bool is<char*>() const;
// bool is<std::string>() const;
// bool is<String>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, const char *>::value ||
is_same<T, char *>::value ||
IsWriteableString<T>::value,
bool>::type
is() const {
return variantIsString(_data);
}
//
// bool is<JsonArray> const;
// bool is<const JsonArray> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, JsonArray>::value, bool>::type
is() const {
return variantIsArray(_data);
}
//
// bool is<JsonObject> const;
// bool is<const JsonObject> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, JsonObject>::value, bool>::type
is() const {
return variantIsObject(_data);
}
FORCE_INLINE bool isNull() const {
return variantIsNull(_data);
}
FORCE_INLINE bool isInvalid() const {
return _data == 0;
}
size_t size() const {
return objectSize(variantAsObject(_data)) +
arraySize(variantAsArray(_data));
}
protected:
JsonVariantProxy(TData *data) : _data(data) {}
TData *_data;
};
// A variant that can be a any value serializable to a JSON value.
//
// It can be set to:
// - a boolean
// - a char, short, int or a long (signed or unsigned)
// - a string (const char*)
// - a reference to a JsonArray or JsonObject
class JsonVariant : public JsonVariantProxy<JsonVariantData>,
public JsonVariantBase<JsonVariant>,
public Visitable {
typedef JsonVariantProxy<JsonVariantData> proxy_type;
friend class JsonVariantConst;
public:
// Intenal use only
FORCE_INLINE JsonVariant(MemoryPool *memoryPool, JsonVariantData *data)
: proxy_type(data), _memoryPool(memoryPool) {}
// Creates an uninitialized JsonVariant
FORCE_INLINE JsonVariant() : proxy_type(0), _memoryPool(0) {}
// set(bool value)
FORCE_INLINE bool set(bool value) const {
return variantSetBoolean(_data, value, _memoryPool);
}
// set(double value);
// set(float value);
template <typename T>
FORCE_INLINE bool set(
T value,
typename enable_if<is_floating_point<T>::value>::type * = 0) const {
return variantSetFloat(_data, static_cast<JsonFloat>(value), _memoryPool);
}
// set(char)
// set(signed short)
// set(signed int)
// set(signed long)
// set(signed char)
template <typename T>
FORCE_INLINE bool set(
T value,
typename enable_if<is_integral<T>::value && is_signed<T>::value>::type * =
0) const {
return variantSetSignedInteger(_data, value, _memoryPool);
}
// set(unsigned short)
// set(unsigned int)
// set(unsigned long)
template <typename T>
FORCE_INLINE bool set(
T value, typename enable_if<is_integral<T>::value &&
is_unsigned<T>::value>::type * = 0) const {
return variantSetUnsignedInteger(_data, static_cast<JsonUInt>(value),
_memoryPool);
}
// set(SerializedValue<const char *>)
FORCE_INLINE bool set(SerializedValue<const char *> value) const {
return variantSetLinkedRaw(_data, value, _memoryPool);
}
// set(SerializedValue<std::string>)
// set(SerializedValue<String>)
// set(SerializedValue<const __FlashStringHelper*>)
template <typename T>
FORCE_INLINE bool set(
SerializedValue<T> value,
typename enable_if<!is_same<const char *, T>::value>::type * = 0) const {
return variantSetOwnedRaw(_data, value, _memoryPool);
}
// set(const std::string&)
// set(const String&)
template <typename T>
FORCE_INLINE bool set(
const T &value,
typename enable_if<IsString<T>::value>::type * = 0) const {
return variantSetString(_data, makeString(value), _memoryPool);
}
// set(char*)
template <typename T>
FORCE_INLINE bool set(
T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
return variantSetString(_data, makeString(value), _memoryPool);
}
// set(const char*);
FORCE_INLINE bool set(const char *value) const {
return variantSetString(_data, value, _memoryPool);
}
// for internal use only
FORCE_INLINE bool set(StringInMemoryPool value) const {
return variantSetOwnedString(_data, value.slot(), _memoryPool);
}
FORCE_INLINE bool set(ZeroTerminatedRamStringConst value) const {
return variantSetString(_data, value.c_str(), _memoryPool);
}
bool set(JsonVariantConst value) const;
bool set(JsonVariant value) const;
FORCE_INLINE bool set(JsonArray array) const;
FORCE_INLINE bool set(const JsonArraySubscript &) const;
FORCE_INLINE bool set(JsonObject object) const;
template <typename TString>
FORCE_INLINE bool set(const JsonObjectSubscript<TString> &) const;
// Get the variant as the specified type.
//
// std::string as<std::string>() const;
// String as<String>() const;
template <typename T>
FORCE_INLINE typename enable_if<!is_same<T, JsonArray>::value &&
!is_same<T, JsonObject>::value &&
!is_same<T, JsonVariant>::value,
typename JsonVariantAs<T>::type>::type
as() const {
return variantAs<T>(_data);
}
//
// JsonArray as<JsonArray>() const;
// const JsonArray as<const JsonArray>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, JsonArray>::value, T>::type as()
const;
//
// JsonObject as<JsonObject>() const;
// const JsonObject as<const JsonObject>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, JsonObject>::value, T>::type as()
const;
//
// JsonVariant as<JsonVariant> const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, JsonVariant>::value, T>::type as()
const {
return *this;
}
template <typename Visitor>
void accept(Visitor &visitor) const;
FORCE_INLINE bool operator==(JsonVariant lhs) const {
return variantEquals(_data, lhs._data);
}
FORCE_INLINE bool operator!=(JsonVariant lhs) const {
return !variantEquals(_data, lhs._data);
}
// Change the type of the variant
//
// JsonArray to<JsonArray>()
template <typename T>
typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type to() const;
//
// JsonObject to<JsonObject>()
template <typename T>
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type to()
const;
//
// JsonObject to<JsonVariant>()
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type to()
const;
private:
MemoryPool *_memoryPool;
};
class JsonVariantConst : public JsonVariantProxy<const JsonVariantData>,
public JsonVariantBase<JsonVariantConst>,
public Visitable {
typedef JsonVariantProxy<const JsonVariantData> proxy_type;
friend class JsonVariant;
public:
JsonVariantConst() : proxy_type(0) {}
JsonVariantConst(const JsonVariantData *data) : proxy_type(data) {}
JsonVariantConst(JsonVariant var) : proxy_type(var._data) {}
template <typename Visitor>
void accept(Visitor &visitor) const;
// Get the variant as the specified type.
//
template <typename T>
FORCE_INLINE typename JsonVariantConstAs<T>::type as() const {
return variantAs<typename JsonVariantConstAs<T>::type>(_data);
}
FORCE_INLINE JsonVariantConst operator[](size_t index) const;
//
// const JsonVariantConst operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, JsonVariantConst>::type
operator[](const TString &key) const {
return JsonVariantConst(objectGet(variantAsObject(_data), makeString(key)));
}
//
// JsonVariantConst operator[](TKey);
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString *>::value, JsonVariantConst>::type
operator[](TString *key) const {
return JsonVariantConst(objectGet(variantAsObject(_data), makeString(key)));
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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

View File

@ -1,123 +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, _memoryPool));
}
template <typename T>
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type
JsonVariant::to() const {
return JsonObject(_memoryPool, variantToObject(_data, _memoryPool));
}
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type
JsonVariant::to() const {
variantSetNull(_data, _memoryPool);
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:
return visitor.visitString(_data->content.asString);
case JSON_OWNED_STRING:
return visitor.visitString(_data->content.asOwnedString->value);
case JSON_OWNED_RAW:
return visitor.visitRawJson(_data->content.asOwnedRaw->value,
_data->content.asOwnedRaw->size);
case JSON_LINKED_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

View File

@ -1,187 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Strings/StringInMemoryPool.hpp"
#include "Alignment.hpp"
#include "MemoryPool.hpp"
#include "StaticMemoryPool.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 {
class Block : public StaticMemoryPoolBase {
public:
Block(char* buf, size_t sz, Block* nxt)
: StaticMemoryPoolBase(buf, sz), next(nxt) {}
Block* next;
};
public:
enum { EmptyBlockSize = sizeof(Block) };
DynamicMemoryPoolBase(size_t initialSize = ARDUINOJSON_DEFAULT_POOL_SIZE)
: _head(NULL), _nextBlockCapacity(initialSize) {}
~DynamicMemoryPoolBase() {
clear();
}
void reserve(size_t capacity) {
_nextBlockCapacity = capacity;
}
virtual size_t size() const {
size_t sum = 0;
for (Block* b = _head; b; b = b->next) {
sum += b->size();
}
return sum;
}
virtual VariantSlot* allocVariant() {
for (Block* b = _head; b; b = b->next) {
VariantSlot* s = b->allocVariant();
if (s) return s;
}
if (!addNewBlock(sizeof(VariantSlot))) return 0;
return _head->allocVariant();
}
virtual void freeVariant(VariantSlot* slot) {
for (Block* b = _head; b; b = b->next) {
if (b->owns(slot)) {
b->freeVariant(slot);
break;
}
}
}
virtual void freeString(StringSlot* slot) {
for (Block* b = _head; b; b = b->next) {
if (b->owns(slot)) {
b->freeString(slot);
break;
}
}
}
virtual StringSlot* allocFrozenString(size_t n) {
for (Block* b = _head; b; b = b->next) {
StringSlot* s = b->allocFrozenString(n);
if (s) return s;
}
if (!addNewBlock(sizeof(StringSlot) + n)) return 0;
return _head->allocFrozenString(n);
}
virtual StringSlot* allocExpandableString() {
for (Block* b = _head; b; b = b->next) {
StringSlot* s = b->allocExpandableString();
if (s) return s;
}
if (!addNewBlock(sizeof(StringSlot))) return 0;
return _head->allocExpandableString();
}
virtual StringSlot* expandString(StringSlot* oldSlot) {
if (!addNewBlock(sizeof(StringSlot) + oldSlot->size)) return 0;
StringSlot* newSlot = _head->allocExpandableString();
ARDUINOJSON_ASSERT(newSlot->size > oldSlot->size);
memcpy(newSlot->value, oldSlot->value, oldSlot->size);
freeString(oldSlot);
return newSlot;
}
virtual void freezeString(StringSlot* slot, size_t newSize) {
for (Block* b = _head; b; b = b->next) {
if (b->owns(slot)) {
b->freezeString(slot, newSize);
}
}
}
// 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;
}
size_t blockCount() const {
size_t sum = 0;
for (Block* b = _head; b; b = b->next) sum++;
return sum;
}
private:
bool addNewBlock(size_t minCapacity) {
size_t capacity = _nextBlockCapacity;
if (minCapacity > capacity) capacity = minCapacity;
capacity = addPadding(capacity);
size_t bytes = sizeof(Block) + capacity;
char* p = reinterpret_cast<char*>(_allocator.allocate(bytes));
if (!p) return false;
Block* block = new (p) Block(p + sizeof(Block), capacity, _head);
_nextBlockCapacity = capacity * 2;
_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

View File

@ -4,31 +4,117 @@
#pragma once
#include <stddef.h> // for size_t
#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"
#include "VariantSlot.hpp"
namespace ARDUINOJSON_NAMESPACE {
// _begin _end
// v v
// +-------------+--------------+-----------+
// | strings... | (free) | ...slots |
// +-------------+--------------+-----------+
// ^ ^
// _left _right
class MemoryPool {
public:
virtual StringSlot *allocExpandableString() = 0;
virtual StringSlot *allocFrozenString(size_t) = 0;
virtual StringSlot *expandString(StringSlot *) = 0;
virtual void freezeString(StringSlot *, size_t) = 0;
virtual void freeString(StringSlot *) = 0;
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));
}
virtual VariantSlot *allocVariant() = 0;
virtual void freeVariant(VariantSlot *) = 0;
void* buffer() {
return _begin;
}
virtual size_t size() const = 0;
// Gets the capacity of the memoryPool in bytes
size_t capacity() const {
return size_t(_end - _begin);
}
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() {}
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

View File

@ -1,67 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h> // for size_t
namespace ARDUINOJSON_NAMESPACE {
template <typename TSlot>
class SlotList {
public:
SlotList() : _head(0) {}
TSlot *pop() {
TSlot *slot = _head;
if (slot) _head = slot->next;
return slot;
}
void push(TSlot *slot) {
slot->next = _head;
_head = slot;
}
bool remove(const TSlot *slot) {
if (_head == slot) {
_head = slot->next;
return true;
}
for (TSlot *s = _head; s; s = s->next) {
if (s->next == slot) {
s->next = slot->next;
return true;
}
}
return false;
}
bool remove(const void *slot) {
return remove(reinterpret_cast<const TSlot *>(slot));
}
template <typename Functor>
void forEach(const Functor &f) {
for (TSlot *s = _head; s; s = s->next) {
f(s);
}
}
size_t size() const {
size_t sum = 0;
for (TSlot *s = _head; s; s = s->next) sum += sizeof(TSlot);
return sum;
}
void clear() {
_head = 0;
}
private:
TSlot *_head;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,236 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Polyfills/assert.hpp"
#include "../Polyfills/mpl/max.hpp"
#include "../Strings/StringInMemoryPool.hpp"
#include "Alignment.hpp"
#include "MemoryPool.hpp"
#include "SlotList.hpp"
namespace ARDUINOJSON_NAMESPACE {
// _begin _end
// v v
// +-------------+--------------+-----------+
// | strings... | (free) | ...slots |
// +-------------+--------------+-----------+
// ^ ^
// _left _right
class StaticMemoryPoolBase : public MemoryPool {
class UpdateStringSlotAddress {
public:
UpdateStringSlotAddress(const char* address, size_t offset)
: _address(address), _offset(offset) {}
void operator()(StringSlot* slot) const {
ARDUINOJSON_ASSERT(slot != NULL);
if (slot->value > _address) slot->value -= _offset;
}
private:
const char* _address;
size_t _offset;
};
public:
// Gets the capacity of the memoryPool in bytes
size_t capacity() const {
return size_t(_end - _begin);
}
virtual size_t size() const {
return allocated_bytes() - _freeVariants.size() - _freeStrings.size();
}
virtual VariantSlot* allocVariant() {
VariantSlot* s = _freeVariants.pop();
if (s) return s;
return s ? s : allocRight<VariantSlot>();
}
virtual void freeVariant(VariantSlot* slot) {
freeVariantSlot(slot);
compactRightSide();
}
virtual void freeString(StringSlot* slot) {
freeStringSlot(slot);
compactLeftSide(slot->value, slot->size);
compactRightSide();
}
virtual StringSlot* allocFrozenString(size_t n) {
StringSlot* s = allocStringSlot();
if (!s) return 0;
if (!canAlloc(n)) return 0;
s->value = _left;
s->size = n;
_left += n;
_usedString.push(s);
checkInvariants();
return s;
}
virtual StringSlot* allocExpandableString() {
StringSlot* s = allocStringSlot();
if (!s) return 0;
s->value = _left;
s->size = size_t(_right - _left);
_usedString.push(s);
_left = _right;
checkInvariants();
return s;
}
virtual StringSlot* expandString(StringSlot*) {
return 0;
}
virtual void freezeString(StringSlot* slot, size_t newSize) {
_left -= (slot->size - newSize);
slot->size = newSize;
checkInvariants();
}
void clear() {
_left = _begin;
_right = _end;
_freeVariants.clear();
_freeStrings.clear();
_usedString.clear();
}
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;
}
protected:
StaticMemoryPoolBase(char* buffer, size_t capa)
: _begin(buffer),
_left(buffer),
_right(buffer + capa),
_end(buffer + capa) {}
~StaticMemoryPoolBase() {}
// Gets the current usage of the memoryPool in bytes
size_t allocated_bytes() const {
return size_t(_left - _begin + _end - _right);
}
private:
StringSlot* allocStringSlot() {
StringSlot* s = _freeStrings.pop();
if (s) return s;
return allocRight<StringSlot>();
}
void freeVariantSlot(VariantSlot* slot) {
_freeVariants.push(slot);
}
void freeStringSlot(StringSlot* slot) {
_usedString.remove(slot);
_freeStrings.push(slot);
}
void compactLeftSide(char* holeAddress, size_t holeSize) {
ARDUINOJSON_ASSERT(holeAddress >= _begin);
ARDUINOJSON_ASSERT(holeAddress + holeSize <= _left);
char* holeEnd = holeAddress + holeSize;
memmove(holeAddress, // where the hole begun
holeEnd, // where the hole ended
size_t(_left - holeEnd)); // everything after the hole
_left -= holeSize;
_usedString.forEach(UpdateStringSlotAddress(holeAddress, holeSize));
checkInvariants();
}
void compactRightSide() {
loop:
if (_freeStrings.remove(_right)) {
_right += sizeof(StringSlot);
goto loop;
}
if (_freeVariants.remove(_right)) {
_right += sizeof(VariantSlot);
goto loop;
}
checkInvariants();
}
void checkInvariants() {
ARDUINOJSON_ASSERT(_begin <= _left);
ARDUINOJSON_ASSERT(_left <= _right);
ARDUINOJSON_ASSERT(_right <= _end);
}
char *_begin, *_left, *_right, *_end;
SlotList<VariantSlot> _freeVariants;
SlotList<StringSlot> _freeStrings;
SlotList<StringSlot> _usedString;
}; // namespace ARDUINOJSON_NAMESPACE
#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 =
AddPadding<Max<1, CAPACITY>::value>::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

View File

@ -4,15 +4,12 @@
#pragma once
#include "../Strings/StringInMemoryPool.hpp"
#include "MemoryPool.hpp"
namespace ARDUINOJSON_NAMESPACE {
class StringBuilder {
public:
typedef StringInMemoryPool StringType;
explicit StringBuilder(MemoryPool* parent) : _parent(parent), _size(0) {
_slot = _parent->allocExpandableString();
}
@ -26,28 +23,28 @@ class StringBuilder {
}
void append(char c) {
if (!_slot) return;
if (!_slot.value) return;
if (_size >= _slot->size) {
_slot = _parent->expandString(_slot);
if (!_slot) return;
if (_size >= _slot.size) {
_slot.value = 0;
return;
}
_slot->value[_size++] = c;
_slot.value[_size++] = c;
}
StringType complete() {
char* complete() {
append('\0');
if (_slot) {
if (_slot.value) {
_parent->freezeString(_slot, _size);
}
return _slot;
return _slot.value;
}
private:
MemoryPool* _parent;
size_t _size;
StringSlot* _slot;
StringSlot _slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -7,14 +7,12 @@
#include <stddef.h> // for size_t
#include "../Configuration.hpp"
#define JSON_STRING_SIZE(SIZE) \
(sizeof(ARDUINOJSON_NAMESPACE::StringSlot) + (SIZE))
#define JSON_STRING_SIZE(SIZE) (SIZE)
namespace ARDUINOJSON_NAMESPACE {
struct StringSlot {
char *value;
size_t size;
struct StringSlot *next;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,21 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Data/JsonVariantData.hpp"
namespace ARDUINOJSON_NAMESPACE {
struct VariantSlot {
JsonVariantData value;
struct VariantSlot* next;
struct VariantSlot* prev;
union {
const char* linkedKey;
StringSlot* ownedKey;
};
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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>

View File

@ -4,7 +4,7 @@
#pragma once
#include "Polyfills/type_traits.hpp"
#include "../Polyfills/type_traits.hpp"
namespace ARDUINOJSON_NAMESPACE {

View File

@ -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,27 +17,28 @@ template <typename TReader, typename TStringStorage>
class MsgPackDeserializer {
typedef typename remove_reference<TStringStorage>::type::StringBuilder
StringBuilder;
typedef typename StringBuilder::StringType StringType;
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;
}
@ -45,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:
@ -55,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:
@ -112,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;
@ -174,48 +179,48 @@ 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);
@ -228,46 +233,40 @@ class MsgPackDeserializer {
return readString(str, size);
}
DeserializationError readString(JsonVariant variant, size_t n) {
DeserializationError readString(VariantData &variant, size_t n) {
StringType s;
DeserializationError err = readString(s, n);
if (!err) variant.set(s);
if (!err) variant.setOwnedString(s);
return err;
}
DeserializationError readString(StringType &s, size_t n) {
DeserializationError readString(StringType &result, size_t n) {
StringBuilder builder = _stringStorage.startString();
for (; n; --n) {
uint8_t c;
if (!readBytes(c)) return DeserializationError::IncompleteInput;
builder.append(static_cast<char>(c));
}
s = builder.complete();
if (s.isNull()) return DeserializationError::NoMemory;
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;
@ -275,31 +274,25 @@ 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) {
VariantSlot *slot = object.addSlot(_pool);
if (!slot) return DeserializationError::NoMemory;
StringType key;
DeserializationError err = parseKey(key);
if (err) return err;
slot->setOwnedKey(key);
JsonVariant value = object.set(key);
if (value.isInvalid()) return DeserializationError::NoMemory;
err = parse(value);
err = parse(*slot->data());
if (err) return err;
}
++_nestingLimit;
@ -327,7 +320,7 @@ class MsgPackDeserializer {
}
}
MemoryPool *_memoryPool;
MemoryPool *_pool;
TReader _reader;
TStringStorage _stringStorage;
uint8_t _nestingLimit;

View File

@ -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) {

View File

@ -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

View File

@ -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

View 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

View 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

View 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

View 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

View File

@ -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:
FORCE_INLINE JsonVariant get_impl() const {
FORCE_INLINE VariantRef get_impl() const {
return _object.get(_key);
}
FORCE_INLINE 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

View 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

View File

@ -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 {

View File

@ -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

View 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

View File

@ -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|(

View File

@ -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:

View File

@ -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"

View 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

View File

@ -4,6 +4,8 @@
#pragma once
#include <stddef.h> // size_t
namespace ARDUINOJSON_NAMESPACE {
template <typename T>

View File

@ -13,13 +13,13 @@ class StringCopier {
public:
typedef ARDUINOJSON_NAMESPACE::StringBuilder StringBuilder;
StringCopier(MemoryPool* memoryPool) : _memoryPool(memoryPool) {}
StringCopier(MemoryPool* pool) : _pool(pool) {}
StringBuilder startString() {
return StringBuilder(_memoryPool);
return StringBuilder(_pool);
}
private:
MemoryPool* _memoryPool;
MemoryPool* _pool;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,36 +6,33 @@
namespace ARDUINOJSON_NAMESPACE {
template <typename TChar>
class StringMover {
public:
class StringBuilder {
public:
typedef ZeroTerminatedRamStringConst StringType;
StringBuilder(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
StringBuilder(char** ptr) : _writePtr(ptr), _startPtr(*ptr) {}
void append(char c) {
*(*_writePtr)++ = TChar(c);
*(*_writePtr)++ = char(c);
}
StringType 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

View File

@ -21,10 +21,10 @@ struct StringStorage {
template <typename TChar>
struct StringStorage<TChar*,
typename enable_if<!is_const<TChar>::value>::type> {
typedef StringMover<TChar> type;
typedef StringMover type;
static type create(MemoryPool&, TChar* input) {
return type(input);
return type(reinterpret_cast<char*>(input));
}
};

View File

@ -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>
StringSlot* save(TMemoryPool* memoryPool) const {
char* save(MemoryPool* pool) const {
if (isNull()) return NULL;
size_t n = _str->length() + 1;
StringSlot* slot = memoryPool->allocFrozenString(n);
if (slot) memcpy(slot->value, _str->c_str(), n);
return slot;
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

View File

@ -9,9 +9,9 @@
namespace ARDUINOJSON_NAMESPACE {
class ZeroTerminatedRamStringConst {
class ConstRamStringWrapper {
public:
ZeroTerminatedRamStringConst(const char* str = 0) : _str(str) {}
ConstRamStringWrapper(const char* str = 0) : _str(str) {}
bool equals(const char* expected) const {
const char* actual = _str;
@ -40,8 +40,8 @@ class ZeroTerminatedRamStringConst {
const char* _str;
};
inline ZeroTerminatedRamStringConst makeString(const char* str) {
return ZeroTerminatedRamStringConst(str);
inline ConstRamStringWrapper wrapString(const char* str) {
return ConstRamStringWrapper(str);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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>
StringSlot* save(TMemoryPool* memoryPool) const {
char* save(MemoryPool* pool) const {
if (!_str) return NULL;
size_t n = size() + 1; // copy the terminator
StringSlot* slot = memoryPool->allocFrozenString(n);
if (slot) memcpy_P(slot->value, reinterpret_cast<const char*>(_str), n);
return slot;
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 <>

View 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

View File

@ -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>
StringSlot* save(TMemoryPool* memoryPool) const {
char* save(MemoryPool* pool) const {
if (!_str) return NULL;
StringSlot* slot = memoryPool->allocFrozenString(_size);
if (!slot) memcpy_P(slot->value, (const char*)_str, _size);
return slot;
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

View File

@ -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,12 +22,11 @@ class FixedSizeRamString {
return !_str;
}
template <typename TMemoryPool>
StringSlot* save(TMemoryPool* memoryPool) const {
char* save(MemoryPool* pool) const {
if (!_str) return NULL;
StringSlot* slot = memoryPool->allocFrozenString(_size);
if (slot) memcpy(slot->value, _str, _size);
return slot;
char* dup = pool->allocFrozenString(_size);
if (dup) memcpy(dup, _str, _size);
return dup;
}
size_t size() const {
@ -40,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

View File

@ -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>
StringSlot* save(TMemoryPool* memoryPool) const {
char* save(MemoryPool* pool) const {
size_t n = _str->length() + 1;
StringSlot* slot = memoryPool->allocFrozenString(n);
if (slot) memcpy(slot->value, _str->c_str(), n);
return slot;
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

View 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

View File

@ -1,48 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <string.h>
#include "../Memory/StringSlot.hpp"
namespace ARDUINOJSON_NAMESPACE {
class StringInMemoryPool {
public:
StringInMemoryPool(StringSlot* s = 0) : _slot(s) {}
bool equals(const char* expected) const {
if (!_slot) return expected == 0;
const char* actual = _slot->value;
if (actual == expected) return true;
return strcmp(actual, expected) == 0;
}
bool isNull() const {
return !_slot;
}
template <typename TMemoryPool>
StringSlot* save(TMemoryPool*) const {
return _slot;
}
size_t size() const {
return _slot->size;
}
StringSlot* slot() const {
return _slot;
}
const char* c_str() const {
return _slot->value;
}
protected:
StringSlot* _slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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

View File

@ -1,45 +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>
StringSlot* save(TMemoryPool* memoryPool) const {
if (!_str) return NULL;
size_t n = size() + 1;
StringSlot* slot = memoryPool->allocFrozenString(n);
if (slot) memcpy(slot->value, _str, n);
return slot;
}
};
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

View 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

View 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

View File

@ -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;
}

View 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

View File

@ -0,0 +1,287 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Misc/SerializedValue.hpp"
#include "VariantContent.hpp"
namespace ARDUINOJSON_NAMESPACE {
class VariantData {
VariantContent _content; // must be first to allow cast from array to variant
uint8_t _flags;
public:
// Must be a POD!
// - no constructor
// - no destructor
// - no virtual
// - no inheritance
template <typename Visitor>
void accept(Visitor &visitor) const {
switch (type()) {
case VALUE_IS_FLOAT:
return visitor.visitFloat(_content.asFloat);
case VALUE_IS_ARRAY:
return visitor.visitArray(_content.asCollection);
case VALUE_IS_OBJECT:
return visitor.visitObject(_content.asCollection);
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return visitor.visitString(_content.asString);
case VALUE_IS_OWNED_RAW:
case VALUE_IS_LINKED_RAW:
return visitor.visitRawJson(_content.asRaw.data, _content.asRaw.size);
case VALUE_IS_NEGATIVE_INTEGER:
return visitor.visitNegativeInteger(_content.asInteger);
case VALUE_IS_POSITIVE_INTEGER:
return visitor.visitPositiveInteger(_content.asInteger);
case VALUE_IS_BOOLEAN:
return visitor.visitBoolean(_content.asInteger != 0);
default:
return visitor.visitNull();
}
}
template <typename T>
T asIntegral() const;
template <typename T>
T asFloat() const;
const char *asString() const;
bool asBoolean() const {
return asIntegral<int>() != 0;
}
CollectionData *asArray() {
if (type() == VALUE_IS_ARRAY)
return &_content.asCollection;
else
return 0;
}
const CollectionData *asArray() const {
return const_cast<VariantData *>(this)->asArray();
}
CollectionData *asObject() {
if (type() == VALUE_IS_OBJECT)
return &_content.asCollection;
else
return 0;
}
const CollectionData *asObject() const {
return const_cast<VariantData *>(this)->asObject();
}
bool copyFrom(const VariantData &src, MemoryPool *pool) {
switch (src.type()) {
case VALUE_IS_ARRAY:
return toArray().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OBJECT:
return toObject().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OWNED_STRING:
return setOwnedString(RamStringWrapper(src._content.asString), pool);
case VALUE_IS_OWNED_RAW:
return setOwnedRaw(
serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
default:
setType(src.type());
_content = src._content;
return true;
}
}
bool equals(const VariantData &other) const {
if (type() != other.type()) return false;
switch (type()) {
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return !strcmp(_content.asString, other._content.asString);
case VALUE_IS_LINKED_RAW:
case VALUE_IS_OWNED_RAW:
return _content.asRaw.size == other._content.asRaw.size &&
!memcmp(_content.asRaw.data, other._content.asRaw.data,
_content.asRaw.size);
case VALUE_IS_BOOLEAN:
case VALUE_IS_POSITIVE_INTEGER:
case VALUE_IS_NEGATIVE_INTEGER:
return _content.asInteger == other._content.asInteger;
case VALUE_IS_ARRAY:
return _content.asCollection.equalsArray(other._content.asCollection);
case VALUE_IS_OBJECT:
return _content.asCollection.equalsObject(other._content.asCollection);
case VALUE_IS_FLOAT:
return _content.asFloat == other._content.asFloat;
case VALUE_IS_NULL:
default:
return true;
}
}
bool isArray() const {
return type() == VALUE_IS_ARRAY;
}
bool isBoolean() const {
return type() == VALUE_IS_BOOLEAN;
}
bool isInteger() const {
return type() == VALUE_IS_POSITIVE_INTEGER ||
type() == VALUE_IS_NEGATIVE_INTEGER;
}
bool isFloat() const {
return type() == VALUE_IS_FLOAT || type() == VALUE_IS_POSITIVE_INTEGER ||
type() == VALUE_IS_NEGATIVE_INTEGER;
}
bool isString() const {
return (type() == VALUE_IS_LINKED_STRING ||
type() == VALUE_IS_OWNED_STRING);
}
bool isObject() const {
return type() == VALUE_IS_OBJECT;
}
bool isNull() const {
return type() == VALUE_IS_NULL;
}
void setBoolean(bool value) {
setType(VALUE_IS_BOOLEAN);
_content.asInteger = static_cast<UInt>(value);
}
void setFloat(Float value) {
setType(VALUE_IS_FLOAT);
_content.asFloat = value;
}
void setLinkedRaw(SerializedValue<const char *> value) {
setType(VALUE_IS_LINKED_RAW);
_content.asRaw.data = value.data();
_content.asRaw.size = value.size();
}
template <typename T>
bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
char *dup = wrapString(value.data(), value.size()).save(pool);
if (dup) {
setType(VALUE_IS_OWNED_RAW);
_content.asRaw.data = dup;
_content.asRaw.size = value.size();
return true;
} else {
setType(VALUE_IS_NULL);
return false;
}
}
template <typename T>
typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
setUnsignedInteger(value);
}
template <typename T>
typename enable_if<is_signed<T>::value>::type setInteger(T value) {
setSignedInteger(value);
}
template <typename T>
void setSignedInteger(T value) {
if (value >= 0) {
setType(VALUE_IS_POSITIVE_INTEGER);
_content.asInteger = static_cast<UInt>(value);
} else {
setType(VALUE_IS_NEGATIVE_INTEGER);
_content.asInteger = ~static_cast<UInt>(value) + 1;
}
}
void setLinkedString(const char *value) {
setType(VALUE_IS_LINKED_STRING);
_content.asString = value;
}
void setNull() {
setType(VALUE_IS_NULL);
}
void setOwnedString(const char *s) {
setType(VALUE_IS_OWNED_STRING);
_content.asString = s;
}
template <typename T>
bool setOwnedString(T value, MemoryPool *pool) {
char *dup = value.save(pool);
if (dup) {
setType(VALUE_IS_OWNED_STRING);
_content.asString = dup;
return true;
} else {
setType(VALUE_IS_NULL);
return false;
}
}
void setUnsignedInteger(UInt value) {
setType(VALUE_IS_POSITIVE_INTEGER);
_content.asInteger = static_cast<UInt>(value);
}
CollectionData &toArray() {
setType(VALUE_IS_ARRAY);
_content.asCollection.clear();
return _content.asCollection;
}
CollectionData &toObject() {
setType(VALUE_IS_OBJECT);
_content.asCollection.clear();
return _content.asCollection;
}
size_t size() const {
if (type() == VALUE_IS_OBJECT || type() == VALUE_IS_ARRAY)
return _content.asCollection.size();
else
return 0;
}
private:
uint8_t type() const {
return _flags & VALUE_MASK;
}
void setType(uint8_t t) {
_flags &= KEY_IS_OWNED;
_flags |= t;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,145 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "VariantData.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename Visitor>
inline void variantAccept(const VariantData *var, Visitor &visitor) {
if (var != 0)
var->accept(visitor);
else
visitor.visitNull();
}
inline const CollectionData *variantAsObject(const VariantData *var) {
return var != 0 ? var->asObject() : 0;
}
inline CollectionData *variantAsObject(VariantData *var) {
return var != 0 ? var->asObject() : 0;
}
inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
MemoryPool *pool) {
if (!dst) return false;
if (!src) {
dst->setNull();
return true;
}
return dst->copyFrom(*src, pool);
}
inline bool variantEquals(const VariantData *a, const VariantData *b) {
if (a == b) return true;
if (!a || !b) return false;
return a->equals(*b);
}
inline bool variantIsArray(const VariantData *var) {
return var && var->isArray();
}
inline bool variantIsBoolean(const VariantData *var) {
return var && var->isBoolean();
}
inline bool variantIsInteger(const VariantData *var) {
return var && var->isInteger();
}
inline bool variantIsFloat(const VariantData *var) {
return var && var->isFloat();
}
inline bool variantIsString(const VariantData *var) {
return var && var->isString();
}
inline bool variantIsObject(const VariantData *var) {
return var && var->isObject();
}
inline bool variantIsNull(const VariantData *var) {
return var == 0 || var->isNull();
}
inline bool variantSetBoolean(VariantData *var, bool value) {
if (!var) return false;
var->setBoolean(value);
return true;
}
inline bool variantSetFloat(VariantData *var, Float value) {
if (!var) return false;
var->setFloat(value);
return true;
}
inline bool variantSetLinkedRaw(VariantData *var,
SerializedValue<const char *> value) {
if (!var) return false;
var->setLinkedRaw(value);
return true;
}
template <typename T>
inline bool variantSetOwnedRaw(VariantData *var, SerializedValue<T> value,
MemoryPool *pool) {
return var != 0 && var->setOwnedRaw(value, pool);
}
template <typename T>
inline bool variantSetSignedInteger(VariantData *var, T value) {
if (!var) return false;
var->setSignedInteger(value);
return true;
}
inline bool variantSetLinkedString(VariantData *var, const char *value) {
if (!var) return false;
var->setLinkedString(value);
return true;
}
inline void variantSetNull(VariantData *var) {
if (!var) return;
var->setNull();
}
inline bool variantSetOwnedString(VariantData *var, char *value) {
if (!var) return false;
var->setOwnedString(value);
return true;
}
template <typename T>
inline bool variantSetOwnedString(VariantData *var, T value, MemoryPool *pool) {
return var != 0 && var->setOwnedString(value, pool);
}
inline bool variantSetUnsignedInteger(VariantData *var, UInt value) {
if (!var) return false;
var->setUnsignedInteger(value);
return true;
}
inline size_t variantSize(const VariantData *var) {
return var != 0 ? var->size() : 0;
}
inline CollectionData *variantToArray(VariantData *var) {
if (!var) return 0;
return &var->toArray();
}
inline CollectionData *variantToObject(VariantData *var) {
if (!var) return 0;
return &var->toObject();
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,123 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Configuration.hpp"
#include "../Numbers/parseFloat.hpp"
#include "../Numbers/parseInteger.hpp"
#include "VariantRef.hpp"
#include <string.h> // for strcmp
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline T VariantData::asIntegral() const {
switch (type()) {
case VALUE_IS_POSITIVE_INTEGER:
case VALUE_IS_BOOLEAN:
return T(_content.asInteger);
case VALUE_IS_NEGATIVE_INTEGER:
return T(~_content.asInteger + 1);
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return parseInteger<T>(_content.asString);
case VALUE_IS_FLOAT:
return T(_content.asFloat);
default:
return 0;
}
}
// T = float/double
template <typename T>
inline T VariantData::asFloat() const {
switch (type()) {
case VALUE_IS_POSITIVE_INTEGER:
case VALUE_IS_BOOLEAN:
return static_cast<T>(_content.asInteger);
case VALUE_IS_NEGATIVE_INTEGER:
return -static_cast<T>(_content.asInteger);
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return parseFloat<T>(_content.asString);
case VALUE_IS_FLOAT:
return static_cast<T>(_content.asFloat);
default:
return 0;
}
}
inline const char* VariantData::asString() const {
switch (type()) {
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return _content.asString;
default:
return 0;
}
}
inline bool VariantRef::set(ArrayRef array) const {
return to<ArrayRef>().copyFrom(array);
}
inline bool VariantRef::set(const ArraySubscript& value) const {
return set(value.as<VariantRef>());
}
inline bool VariantRef::set(ObjectRef object) const {
return to<ObjectRef>().copyFrom(object);
}
template <typename TString>
inline bool VariantRef::set(const ObjectSubscript<TString>& value) const {
return set(value.template as<VariantRef>());
}
inline bool VariantRef::set(VariantConstRef value) const {
return variantCopyFrom(_data, value._data, _pool);
}
inline bool VariantRef::set(VariantRef value) const {
return variantCopyFrom(_data, value._data, _pool);
}
template <typename T>
inline typename enable_if<is_same<T, ArrayRef>::value, T>::type VariantRef::as()
const {
return ArrayRef(_pool, _data != 0 ? _data->asArray() : 0);
}
template <typename T>
inline typename enable_if<is_same<T, ObjectRef>::value, T>::type
VariantRef::as() const {
return ObjectRef(_pool, variantAsObject(_data));
}
template <typename T>
inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type
VariantRef::to() const {
return ArrayRef(_pool, variantToArray(_data));
}
template <typename T>
typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type
VariantRef::to() const {
return ObjectRef(_pool, variantToObject(_data));
}
template <typename T>
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type
VariantRef::to() const {
variantSetNull(_data);
return *this;
}
inline VariantConstRef VariantConstRef::operator[](size_t index) const {
return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index];
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,320 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include "../Memory/MemoryPool.hpp"
#include "../Misc/Visitable.hpp"
#include "../Numbers/parseFloat.hpp"
#include "../Numbers/parseInteger.hpp"
#include "../Operators/VariantOperators.hpp"
#include "../Polyfills/type_traits.hpp"
#include "VariantAs.hpp"
#include "VariantFunctions.hpp"
#include "VariantRef.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Forward declarations.
class ArrayRef;
class ObjectRef;
// Contains the methods shared by VariantRef and VariantConstRef
template <typename TData>
class VariantRefBase {
public:
// Tells wether the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
//
// bool is<char>() const;
// bool is<signed char>() const;
// bool is<signed short>() const;
// bool is<signed int>() const;
// bool is<signed long>() const;
// bool is<unsigned char>() const;
// bool is<unsigned short>() const;
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_integral<T>::value, bool>::type is()
const {
return variantIsInteger(_data);
}
//
// bool is<double>() const;
// bool is<float>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
const {
return variantIsFloat(_data);
}
//
// bool is<bool>() const
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, bool>::value, bool>::type is()
const {
return variantIsBoolean(_data);
}
//
// bool is<const char*>() const;
// bool is<char*>() const;
// bool is<std::string>() const;
// bool is<String>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, const char *>::value ||
is_same<T, char *>::value ||
IsWriteableString<T>::value,
bool>::type
is() const {
return variantIsString(_data);
}
//
// bool is<ArrayRef> const;
// bool is<const ArrayRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ArrayRef>::value, bool>::type
is() const {
return variantIsArray(_data);
}
//
// bool is<ObjectRef> const;
// bool is<const ObjectRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type
is() const {
return variantIsObject(_data);
}
FORCE_INLINE bool isNull() const {
return variantIsNull(_data);
}
size_t size() const {
return variantSize(_data);
}
protected:
VariantRefBase(TData *data) : _data(data) {}
TData *_data;
};
// A variant that can be a any value serializable to a JSON value.
//
// It can be set to:
// - a boolean
// - a char, short, int or a long (signed or unsigned)
// - a string (const char*)
// - a reference to a ArrayRef or ObjectRef
class VariantRef : public VariantRefBase<VariantData>,
public VariantOperators<VariantRef>,
public Visitable {
typedef VariantRefBase<VariantData> base_type;
friend class VariantConstRef;
public:
// Intenal use only
FORCE_INLINE VariantRef(MemoryPool *pool, VariantData *data)
: base_type(data), _pool(pool) {}
// Creates an uninitialized VariantRef
FORCE_INLINE VariantRef() : base_type(0), _pool(0) {}
// set(bool value)
FORCE_INLINE bool set(bool value) const {
return variantSetBoolean(_data, value);
}
// set(double value);
// set(float value);
template <typename T>
FORCE_INLINE bool set(
T value,
typename enable_if<is_floating_point<T>::value>::type * = 0) const {
return variantSetFloat(_data, static_cast<Float>(value));
}
// set(char)
// set(signed short)
// set(signed int)
// set(signed long)
// set(signed char)
template <typename T>
FORCE_INLINE bool set(
T value,
typename enable_if<is_integral<T>::value && is_signed<T>::value>::type * =
0) const {
return variantSetSignedInteger(_data, value);
}
// set(unsigned short)
// set(unsigned int)
// set(unsigned long)
template <typename T>
FORCE_INLINE bool set(
T value, typename enable_if<is_integral<T>::value &&
is_unsigned<T>::value>::type * = 0) const {
return variantSetUnsignedInteger(_data, static_cast<UInt>(value));
}
// set(SerializedValue<const char *>)
FORCE_INLINE bool set(SerializedValue<const char *> value) const {
return variantSetLinkedRaw(_data, value);
}
// set(SerializedValue<std::string>)
// set(SerializedValue<String>)
// set(SerializedValue<const __FlashStringHelper*>)
template <typename T>
FORCE_INLINE bool set(
SerializedValue<T> value,
typename enable_if<!is_same<const char *, T>::value>::type * = 0) const {
return variantSetOwnedRaw(_data, value, _pool);
}
// set(const std::string&)
// set(const String&)
template <typename T>
FORCE_INLINE bool set(
const T &value,
typename enable_if<IsString<T>::value>::type * = 0) const {
return variantSetOwnedString(_data, wrapString(value), _pool);
}
// set(char*)
// set(const __FlashStringHelper*)
template <typename T>
FORCE_INLINE bool set(
T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
return variantSetOwnedString(_data, wrapString(value), _pool);
}
// set(const char*);
FORCE_INLINE bool set(const char *value) const {
return variantSetLinkedString(_data, value);
}
bool set(VariantConstRef value) const;
bool set(VariantRef value) const;
FORCE_INLINE bool set(ArrayRef array) const;
FORCE_INLINE bool set(const ArraySubscript &) const;
FORCE_INLINE bool set(ObjectRef object) const;
template <typename TString>
FORCE_INLINE bool set(const ObjectSubscript<TString> &) const;
// Get the variant as the specified type.
//
// std::string as<std::string>() const;
// String as<String>() const;
template <typename T>
FORCE_INLINE typename enable_if<!is_same<T, ArrayRef>::value &&
!is_same<T, ObjectRef>::value &&
!is_same<T, VariantRef>::value,
typename VariantAs<T>::type>::type
as() const {
return variantAs<T>(_data);
}
//
// ArrayRef as<ArrayRef>() const;
// const ArrayRef as<const ArrayRef>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, ArrayRef>::value, T>::type as()
const;
//
// ObjectRef as<ObjectRef>() const;
// const ObjectRef as<const ObjectRef>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, ObjectRef>::value, T>::type as()
const;
//
// VariantRef as<VariantRef> const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, VariantRef>::value, T>::type as()
const {
return *this;
}
template <typename Visitor>
void accept(Visitor &visitor) const {
variantAccept(_data, visitor);
}
FORCE_INLINE bool operator==(VariantRef lhs) const {
return variantEquals(_data, lhs._data);
}
FORCE_INLINE bool operator!=(VariantRef lhs) const {
return !variantEquals(_data, lhs._data);
}
// Change the type of the variant
//
// ArrayRef to<ArrayRef>()
template <typename T>
typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type to() const;
//
// ObjectRef to<ObjectRef>()
template <typename T>
typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type to() const;
//
// ObjectRef to<VariantRef>()
template <typename T>
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
const;
private:
MemoryPool *_pool;
};
class VariantConstRef : public VariantRefBase<const VariantData>,
public VariantOperators<VariantConstRef>,
public Visitable {
typedef VariantRefBase<const VariantData> base_type;
friend class VariantRef;
public:
VariantConstRef() : base_type(0) {}
VariantConstRef(const VariantData *data) : base_type(data) {}
VariantConstRef(VariantRef var) : base_type(var._data) {}
template <typename Visitor>
void accept(Visitor &visitor) const {
variantAccept(_data, visitor);
}
// Get the variant as the specified type.
//
template <typename T>
FORCE_INLINE typename VariantConstAs<T>::type as() const {
return variantAs<typename VariantConstAs<T>::type>(_data);
}
FORCE_INLINE VariantConstRef operator[](size_t index) const;
//
// const VariantConstRef operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString &key) const {
return VariantConstRef(objectGet(variantAsObject(_data), wrapString(key)));
}
//
// VariantConstRef operator[](TKey);
// TKey = const char*, const char[N], const __FlashStringHelper*
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString *>::value, VariantConstRef>::type
operator[](TString *key) const {
const CollectionData *obj = variantAsObject(_data);
return VariantConstRef(obj ? obj->get(wrapString(key)) : 0);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,95 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Polyfills/type_traits.hpp"
#include "../Variant/VariantContent.hpp"
#include <stdint.h> // int8_t, int16_t
namespace ARDUINOJSON_NAMESPACE {
typedef conditional<sizeof(void*) <= 2, int8_t, int16_t>::type VariantSlotDiff;
class VariantSlot {
// CAUTION: same layout as VariantData
// we cannot use composition because it adds padding
// (+20% on ESP8266 for example)
VariantContent _content;
uint8_t _flags;
VariantSlotDiff _next;
const char* _key;
public:
// Must be a POD!
// - no constructor
// - no destructor
// - no virtual
// - no inheritance
VariantData* data() {
return reinterpret_cast<VariantData*>(&_content);
}
const VariantData* data() const {
return reinterpret_cast<const VariantData*>(&_content);
}
VariantSlot* next() {
return _next ? this + _next : 0;
}
const VariantSlot* next() const {
return const_cast<VariantSlot*>(this)->next();
}
VariantSlot* next(size_t distance) {
VariantSlot* slot = this;
while (distance--) {
if (!slot->_next) return 0;
slot += slot->_next;
}
return slot;
}
const VariantSlot* next(size_t distance) const {
return const_cast<VariantSlot*>(this)->next(distance);
}
void setNext(VariantSlot* slot) {
_next = VariantSlotDiff(slot ? slot - this : 0);
}
void setNextNotNull(VariantSlot* slot) {
ARDUINOJSON_ASSERT(slot != 0);
_next = VariantSlotDiff(slot - this);
}
void setOwnedKey(const char* k) {
_flags |= KEY_IS_OWNED;
_key = k;
}
void setLinkedKey(const char* k) {
_flags &= VALUE_MASK;
_key = k;
}
const char* key() const {
return _key;
}
bool ownsKey() const {
return (_flags & KEY_IS_OWNED) != 0;
}
void clear() {
_next = 0;
_flags = 0;
_key = 0;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -5,26 +5,26 @@
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class JsonArray;
class JsonObject;
class JsonVariant;
class ArrayRef;
class ObjectRef;
class VariantRef;
// A metafunction that returns the type of the value returned by
// JsonVariant::to<T>()
// VariantRef::to<T>()
template <typename T>
struct JsonVariantTo {};
struct VariantTo {};
template <>
struct JsonVariantTo<JsonArray> {
typedef JsonArray type;
struct VariantTo<ArrayRef> {
typedef ArrayRef type;
};
template <>
struct JsonVariantTo<JsonObject> {
typedef JsonObject type;
struct VariantTo<ObjectRef> {
typedef ObjectRef type;
};
template <>
struct JsonVariantTo<JsonVariant> {
typedef JsonVariant type;
struct VariantTo<VariantRef> {
typedef VariantRef type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,7 +4,7 @@
#pragma once
#define ARDUINOJSON_VERSION "6.6.0-beta"
#define ARDUINOJSON_VERSION "6.7.0-beta"
#define ARDUINOJSON_VERSION_MAJOR 6
#define ARDUINOJSON_VERSION_MINOR 6
#define ARDUINOJSON_VERSION_MINOR 7
#define ARDUINOJSON_VERSION_REVISION 0

View File

@ -71,7 +71,6 @@ if(MSVC)
)
endif()
add_subdirectory(DynamicMemoryPool)
add_subdirectory(IntegrationTests)
add_subdirectory(JsonArray)
add_subdirectory(JsonDeserializer)
@ -80,9 +79,9 @@ add_subdirectory(JsonObject)
add_subdirectory(JsonSerializer)
add_subdirectory(JsonVariant)
add_subdirectory(JsonWriter)
add_subdirectory(MemoryPool)
add_subdirectory(Misc)
add_subdirectory(MixedConfiguration)
add_subdirectory(MsgPackDeserializer)
add_subdirectory(MsgPackSerializer)
add_subdirectory(Numbers)
add_subdirectory(StaticMemoryPool)
add_subdirectory(MixedConfiguration)

View File

@ -1,16 +0,0 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2018
# MIT License
add_executable(DynamicMemoryPoolTests
allocString.cpp
allocVariant.cpp
blocks.cpp
clear.cpp
no_memory.cpp
size.cpp
StringBuilder.cpp
)
target_link_libraries(DynamicMemoryPoolTests catch)
add_test(DynamicMemoryPool DynamicMemoryPoolTests)

Some files were not shown because too many files have changed in this diff Show More