Compare commits

..

32 Commits

Author SHA1 Message Date
9f1421e0a6 Set version to 6.5.0-beta 2018-10-13 13:23:34 +02:00
84f199f0dd Added copy-constructor and copy-assignment-operator for JsonDocument (issue #827) 2018-10-13 13:21:30 +02:00
8230f8fc9b Restored JsonVariantLocal to fix the use-after-free 2018-10-12 20:00:49 +01:00
02d809f3f4 Added Visitable to reduce the number of definitions of operator<< 2018-10-12 17:59:50 +02:00
b0560cbd99 Added JsonArrayConst, JsonObjectConst, and JsonVariantConst 2018-10-12 12:00:27 +02:00
d1003ff6c9 Simplified string handling in JsonObject 2018-10-10 09:18:36 +02:00
b11ad4077b Merge branch 'master' into 6.x 2018-10-09 15:00:49 +02:00
5dc7dc1216 Increased the default capacity of DynamicJsonDocument 2018-10-08 18:32:58 +02:00
0d4a93018b Set version to 5.13.3 2018-10-06 17:50:41 +02:00
3ca40db9f8 Added a coupon code for the book 2018-10-06 17:42:01 +02:00
ce607196d1 Travis: update osx images 2018-10-06 17:24:54 +02:00
0b3af166ae Fixed JsonVariant::is<String>() (closes #763) 2018-10-06 17:21:16 +02:00
39e5660c4a Extracted a base class for JsonDocument 2018-10-04 14:59:07 +02:00
6b985b2d1f Fixed object keys not being duplicated 2018-10-04 11:16:23 +02:00
527dc19794 Allow mixed configuration in compilation units (issue #809) 2018-10-02 16:54:05 +02:00
29e71cbb16 Added implicit conversion from JsonArray and JsonObject to JsonVariant 2018-10-01 12:55:40 +02:00
2d54019f83 Set version to 6.4.0-beta 2018-09-11 16:31:04 +02:00
98c8e8e35a Added a test for issue #808 2018-09-11 16:21:30 +02:00
b106b1ed14 Copy JsonArray and JsonObject, instead of storing pointers (fixes #780) 2018-09-11 16:06:08 +02:00
2998a55f0b Renamed JsonBuffer to MemoryPool 2018-09-03 16:14:21 +02:00
e5c4778ff7 Updated publish script 2018-08-31 17:04:22 +02:00
2ec9569b36 Set version to 6.3.0-beta 2018-08-31 16:57:14 +02:00
58303d0837 Added date in change log 2018-08-31 16:38:42 +02:00
e3639918eb Reduced executable size 2018-08-31 16:29:08 +02:00
6d290bd001 Fixed duplication of char* 2018-08-22 14:37:17 +02:00
7683667b3c Fixed serializeJson(obj[key], dst) (closes #794) 2018-08-21 18:07:41 +02:00
9cbc891816 Implemented reference semantics for JsonVariant 2018-08-21 17:56:16 +02:00
0454bd1ef6 Set version to 6.2.3-beta 2018-07-19 18:28:03 +02:00
f139100b23 Added a script to update the version number 2018-07-19 18:27:44 +02:00
3f666bd5f0 Fixed exception when using Flash strings as object keys (fixes #784) 2018-07-19 17:22:28 +02:00
fa1a40ac6e Fixed JsonVariant::is<int>() that returned true for empty strings 2018-07-05 09:53:11 +02:00
954428e341 Improved float serialization when -fsingle-precision-constant is used 2018-07-05 09:48:57 +02:00
205 changed files with 5167 additions and 3459 deletions

View File

@ -97,11 +97,19 @@ matrix:
- compiler: gcc
env: SCRIPT=coverage
- os: osx
osx_image: xcode6.4
osx_image: xcode7.3
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode7.3
osx_image: xcode8.3
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode9.4
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode10
compiler: clang
env: SCRIPT=cmake SANITIZE=address
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno

View File

@ -1,21 +1,96 @@
ArduinoJson: change log
=======================
v6.2.2-beta
v6.5.0-beta (2018-10-13)
-----------
* Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant`
* Allow mixed configuration in compilation units (issue #809)
* Fixed object keys not being duplicated
* `JsonPair::key()` now returns a `JsonKey`
* Increased the default capacity of `DynamicJsonDocument`
* Fixed `JsonVariant::is<String>()` (closes #763)
* Added `JsonArrayConst`, `JsonObjectConst`, and `JsonVariantConst`
* Added copy-constructor and copy-assignment-operator for `JsonDocument` (issue #827)
v6.4.0-beta (2018-09-11)
-----------
* Copy `JsonArray` and `JsonObject`, instead of storing pointers (issue #780)
* Added `JsonVariant::to<JsonArray>()` and `JsonVariant::to<JsonObject>()`
v6.3.0-beta (2018-08-31)
-----------
* Implemented reference semantics for `JsonVariant`
* Replaced `JsonPair`'s `key` and `value` with `key()` and `value()`
* Fixed `serializeJson(obj[key], dst)` (issue #794)
> ### BREAKING CHANGES
>
> #### JsonVariant
>
> `JsonVariant` now has a semantic similar to `JsonObject` and `JsonArray`.
> It's a reference to a value stored in the `JsonDocument`.
> As a consequence, a `JsonVariant` cannot be used as a standalone variable anymore.
>
> Old code:
>
> ```c++
> JsonVariant myValue = 42;
> ```
>
> New code:
>
> ```c++
> DynamicJsonDocument doc;
> JsonVariant myValue = doc.to<JsonVariant>();
> myValue.set(42);
> ```
>
> #### JsonPair
>
> Old code:
>
> ```c++
> for(JsonPair p : myObject) {
> Serial.println(p.key);
> Serial.println(p.value.as<int>());
> }
> ```
>
> New code:
>
> ```c++
> for(JsonPair p : myObject) {
> Serial.println(p.key());
> Serial.println(p.value().as<int>());
> }
> ```
>
> CAUTION: the key is now read only!
v6.2.3-beta (2018-07-19)
-----------
* Fixed exception when using Flash strings as object keys (issue #784)
v6.2.2-beta (2018-07-18)
-----------
* Fixed `invalid application of 'sizeof' to incomplete type '__FlashStringHelper'` (issue #783)
* Fixed `char[]` not duplicated when passed to `JsonVariant::operator[]`
v6.2.1-beta
v6.2.1-beta (2018-07-17)
-----------
* Fixed `JsonObject` not inserting keys of type `String` (issue #782)
v6.2.0-beta
v6.2.0-beta (2018-07-12)
-----------
* Disabled lazy number deserialization (issue #772)
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
* Improved float serialization when `-fsingle-precision-constant` is used
* Renamed function `RawJson()` to `serialized()`
* `serializeMsgPack()` now supports values marked with `serialized()`
@ -41,7 +116,7 @@ v6.2.0-beta
> object["values"] = serialized("[1,2,3,4]");
> ```
v6.1.0-beta
v6.1.0-beta (2018-07-02)
-----------
* Return `JsonArray` and `JsonObject` by value instead of reference (issue #309)
@ -71,12 +146,12 @@ v6.1.0-beta
> }
> ```
v6.0.1-beta
v6.0.1-beta (2018-06-11)
-----------
* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752)
v6.0.0-beta
v6.0.0-beta (2018-06-07)
-----------
* Added `DynamicJsonDocument` and `StaticJsonDocument`

View File

@ -1,4 +1,4 @@
version: 6.0.1.{build}
version: 6.4.0.{build}
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017

View File

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

View File

@ -1,5 +1,5 @@
name=ArduinoJson
version=6.2.2-beta
version=6.5.0-beta
author=Benoit Blanchon <blog.benoitblanchon.fr>
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
sentence=An efficient and elegant JSON library for Arduino.

49
scripts/publish.sh Normal file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env bash
set -eu
cd "$(dirname "$0")/.."
VERSION="$1"
DATE=$(date +%F)
TAG="v$VERSION"
update_version_in_source () {
IFS=".-" read MAJOR MINOR REVISION EXTRA < <(echo "$VERSION")
UNDERLINE=$(printf -- '-%.0s' $(seq 1 ${#TAG}))
sed -i~ -bE "4s/HEAD/$TAG ($DATE)/; 5s/-+/$UNDERLINE/" CHANGELOG.md
rm CHANGELOG.md*~
sed -i~ -bE "s/\"version\":.*$/\"version\": \"$VERSION\",/" library.json
rm library.json*~
sed -i~ -bE "s/version=.*$/version=$VERSION/" library.properties
rm library.properties*~
sed -i~ -bE \
-e "s/ARDUINOJSON_VERSION .*$/ARDUINOJSON_VERSION \"$VERSION\"/" \
-e "s/ARDUINOJSON_VERSION_MAJOR .*$/ARDUINOJSON_VERSION_MAJOR $MAJOR/" \
-e "s/ARDUINOJSON_VERSION_MINOR .*$/ARDUINOJSON_VERSION_MINOR $MINOR/" \
-e "s/ARDUINOJSON_VERSION_REVISION .*$/ARDUINOJSON_VERSION_REVISION $REVISION/" \
src/ArduinoJson/version.hpp
rm src/ArduinoJson/version.hpp*~
}
commit_new_version () {
git add src/ArduinoJson/version.hpp CHANGELOG.md library.json library.properties
git commit -m "Set version to $VERSION"
}
add_tag () {
CHANGES=$(awk '/\* /{ FOUND=1; print; next } { if (FOUND) exit}' CHANGELOG.md)
git tag -m "ArduinoJson $VERSION"$'\n'"$CHANGES" "$TAG"
}
push () {
git push --follow-tags
}
update_version_in_source
commit_new_version
add_tag
push

View File

@ -4,18 +4,17 @@
#pragma once
#include "ArduinoJson/version.hpp"
#include "ArduinoJson/DynamicJsonDocument.hpp"
#include "ArduinoJson/StaticJsonDocument.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/Namespace.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonDocument.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/JsonVariant.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"
@ -24,3 +23,21 @@
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
namespace ArduinoJson {
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

@ -4,6 +4,18 @@
#pragma once
#if defined(_MSC_VER)
#define ARDUINOJSON_HAS_INT64 1
#else
#define ARDUINOJSON_HAS_INT64 0
#endif
#if __cplusplus >= 201103L
#define ARDUINOJSON_HAS_LONG_LONG 1
#else
#define ARDUINOJSON_HAS_LONG_LONG 0
#endif
// Small or big machine?
#ifndef ARDUINOJSON_EMBEDDED_MODE
#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
@ -25,9 +37,6 @@
#ifndef ARDUINOJSON_USE_LONG_LONG
#define ARDUINOJSON_USE_LONG_LONG 0
#endif
#ifndef ARDUINOJSON_USE_INT64
#define ARDUINOJSON_USE_INT64 0
#endif
// Embedded systems usually don't have std::string
#ifndef ARDUINOJSON_ENABLE_STD_STRING
@ -44,6 +53,11 @@
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
#endif
// Default capacity for DynamicJsonDocument
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
#define ARDUINOJSON_DEFAULT_POOL_SIZE 1024
#endif
#else // ARDUINOJSON_EMBEDDED_MODE
// On a computer we have plenty of memory so we can use doubles
@ -53,22 +67,13 @@
// Use long long when available
#ifndef ARDUINOJSON_USE_LONG_LONG
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64
#define ARDUINOJSON_USE_LONG_LONG 1
#else
#define ARDUINOJSON_USE_LONG_LONG 0
#endif
#endif
// Use _int64 on old versions of Visual Studio
#ifndef ARDUINOJSON_USE_INT64
#if defined(_MSC_VER) && _MSC_VER <= 1700
#define ARDUINOJSON_USE_INT64 1
#else
#define ARDUINOJSON_USE_INT64 0
#endif
#endif
// On a computer, we can use std::string
#ifndef ARDUINOJSON_ENABLE_STD_STRING
#define ARDUINOJSON_ENABLE_STD_STRING 1
@ -84,6 +89,11 @@
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
#endif
// Default capacity for DynamicJsonDocument
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
#define ARDUINOJSON_DEFAULT_POOL_SIZE 16384
#endif
#endif // ARDUINOJSON_EMBEDDED_MODE
#ifdef ARDUINO
@ -141,10 +151,6 @@
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
#endif
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
#endif
#ifndef ARDUINOJSON_LITTLE_ENDIAN
#if defined(_MSC_VER) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \

View File

@ -0,0 +1,99 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariantData.hpp"
#include "Slot.hpp"
#include "SlotFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline JsonVariantData* arrayAdd(JsonArrayData* arr, MemoryPool* pool) {
if (!arr) return 0;
Slot* slot = new (pool) Slot();
if (!slot) return 0;
slot->next = 0;
if (arr->tail) {
slot->prev = arr->tail;
arr->tail->next = slot;
arr->tail = slot;
} else {
slot->prev = 0;
arr->head = slot;
arr->tail = slot;
}
return &slot->value;
}
inline Slot* arrayGetSlot(const JsonArrayData* arr, size_t index) {
if (!arr) return 0;
return slotAdvance(arr->head, index);
}
inline JsonVariantData* arrayGet(const JsonArrayData* arr, size_t index) {
Slot* slot = arrayGetSlot(arr, index);
return slot ? &slot->value : 0;
}
inline void arrayRemove(JsonArrayData* arr, Slot* slot) {
if (!arr || !slot) return;
if (slot->prev)
slot->prev->next = slot->next;
else
arr->head = slot->next;
if (slot->next)
slot->next->prev = slot->prev;
else
arr->tail = slot->prev;
}
inline void arrayRemove(JsonArrayData* arr, size_t index) {
arrayRemove(arr, arrayGetSlot(arr, index));
}
inline void arrayClear(JsonArrayData* arr) {
if (!arr) return;
arr->head = 0;
arr->tail = 0;
}
bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
inline bool arrayCopy(JsonArrayData* dst, const JsonArrayData* src,
MemoryPool* pool) {
if (!dst || !src) return false;
arrayClear(dst);
for (Slot* s = src->head; s; s = s->next) {
if (!variantCopy(arrayAdd(dst, pool), &s->value, pool)) return false;
}
return true;
}
bool variantEquals(const JsonVariantData*, const JsonVariantData*);
inline bool arrayEquals(const JsonArrayData* a1, const JsonArrayData* a2) {
if (a1 == a2) return true;
if (!a1 || !a2) return false;
Slot* s1 = a1->head;
Slot* s2 = a2->head;
for (;;) {
if (s1 == s2) return true;
if (!s1 || !s2) return false;
if (!variantEquals(&s1->value, &s2->value)) return false;
s1 = s1->next;
s2 = s2->next;
}
}
inline size_t arraySize(const JsonArrayData* arr) {
if (!arr) return 0;
return slotSize(arr->head);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,17 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Polyfills/type_traits.hpp"
namespace ArduinoJson {
namespace Internals {
class JsonVariantTag {};
template <typename T>
struct IsVariant : is_base_of<JsonVariantTag, T> {};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -6,13 +6,11 @@
#include "../Configuration.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_USE_DOUBLE
typedef double JsonFloat;
#else
typedef float JsonFloat;
#endif
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,18 +6,15 @@
#include "../Configuration.hpp"
namespace ArduinoJson {
namespace Internals {
#include <stdint.h> // int64_t
namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_USE_LONG_LONG
typedef long long JsonInteger;
typedef unsigned long long JsonUInt;
#elif ARDUINOJSON_USE_INT64
typedef __int64 JsonInteger;
typedef unsigned _int64 JsonUInt;
typedef int64_t JsonInteger;
typedef uint64_t JsonUInt;
#else
typedef long JsonInteger;
typedef unsigned long JsonUInt;
#endif
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,14 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
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>()
@ -19,5 +25,25 @@ struct JsonVariantAs<char*> {
typedef const char* type;
};
} // namespace Internals
} // namespace ArduinoJson
// 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,30 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"
namespace ArduinoJson {
namespace Internals {
// Forward declarations
struct JsonArrayData;
struct JsonObjectData;
// A union that defines the actual content of a JsonVariant.
// The enum JsonVariantType determines which member is in use.
union JsonVariantContent {
JsonFloat asFloat; // used for double and float
JsonUInt asInteger; // used for bool, char, short, int and longs
JsonArrayData* asArray; // asArray cannot be null
JsonObjectData* asObject; // asObject cannot be null
const char* asString; // asString can be null
struct {
const char* data;
size_t size;
} asRaw;
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -0,0 +1,79 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h> // ptrdiff_t, size_t
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"
namespace ARDUINOJSON_NAMESPACE {
enum JsonVariantType {
JSON_NULL,
JSON_LINKED_RAW,
JSON_OWNED_RAW,
JSON_LINKED_STRING,
JSON_OWNED_STRING,
JSON_BOOLEAN,
JSON_POSITIVE_INTEGER,
JSON_NEGATIVE_INTEGER,
JSON_ARRAY,
JSON_OBJECT,
JSON_FLOAT
};
struct JsonObjectData {
struct Slot *head;
struct Slot *tail;
};
struct JsonArrayData {
struct Slot *head;
struct Slot *tail;
};
struct RawData {
const char *data;
size_t size;
};
// A union that defines the actual content of a JsonVariantData.
// The enum JsonVariantType determines which member is in use.
union JsonVariantContent {
JsonFloat asFloat;
JsonUInt asInteger;
JsonArrayData asArray;
JsonObjectData asObject;
const char *asString;
struct {
const char *data;
size_t size;
} asRaw;
};
// this struct must be a POD type to prevent error calling offsetof on clang
struct JsonVariantData {
bool keyIsStatic : 1;
JsonVariantType type : 7;
JsonVariantContent content;
};
inline JsonVariantData *getVariantData(JsonArrayData *arr) {
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
offsetof(JsonVariantContent, asArray);
if (!arr) return 0;
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(arr) -
offset);
}
inline JsonVariantData *getVariantData(JsonObjectData *obj) {
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
offsetof(JsonVariantContent, asObject);
if (!obj) return 0;
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(obj) -
offset);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,23 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
template <typename T>
struct JsonVariantDefault {
static T get() {
return T();
}
};
template <typename T>
struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
template <typename T>
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
}
}

View File

@ -0,0 +1,30 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class JsonArray;
class JsonObject;
class JsonVariant;
// A metafunction that returns the type of the value returned by
// JsonVariant::to<T>()
template <typename T>
struct JsonVariantTo {};
template <>
struct JsonVariantTo<JsonArray> {
typedef JsonArray type;
};
template <>
struct JsonVariantTo<JsonObject> {
typedef JsonObject type;
};
template <>
struct JsonVariantTo<JsonVariant> {
typedef JsonVariant type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,25 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
// Enumerated type to know the current type of a JsonVariant.
// The value determines which member of JsonVariantContent is used.
enum JsonVariantType {
JSON_UNDEFINED, // JsonVariant has not been initialized
JSON_UNPARSED, // JsonVariant contains an unparsed string
JSON_STRING, // JsonVariant stores a const char*
JSON_BOOLEAN, // JsonVariant stores a bool
JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt
JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArrayData
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObjectData
JSON_FLOAT // JsonVariant stores a JsonFloat
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,88 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Memory/JsonBuffer.hpp"
#include "ListConstIterator.hpp"
#include "ListIterator.hpp"
namespace ArduinoJson {
namespace Internals {
// A singly linked list of T.
// The linked list is composed of ListNode<T>.
// It is derived by JsonArrayData and JsonObjectData
template <typename T>
class List {
public:
typedef T value_type;
typedef ListNode<T> node_type;
typedef ListIterator<T> iterator;
typedef ListConstIterator<T> const_iterator;
explicit List(JsonBuffer *buf) : _buffer(buf), _firstNode(NULL) {}
// Returns the numbers of elements in the list.
// For a JsonObjectData, it would return the number of key-value pairs
size_t size() const {
size_t nodeCount = 0;
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
return nodeCount;
}
iterator add() {
node_type *newNode = new (_buffer) node_type();
if (_firstNode) {
node_type *lastNode = _firstNode;
while (lastNode->next) lastNode = lastNode->next;
lastNode->next = newNode;
} else {
_firstNode = newNode;
}
return iterator(newNode);
}
iterator begin() {
return iterator(_firstNode);
}
iterator end() {
return iterator(NULL);
}
const_iterator begin() const {
return const_iterator(_firstNode);
}
const_iterator end() const {
return const_iterator(NULL);
}
void remove(iterator it) {
node_type *nodeToRemove = it._node;
if (!nodeToRemove) return;
if (nodeToRemove == _firstNode) {
_firstNode = nodeToRemove->next;
} else {
for (node_type *node = _firstNode; node; node = node->next)
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
}
}
JsonBuffer &buffer() const {
return *_buffer;
}
JsonBuffer *_buffer; // TODO!!
protected:
void clear() {
_firstNode = 0;
}
private:
node_type *_firstNode;
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,50 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "ListNode.hpp"
namespace ArduinoJson {
namespace Internals {
// A read-only forward itertor for List<T>
template <typename T>
class ListConstIterator {
public:
explicit ListConstIterator(const ListNode<T> *node = NULL) : _node(node) {}
const T &operator*() const {
return _node->content;
}
const T *operator->() {
return &_node->content;
}
bool operator==(const ListConstIterator<T> &other) const {
return _node == other._node;
}
bool operator!=(const ListConstIterator<T> &other) const {
return _node != other._node;
}
ListConstIterator<T> &operator++() {
if (_node) _node = _node->next;
return *this;
}
ListConstIterator<T> &operator+=(size_t distance) {
while (_node && distance) {
_node = _node->next;
--distance;
}
return *this;
}
private:
const ListNode<T> *_node;
};
}
}

View File

@ -1,60 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "ListConstIterator.hpp"
#include "ListNode.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename T>
class List;
// A read-write forward iterator for List<T>
template <typename T>
class ListIterator {
friend class List<T>;
public:
explicit ListIterator(ListNode<T> *node = NULL) : _node(node) {}
T &operator*() const {
return _node->content;
}
T *operator->() {
return &_node->content;
}
bool operator==(const ListIterator<T> &other) const {
return _node == other._node;
}
bool operator!=(const ListIterator<T> &other) const {
return _node != other._node;
}
ListIterator<T> &operator++() {
if (_node) _node = _node->next;
return *this;
}
ListIterator<T> &operator+=(size_t distance) {
while (_node && distance) {
_node = _node->next;
--distance;
}
return *this;
}
operator ListConstIterator<T>() const {
return ListConstIterator<T>(_node);
}
private:
ListNode<T> *_node;
};
}
}

View File

@ -1,24 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h> // for NULL
#include "../Memory/JsonBufferAllocated.hpp"
namespace ArduinoJson {
namespace Internals {
// A node for a singly-linked list.
// Used by List<T> and its iterators.
template <typename T>
struct ListNode : public Internals::JsonBufferAllocated {
ListNode() throw() : next(NULL) {}
ListNode<T> *next;
T content;
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -0,0 +1,123 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariantData.hpp"
#include "SlotFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline Slot* objectFindSlot(const JsonObjectData* obj, TKey key) {
if (!obj) return 0;
Slot* slot = obj->head;
while (slot) {
if (key.equals(slot->key)) break;
slot = slot->next;
}
return slot;
}
template <typename TKey>
inline bool objectContainsKey(const JsonObjectData* obj, const TKey& key) {
return objectFindSlot(obj, key) != 0;
}
template <typename TKey>
inline JsonVariantData* objectAdd(JsonObjectData* obj, TKey key,
MemoryPool* pool) {
Slot* slot = new (pool) Slot();
if (!slot) return 0;
slot->next = 0;
if (obj->tail) {
slot->prev = obj->tail;
obj->tail->next = slot;
obj->tail = slot;
} else {
slot->prev = 0;
obj->head = slot;
obj->tail = slot;
}
if (!slotSetKey(slot, key, pool)) return 0;
return &slot->value;
}
template <typename TKey>
inline JsonVariantData* objectSet(JsonObjectData* obj, TKey key,
MemoryPool* pool) {
if (!obj) return 0;
// ignore null key
if (key.isNull()) return 0;
// search a matching key
Slot* slot = objectFindSlot(obj, key);
if (slot) return &slot->value;
return objectAdd(obj, key, pool);
}
template <typename TKey>
inline JsonVariantData* objectGet(const JsonObjectData* obj, TKey key) {
Slot* slot = objectFindSlot(obj, key);
return slot ? &slot->value : 0;
}
inline void objectClear(JsonObjectData* obj) {
if (!obj) return;
obj->head = 0;
obj->tail = 0;
}
inline void objectRemove(JsonObjectData* obj, Slot* slot) {
if (!obj) return;
if (!slot) return;
if (slot->prev)
slot->prev->next = slot->next;
else
obj->head = slot->next;
if (slot->next)
slot->next->prev = slot->prev;
else
obj->tail = slot->prev;
}
inline size_t objectSize(const JsonObjectData* obj) {
if (!obj) return 0;
return slotSize(obj->head);
}
// bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
inline bool objectCopy(JsonObjectData* dst, const JsonObjectData* src,
MemoryPool* pool) {
if (!dst || !src) return false;
objectClear(dst);
for (Slot* s = src->head; s; s = s->next) {
JsonVariantData* var;
if (s->value.keyIsStatic)
var = objectAdd(dst, ZeroTerminatedRamStringConst(s->key), pool);
else
var = objectAdd(dst, ZeroTerminatedRamString(s->key), pool);
if (!variantCopy(var, &s->value, pool)) return false;
}
return true;
}
inline bool objectEquals(const JsonObjectData* o1, const JsonObjectData* o2) {
if (o1 == o2) return true;
if (!o1 || !o2) return false;
for (Slot* s = o1->head; s; s = s->next) {
JsonVariantData* v1 = &s->value;
JsonVariantData* v2 = objectGet(o2, makeString(s->key));
if (!variantEquals(v1, v2)) return false;
}
return true;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,19 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Memory/AllocableInMemoryPool.hpp"
#include "JsonVariantData.hpp"
namespace ARDUINOJSON_NAMESPACE {
struct Slot : AllocableInMemoryPool {
JsonVariantData value;
struct Slot* next;
struct Slot* prev;
const char* key;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,59 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Strings/StringTypes.hpp"
#include "JsonVariantData.hpp"
#include "Slot.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline bool slotSetKey(Slot* slot, TKey key, MemoryPool* pool) {
const char* dup = key.save(pool);
if (!dup) return false;
slot->key = dup;
slot->value.keyIsStatic = false;
return true;
}
inline bool slotSetKey(Slot* slot, ZeroTerminatedRamStringConst key,
MemoryPool* pool) {
slot->key = key.save(pool);
slot->value.keyIsStatic = true;
return true;
}
inline bool slotSetKey(Slot* slot, StringInMemoryPool key, MemoryPool* pool) {
slot->key = key.save(pool);
slot->value.keyIsStatic = false;
return true;
}
inline const Slot* slotAdvance(const Slot* slot, size_t distance) {
while (distance && slot) {
slot = slot->next;
distance--;
}
return slot;
}
inline Slot* slotAdvance(Slot* slot, size_t distance) {
while (distance && slot) {
slot = slot->next;
distance--;
}
return slot;
}
inline size_t slotSize(const Slot* slot) {
size_t n = 0;
while (slot) {
n++;
slot = slot->next;
}
return n;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,53 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../JsonVariant.hpp"
#include "../Memory/JsonBuffer.hpp"
#include "../Polyfills/type_traits.hpp"
#include "../Strings/StringTypes.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename Source, typename Enable = void>
struct ValueSaver {
template <typename Destination>
static bool save(JsonBuffer*, Destination& destination, Source source) {
destination = source;
return true;
}
};
// We duplicate all strings except const char*
template <typename TString>
struct ValueSaver<
TString, typename enable_if<IsString<TString>::value &&
!is_same<const char*, TString>::value>::type> {
template <typename Destination>
static bool save(JsonBuffer* buffer, Destination& dest, TString source) {
const char* dup = makeString(source).save(buffer);
if (!dup) return false;
dest = dup;
return true;
}
};
// We duplicate all SerializedValue<T> except SerializedValue<const char*>
template <typename TString>
struct ValueSaver<
const SerializedValue<TString>&,
typename enable_if<!is_same<const char*, TString>::value>::type> {
template <typename Destination>
static bool save(JsonBuffer* buffer, Destination& dest,
const SerializedValue<TString>& source) {
const char* dup = makeString(source.data(), source.size()).save(buffer);
if (!dup) return false;
dest = SerializedValue<const char*>(dup, source.size());
return true;
}
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -0,0 +1,48 @@
// 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

@ -0,0 +1,29 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../JsonVariant.hpp"
#include "../Serialization/DynamicStringWriter.hpp"
#include "VariantFunctions.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);
}
template <typename T>
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
const JsonVariantData* _data) {
const char* cstr = variantAsString(_data);
if (cstr) return T(cstr);
T s;
serializeJson(JsonVariantConst(_data), s);
return s;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,287 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Numbers/parseFloat.hpp"
#include "../Numbers/parseInteger.hpp"
#include "../SerializedValue.hpp"
#include "ArrayFunctions.hpp"
#include "JsonVariantData.hpp"
#include "ObjectFunctions.hpp"
#include "Slot.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline T variantAsIntegral(const JsonVariantData* var) {
if (!var) return 0;
switch (var->type) {
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return T(var->content.asInteger);
case JSON_NEGATIVE_INTEGER:
return T(~var->content.asInteger + 1);
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return parseInteger<T>(var->content.asString);
case JSON_FLOAT:
return T(var->content.asFloat);
default:
return 0;
}
}
inline bool variantAsBoolean(const JsonVariantData* var) {
return variantAsIntegral<int>(var) != 0;
}
// T = float/double
template <typename T>
inline T variantAsFloat(const JsonVariantData* var) {
if (!var) return 0;
switch (var->type) {
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return static_cast<T>(var->content.asInteger);
case JSON_NEGATIVE_INTEGER:
return -static_cast<T>(var->content.asInteger);
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return parseFloat<T>(var->content.asString);
case JSON_FLOAT:
return static_cast<T>(var->content.asFloat);
default:
return 0;
}
}
inline const char* variantAsString(const JsonVariantData* var) {
if (!var) return 0;
if (var &&
(var->type == JSON_LINKED_STRING || var->type == JSON_OWNED_STRING))
return var->content.asString;
else
return 0;
}
inline JsonArrayData* variantAsArray(JsonVariantData* var) {
if (var && var->type == JSON_ARRAY)
return &var->content.asArray;
else
return 0;
}
inline const JsonArrayData* variantAsArray(const JsonVariantData* var) {
if (var && var->type == JSON_ARRAY)
return &var->content.asArray;
else
return 0;
}
inline JsonObjectData* variantAsObject(JsonVariantData* var) {
if (var && var->type == JSON_OBJECT)
return &var->content.asObject;
else
return 0;
}
inline const JsonObjectData* variantAsObject(const JsonVariantData* var) {
if (var && var->type == JSON_OBJECT)
return &var->content.asObject;
else
return 0;
}
inline bool variantSetBoolean(JsonVariantData* var, bool value) {
if (!var) return false;
var->type = JSON_BOOLEAN;
var->content.asInteger = static_cast<JsonUInt>(value);
return true;
}
inline bool variantSetFloat(JsonVariantData* var, JsonFloat value) {
if (!var) return false;
var->type = JSON_FLOAT;
var->content.asFloat = value;
return true;
}
template <typename T>
inline bool variantSetSignedInteger(JsonVariantData* var, T value) {
if (!var) return false;
if (value >= 0) {
var->type = JSON_POSITIVE_INTEGER;
var->content.asInteger = static_cast<JsonUInt>(value);
} else {
var->type = JSON_NEGATIVE_INTEGER;
var->content.asInteger = ~static_cast<JsonUInt>(value) + 1;
}
return true;
}
inline bool variantSetSignedInteger(JsonVariantData* var, JsonUInt value) {
if (!var) return false;
var->type = JSON_POSITIVE_INTEGER;
var->content.asInteger = static_cast<JsonUInt>(value);
return true;
}
inline bool variantSetLinkedRaw(JsonVariantData* var,
SerializedValue<const char*> value) {
if (!var) return false;
var->type = JSON_LINKED_RAW;
var->content.asRaw.data = value.data();
var->content.asRaw.size = value.size();
return true;
}
template <typename T>
inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value,
MemoryPool* pool) {
if (!var) return false;
const char* dup = makeString(value.data(), value.size()).save(pool);
if (dup) {
var->type = JSON_OWNED_RAW;
var->content.asRaw.data = dup;
var->content.asRaw.size = value.size();
return true;
} else {
var->type = JSON_NULL;
return false;
}
}
template <typename T>
inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) {
if (!var) return false;
const char* dup = value.save(pool);
if (dup) {
var->type = JSON_OWNED_STRING;
var->content.asString = dup;
return true;
} else {
var->type = JSON_NULL;
return false;
}
}
inline bool variantSetString(JsonVariantData* var, const char* value) {
if (!var) return false;
var->type = JSON_LINKED_STRING;
var->content.asString = value;
return true;
}
inline bool variantSetString(JsonVariantData* var, const char* value,
MemoryPool* pool) {
return variantSetString(var, makeString(const_cast<char*>(value)), pool);
}
inline void variantSetNull(JsonVariantData* var) {
if (var) var->type = JSON_NULL;
}
inline JsonArrayData* variantToArray(JsonVariantData* var) {
if (!var) return 0;
var->type = JSON_ARRAY;
var->content.asArray.head = 0;
var->content.asArray.tail = 0;
return &var->content.asArray;
}
inline JsonObjectData* variantToObject(JsonVariantData* var) {
if (!var) return 0;
var->type = JSON_OBJECT;
var->content.asObject.head = 0;
var->content.asObject.tail = 0;
return &var->content.asObject;
}
inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src,
MemoryPool* pool) {
if (!dst) return false;
if (!src) {
dst->type = JSON_NULL;
return true;
}
switch (src->type) {
case JSON_ARRAY:
return arrayCopy(variantToArray(dst), &src->content.asArray, pool);
case JSON_OBJECT:
return objectCopy(variantToObject(dst), &src->content.asObject, pool);
case JSON_OWNED_STRING:
return variantSetString(dst, src->content.asString, pool);
case JSON_OWNED_RAW:
return variantSetOwnedRaw(
dst,
serialized(const_cast<char*>(src->content.asRaw.data),
src->content.asRaw.size),
pool);
default:
*dst = *src;
return true;
}
}
inline bool variantIsInteger(const JsonVariantData* var) {
return var && (var->type == JSON_POSITIVE_INTEGER ||
var->type == JSON_NEGATIVE_INTEGER);
}
inline bool variantIsFloat(const JsonVariantData* var) {
return var &&
(var->type == JSON_FLOAT || var->type == JSON_POSITIVE_INTEGER ||
var->type == JSON_NEGATIVE_INTEGER);
}
inline bool variantIsString(const JsonVariantData* var) {
return var &&
(var->type == JSON_LINKED_STRING || var->type == JSON_OWNED_STRING);
}
inline bool variantIsArray(const JsonVariantData* var) {
return var && var->type == JSON_ARRAY;
}
inline bool variantIsObject(const JsonVariantData* var) {
return var && var->type == JSON_OBJECT;
}
inline bool variantIsNull(const JsonVariantData* var) {
return var == 0 || var->type == JSON_NULL;
}
inline bool variantEquals(const JsonVariantData* a, const JsonVariantData* b) {
if (a == b) return true;
if (!a || !b) return false;
if (a->type != b->type) return false;
switch (a->type) {
case JSON_LINKED_RAW:
case JSON_OWNED_RAW:
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return !strcmp(a->content.asString, b->content.asString);
case JSON_BOOLEAN:
case JSON_POSITIVE_INTEGER:
case JSON_NEGATIVE_INTEGER:
return a->content.asInteger == b->content.asInteger;
case JSON_ARRAY:
return arrayEquals(&a->content.asArray, &b->content.asArray);
case JSON_OBJECT:
return objectEquals(&a->content.asObject, &b->content.asObject);
case JSON_FLOAT:
return a->content.asFloat == b->content.asFloat;
case JSON_NULL:
default:
return true;
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,8 +8,7 @@
#include <Stream.h>
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
struct ArduinoStreamReader {
Stream& _stream;
@ -35,7 +34,6 @@ struct ArduinoStreamReader {
inline ArduinoStreamReader makeReader(Stream& input) {
return ArduinoStreamReader(input);
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TChar>
class UnsafeCharPointerReader {
@ -60,5 +59,4 @@ inline SafeCharPointerReader<char> makeReader(const String& input) {
}
#endif
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,7 +8,7 @@
#include <ostream>
#endif
namespace ArduinoJson {
namespace ARDUINOJSON_NAMESPACE {
class DeserializationError {
public:
@ -80,4 +80,4 @@ inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
}
#endif
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,8 +6,7 @@
#if ARDUINOJSON_ENABLE_PROGMEM
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class UnsafeFlashStringReader {
const char* _ptr;
@ -50,7 +49,6 @@ inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
size_t size) {
return SafeFlashStringReader(input, size);
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TIterator>
class IteratorReader {
@ -30,5 +29,4 @@ inline IteratorReader<typename TInput::const_iterator> makeReader(
return IteratorReader<typename TInput::const_iterator>(input.begin(),
input.end());
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,8 +8,7 @@
#include <istream>
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class StdStreamReader {
std::istream& _stream;
@ -34,7 +33,6 @@ class StdStreamReader {
inline StdStreamReader makeReader(std::istream& input) {
return StdStreamReader(input);
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -12,15 +12,15 @@
#include "./IteratorReader.hpp"
#include "./StdStreamReader.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <template <typename, typename> class TDeserializer,
typename TJsonBuffer, typename TReader, typename TWriter>
TDeserializer<TReader, TWriter> makeDeserializer(TJsonBuffer *buffer,
typename TMemoryPool, typename TReader, typename TWriter>
TDeserializer<TReader, TWriter> makeDeserializer(TMemoryPool &memoryPool,
TReader reader, TWriter writer,
uint8_t nestingLimit) {
return TDeserializer<TReader, TWriter>(buffer, reader, writer, nestingLimit);
return TDeserializer<TReader, TWriter>(memoryPool, reader, writer,
nestingLimit);
}
// DeserializationError deserialize(TDocument& doc, TString input);
@ -28,13 +28,11 @@ TDeserializer<TReader, TWriter> makeDeserializer(TJsonBuffer *buffer,
// TString = const std::string&, const String&
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TString>
typename Internals::enable_if<!Internals::is_array<TString>::value,
DeserializationError>::type
typename enable_if<!is_array<TString>::value, DeserializationError>::type
deserialize(TDocument &doc, const TString &input) {
using namespace Internals;
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
makeStringStorage(doc.buffer(), input),
doc.nestingLimit)
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
@ -44,10 +42,9 @@ deserialize(TDocument &doc, const TString &input) {
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TChar>
DeserializationError deserialize(TDocument &doc, TChar *input) {
using namespace Internals;
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
makeStringStorage(doc.buffer(), input),
doc.nestingLimit)
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
@ -59,10 +56,9 @@ template <template <typename, typename> class TDeserializer, typename TDocument,
typename TChar>
DeserializationError deserialize(TDocument &doc, TChar *input,
size_t inputSize) {
using namespace Internals;
return makeDeserializer<TDeserializer>(
&doc.buffer(), makeReader(input, inputSize),
makeStringStorage(doc.buffer(), input), doc.nestingLimit)
doc.memoryPool(), makeReader(input, inputSize),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
@ -72,11 +68,9 @@ DeserializationError deserialize(TDocument &doc, TChar *input,
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TStream>
DeserializationError deserialize(TDocument &doc, TStream &input) {
using namespace Internals;
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
makeStringStorage(doc.buffer(), input),
doc.nestingLimit)
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,84 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "JsonObject.hpp"
#include "JsonVariant.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonDocument {
Internals::DynamicJsonBuffer _buffer;
JsonVariant _root;
public:
uint8_t nestingLimit;
DynamicJsonDocument() : nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
DynamicJsonDocument(size_t capacity)
: _buffer(capacity), nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
template <typename T>
bool is() const {
return _root.is<T>();
}
template <typename T>
typename Internals::JsonVariantAs<T>::type as() const {
return _root.as<T>();
}
// JsonObject to<JsonObject>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonObject>::value,
JsonObject>::type
to() {
clear();
JsonObject object(&_buffer);
_root = object;
return object;
}
// JsonArray to<JsonArray>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonArray>::value,
JsonArray>::type
to() {
clear();
JsonArray array(&_buffer);
_root = array;
return array;
}
// JsonVariant& to<JsonVariant>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
T&>::type
to() {
clear();
return _root;
}
Internals::DynamicJsonBuffer& buffer() {
return _buffer;
}
void clear() {
_buffer.clear();
_root = JsonVariant();
}
size_t memoryUsage() const {
return _buffer.size();
}
template <typename Visitor>
void visit(Visitor& visitor) const {
return _root.visit(visitor);
}
};
} // namespace ArduinoJson

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class EscapeSequence {
public:
@ -33,5 +32,4 @@ class EscapeSequence {
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// Decorator on top of Print to allow indented output.
// This class is used by serializeJsonPretty() but can also be used
@ -67,5 +66,4 @@ class IndentedPrint {
static const int MAX_LEVEL = 15; // because it's only 4 bits
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,24 +6,28 @@
#include "../Deserialization/deserialize.hpp"
#include "../JsonVariant.hpp"
#include "../Memory/JsonBuffer.hpp"
#include "../Memory/MemoryPool.hpp"
#include "../Numbers/isFloat.hpp"
#include "../Numbers/isInteger.hpp"
#include "../Polyfills/type_traits.hpp"
#include "./EscapeSequence.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TReader, typename TStringStorage>
class JsonDeserializer {
typedef typename remove_reference<TStringStorage>::type::StringBuilder
StringBuilder;
public:
JsonDeserializer(JsonBuffer *buffer, TReader reader,
JsonDeserializer(MemoryPool &memoryPool, TReader reader,
TStringStorage stringStorage, uint8_t nestingLimit)
: _buffer(buffer),
: _memoryPool(&memoryPool),
_reader(reader),
_stringStorage(stringStorage),
_nestingLimit(nestingLimit),
_loaded(false) {}
DeserializationError parse(JsonVariant &variant) {
DeserializationError parse(JsonVariant variant) {
DeserializationError err = skipSpacesAndComments();
if (err) return err;
@ -63,12 +67,11 @@ class JsonDeserializer {
return true;
}
DeserializationError parseArray(JsonVariant &variant) {
DeserializationError parseArray(JsonVariant variant) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonArray array(_buffer);
JsonArray array = variant.to<JsonArray>();
if (array.isNull()) return DeserializationError::NoMemory;
variant = array;
// Check opening braket
if (!eat('[')) return DeserializationError::InvalidInput;
@ -82,13 +85,15 @@ class JsonDeserializer {
// Read each value
for (;;) {
// Allocate slot in array
JsonVariant value = array.add();
if (value.isInvalid()) return DeserializationError::NoMemory;
// 1 - Parse value
JsonVariant value;
_nestingLimit--;
err = parse(value);
_nestingLimit++;
if (err) return err;
if (!array.add(value)) return DeserializationError::NoMemory;
// 2 - Skip spaces
err = skipSpacesAndComments();
@ -100,12 +105,11 @@ class JsonDeserializer {
}
}
DeserializationError parseObject(JsonVariant &variant) {
DeserializationError parseObject(JsonVariant variant) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonObject object(_buffer);
JsonObject object = variant.to<JsonObject>();
if (object.isNull()) return DeserializationError::NoMemory;
variant = object;
// Check opening brace
if (!eat('{')) return DeserializationError::InvalidInput;
@ -120,8 +124,8 @@ class JsonDeserializer {
// Read each key value pair
for (;;) {
// Parse key
const char *key;
err = parseKey(&key);
StringInMemoryPool key;
err = parseKey(key);
if (err) return err;
// Skip spaces
@ -129,13 +133,15 @@ class JsonDeserializer {
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
JsonVariant value;
_nestingLimit--;
err = parse(value);
_nestingLimit++;
if (err) return err;
if (!object.set(key, value)) return DeserializationError::NoMemory;
// Skip spaces
err = skipSpacesAndComments();
@ -151,7 +157,7 @@ class JsonDeserializer {
}
}
DeserializationError parseValue(JsonVariant &variant) {
DeserializationError parseValue(JsonVariant variant) {
if (isQuote(current())) {
return parseStringValue(variant);
} else {
@ -159,7 +165,7 @@ class JsonDeserializer {
}
}
DeserializationError parseKey(const char **key) {
DeserializationError parseKey(StringInMemoryPool &key) {
if (isQuote(current())) {
return parseQuotedString(key);
} else {
@ -167,19 +173,17 @@ class JsonDeserializer {
}
}
DeserializationError parseStringValue(JsonVariant &variant) {
const char *value;
DeserializationError err = parseQuotedString(&value);
DeserializationError parseStringValue(JsonVariant variant) {
StringInMemoryPool value;
DeserializationError err = parseQuotedString(value);
if (err) return err;
variant = value;
variant.set(value);
return DeserializationError::Ok;
}
DeserializationError parseQuotedString(const char **result) {
typename remove_reference<TStringStorage>::type::String str =
_stringStorage.startString();
char stopChar = current();
DeserializationError parseQuotedString(StringInMemoryPool &result) {
StringBuilder str = _stringStorage.startString();
const char stopChar = current();
move();
for (;;) {
@ -202,14 +206,13 @@ class JsonDeserializer {
str.append(c);
}
*result = str.c_str();
if (*result == NULL) return DeserializationError::NoMemory;
result = str.complete();
if (result.isNull()) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
DeserializationError parseNonQuotedString(const char **result) {
typename remove_reference<TStringStorage>::type::String str =
_stringStorage.startString();
DeserializationError parseNonQuotedString(StringInMemoryPool &result) {
StringBuilder str = _stringStorage.startString();
char c = current();
if (c == '\0') return DeserializationError::IncompleteInput;
@ -224,12 +227,12 @@ class JsonDeserializer {
return DeserializationError::InvalidInput;
}
*result = str.c_str();
if (*result == NULL) return DeserializationError::NoMemory;
result = str.complete();
if (result.isNull()) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
DeserializationError parseNumericValue(JsonVariant &result) {
DeserializationError parseNumericValue(JsonVariant result) {
char buffer[64];
uint8_t n = 0;
@ -242,15 +245,15 @@ class JsonDeserializer {
buffer[n] = 0;
if (isInteger(buffer)) {
result = parseInteger<JsonInteger>(buffer);
result.set(parseInteger<JsonInteger>(buffer));
} else if (isFloat(buffer)) {
result = parseFloat<JsonFloat>(buffer);
result.set(parseFloat<JsonFloat>(buffer));
} else if (!strcmp(buffer, "true")) {
result = true;
result.set(true);
} else if (!strcmp(buffer, "false")) {
result = false;
result.set(false);
} else if (!strcmp(buffer, "null")) {
result = static_cast<const char *>(0);
// already null
} else {
return DeserializationError::InvalidInput;
}
@ -329,37 +332,32 @@ class JsonDeserializer {
}
}
JsonBuffer *_buffer;
MemoryPool *_memoryPool;
TReader _reader;
TStringStorage _stringStorage;
uint8_t _nestingLimit;
char _current;
bool _loaded;
}; // namespace Internals
} // namespace Internals
};
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, const TInput &input) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input,
size_t inputSize) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input, inputSize);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput &input) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input);
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,26 +6,26 @@
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "./JsonWriter.hpp"
#include "../Visitable.hpp"
#include "JsonWriter.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class JsonSerializer {
public:
JsonSerializer(TWriter &writer) : _writer(writer) {}
void acceptFloat(JsonFloat value) {
void visitFloat(JsonFloat value) {
_writer.writeFloat(value);
}
void acceptArray(const JsonArray &array) {
void visitArray(JsonArrayConst array) {
_writer.beginArray();
JsonArray::const_iterator it = array.begin();
JsonArrayConst::iterator it = array.begin();
while (it != array.end()) {
it->visit(*this);
it->accept(*this);
++it;
if (it == array.end()) break;
@ -36,14 +36,14 @@ class JsonSerializer {
_writer.endArray();
}
void acceptObject(const JsonObject &object) {
void visitObject(JsonObjectConst object) {
_writer.beginObject();
JsonObject::const_iterator it = object.begin();
JsonObjectConst::iterator it = object.begin();
while (it != object.end()) {
_writer.writeString(it->key);
_writer.writeString(it->key());
_writer.writeColon();
it->value.visit(*this);
it->value().accept(*this);
++it;
if (it == object.end()) break;
@ -54,29 +54,29 @@ class JsonSerializer {
_writer.endObject();
}
void acceptString(const char *value) {
void visitString(const char *value) {
_writer.writeString(value);
}
void acceptRawJson(const char *data, size_t n) {
void visitRawJson(const char *data, size_t n) {
// TODO
for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]);
}
void acceptNegativeInteger(JsonUInt value) {
void visitNegativeInteger(JsonUInt value) {
_writer.writeRaw('-');
_writer.writeInteger(value);
}
void acceptPositiveInteger(JsonUInt value) {
void visitPositiveInteger(JsonUInt value) {
_writer.writeInteger(value);
}
void acceptBoolean(bool value) {
void visitBoolean(bool value) {
_writer.writeBoolean(value);
}
void acceptNull() {
void visitNull() {
_writer.writeRaw("null");
}
@ -88,55 +88,28 @@ class JsonSerializer {
JsonWriter<TWriter> _writer;
};
} // namespace Internals
template <typename TSource, typename TDestination>
size_t serializeJson(TSource &source, TDestination &destination) {
using namespace Internals;
size_t serializeJson(const TSource &source, TDestination &destination) {
return serialize<JsonSerializer>(source, destination);
}
template <typename TSource>
size_t serializeJson(const TSource &source, char *buffer, size_t bufferSize) {
using namespace Internals;
return serialize<JsonSerializer>(source, buffer, bufferSize);
}
template <typename TSource>
size_t measureJson(const TSource &source) {
using namespace Internals;
return measure<JsonSerializer>(source);
}
#if ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream &operator<<(std::ostream &os, const JsonArray &source) {
template <typename T>
inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type
operator<<(std::ostream &os, const T &source) {
serializeJson(source, os);
return os;
}
inline std::ostream &operator<<(std::ostream &os, const JsonObject &source) {
serializeJson(source, os);
return os;
}
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
serializeJson(source, os);
return os;
}
namespace Internals {
inline std::ostream &operator<<(std::ostream &os,
const JsonArraySubscript &source) {
serializeJson(source, os);
return os;
}
template <typename TKey>
inline std::ostream &operator<<(std::ostream &os,
const JsonObjectSubscript<TKey> &source) {
serializeJson(source, os);
return os;
}
} // namespace Internals
#endif
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -11,8 +11,7 @@
#include "../Polyfills/attributes.hpp"
#include "./EscapeSequence.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class JsonWriter {
@ -154,5 +153,4 @@ class JsonWriter {
private:
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -10,8 +10,7 @@
#include "./JsonSerializer.hpp"
#include "./Prettyfier.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TPrint>
class PrettyJsonSerializer_Base {
@ -33,25 +32,21 @@ class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>,
JsonSerializer<Prettyfier<TPrint> >(
PrettyJsonSerializer_Base<TPrint>::_prettyfier) {}
};
} // namespace Internals
template <typename TSource, typename TDestination>
size_t serializeJsonPretty(TSource &source, TDestination &destination) {
using namespace Internals;
return serialize<PrettyJsonSerializer>(source, destination);
}
template <typename TSource>
size_t serializeJsonPretty(const TSource &source, char *buffer,
size_t bufferSize) {
using namespace Internals;
return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
}
template <typename TSource>
size_t measureJsonPretty(const TSource &source) {
using namespace Internals;
return measure<PrettyJsonSerializer>(source);
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,8 +6,7 @@
#include "IndentedPrint.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// Converts a compact JSON string into an indented one.
template <typename TWriter>
@ -141,5 +140,4 @@ class Prettyfier {
IndentedPrint<TWriter>& _sink;
bool _inString;
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,72 +4,134 @@
#pragma once
#include "./JsonArrayData.hpp"
#include "Data/ArrayFunctions.hpp"
#include "Data/JsonVariantData.hpp"
#include "JsonArrayIterator.hpp"
namespace ArduinoJson {
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::Slot))
namespace ARDUINOJSON_NAMESPACE {
class JsonObject;
namespace Internals {
class JsonArraySubscript;
}
class JsonArray {
friend class JsonVariant;
template <typename TData>
class JsonArrayProxy {
public:
FORCE_INLINE bool isNull() const {
return _data == 0;
}
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
return JsonVariantConst(arrayGet(_data, index));
}
FORCE_INLINE size_t size() const {
return arraySize(_data);
}
protected:
JsonArrayProxy(TData* data) : _data(data) {}
TData* _data;
};
class JsonArrayConst : public JsonArrayProxy<const JsonArrayData>,
public Visitable {
friend class JsonArray;
typedef JsonArrayProxy<const JsonArrayData> proxy_type;
public:
typedef Internals::JsonArrayData::iterator iterator;
typedef Internals::JsonArrayData::const_iterator const_iterator;
typedef JsonArrayConstIterator iterator;
JsonArray() : _data(0) {}
JsonArray(Internals::JsonArrayData* arr) : _data(arr) {}
JsonArray(Internals::JsonBuffer* buf)
: _data(new (buf) Internals::JsonArrayData(buf)) {}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
if (_data)
visitor.visitArray(*this);
else
visitor.visitNull();
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_data->head);
}
FORCE_INLINE iterator end() const {
return iterator();
}
FORCE_INLINE JsonArrayConst() : proxy_type(0) {}
FORCE_INLINE JsonArrayConst(const JsonArrayData* data) : proxy_type(data) {}
FORCE_INLINE bool operator==(JsonArrayConst rhs) const {
return arrayEquals(_data, rhs._data);
}
};
class JsonArray : public JsonArrayProxy<JsonArrayData>, public Visitable {
typedef JsonArrayProxy<JsonArrayData> proxy_type;
public:
typedef JsonArrayIterator iterator;
FORCE_INLINE JsonArray() : proxy_type(0), _memoryPool(0) {}
FORCE_INLINE JsonArray(MemoryPool* pool, JsonArrayData* data)
: proxy_type(data), _memoryPool(pool) {}
operator JsonVariant() {
return JsonVariant(_memoryPool, getVariantData(_data));
}
operator JsonArrayConst() const {
return JsonArrayConst(_data);
}
// Adds the specified value at the end of the array.
//
// bool add(TValue);
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArrayData, JsonObject
// std::string, String, JsonObject
template <typename T>
bool add(const T& value) {
return add_impl<const T&>(value);
FORCE_INLINE bool add(const T& value) const {
return add().set(value);
}
// Adds the specified value at the end of the array.
FORCE_INLINE bool add(JsonArray value) const {
return add().set(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
bool add(T* value) {
return add_impl<T*>(value);
FORCE_INLINE bool add(T* value) const {
return add().set(value);
}
iterator begin() {
JsonVariant add() const {
return JsonVariant(_memoryPool, arrayAdd(_data, _memoryPool));
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return _data->begin();
return iterator(_memoryPool, _data->head);
}
const_iterator begin() const {
if (!_data) return const_iterator();
return _data->begin();
}
iterator end() {
FORCE_INLINE iterator end() const {
return iterator();
}
const_iterator end() const {
return const_iterator();
}
// Imports a 1D array
template <typename T, size_t N>
bool copyFrom(T (&array)[N]) {
FORCE_INLINE bool copyFrom(T (&array)[N]) const {
return copyFrom(array, N);
}
// Imports a 1D array
template <typename T>
bool copyFrom(T* array, size_t len) {
bool copyFrom(T* array, size_t len) const {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= add(array[i]);
@ -79,7 +141,7 @@ class JsonArray {
// Imports a 2D array
template <typename T, size_t N1, size_t N2>
bool copyFrom(T (&array)[N1][N2]) {
bool copyFrom(T (&array)[N1][N2]) const {
bool ok = true;
for (size_t i = 0; i < N1; i++) {
JsonArray nestedArray = createNestedArray();
@ -90,9 +152,14 @@ class JsonArray {
return ok;
}
// Copy a JsonArray
FORCE_INLINE bool copyFrom(JsonArray src) const {
return arrayCopy(_data, src._data, _memoryPool);
}
// Exports a 1D array
template <typename T, size_t N>
size_t copyTo(T (&array)[N]) const {
FORCE_INLINE size_t copyTo(T (&array)[N]) const {
return copyTo(array, N);
}
@ -100,8 +167,7 @@ class JsonArray {
template <typename T>
size_t copyTo(T* array, size_t len) const {
size_t i = 0;
for (const_iterator it = begin(); it != end() && i < len; ++it)
array[i++] = *it;
for (iterator it = begin(); it != end() && i < len; ++it) array[i++] = *it;
return i;
}
@ -110,99 +176,76 @@ class JsonArray {
void copyTo(T (&array)[N1][N2]) const {
if (!_data) return;
size_t i = 0;
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
for (iterator it = begin(); it != end() && i < N1; ++it) {
it->as<JsonArray>().copyTo(array[i++]);
}
}
JsonArray createNestedArray();
JsonObject createNestedObject();
FORCE_INLINE JsonArray createNestedArray() const;
FORCE_INLINE JsonObject createNestedObject() const;
Internals::JsonArraySubscript operator[](size_t index);
FORCE_INLINE JsonArraySubscript operator[](size_t index) const;
const Internals::JsonArraySubscript operator[](size_t index) const;
bool operator==(const JsonArray& rhs) const {
return _data == rhs._data;
FORCE_INLINE bool operator==(JsonArray rhs) const {
return arrayEquals(_data, rhs._data);
}
// Gets the value at the specified index.
template <typename T>
typename Internals::JsonVariantAs<T>::type get(size_t index) const {
const_iterator it = begin() += index;
return it != end() ? it->as<T>() : Internals::JsonVariantDefault<T>::get();
FORCE_INLINE typename JsonVariantAs<T>::type get(size_t index) const {
return get_impl(index).as<T>();
}
// Check the type of the value at specified index.
template <typename T>
bool is(size_t index) const {
const_iterator it = begin() += index;
return it != end() ? it->is<T>() : false;
FORCE_INLINE bool is(size_t index) const {
return get_impl(index).is<T>();
}
// Removes element at specified position.
void remove(iterator it) {
if (!_data) return;
_data->remove(it);
FORCE_INLINE void remove(iterator it) const {
arrayRemove(_data, it.internal());
}
// Removes element at specified index.
void remove(size_t index) {
remove(begin() += index);
FORCE_INLINE void remove(size_t index) const {
arrayRemove(_data, index);
}
// Sets the value at specified index.
//
// bool add(size_t index, const TValue&);
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArrayData, JsonObject
// std::string, String, JsonArray, JsonObject
template <typename T>
bool set(size_t index, const T& value) {
FORCE_INLINE bool set(size_t index, const T& value) const {
if (!_data) return false;
return set_impl<const T&>(index, value);
return get_impl(index).set(value);
}
//
// bool add(size_t index, TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
bool set(size_t index, T* value) {
FORCE_INLINE bool set(size_t index, T* value) const {
if (!_data) return false;
return set_impl<T*>(index, value);
}
size_t size() const {
if (!_data) return 0;
return _data->size();
}
bool isNull() const {
return _data == 0;
return get_impl(index).set(value);
}
template <typename Visitor>
void visit(Visitor& visitor) const {
if (_data)
return visitor.acceptArray(*this);
else
visitor.acceptNull();
FORCE_INLINE void accept(Visitor& visitor) const {
JsonArrayConst(_data).accept(visitor);
}
private:
template <typename TValueRef>
bool set_impl(size_t index, TValueRef value) {
iterator it = begin() += index;
if (it == end()) return false;
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, *it, value);
FORCE_INLINE bool add_impl(TValueRef value) const {
return add().set(value);
}
template <typename TValueRef>
bool add_impl(TValueRef value) {
if (!_data) return false;
iterator it = _data->add();
if (it == end()) return false;
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, *it, value);
FORCE_INLINE JsonVariant get_impl(size_t index) const {
return JsonVariant(_memoryPool, arrayGet(_data, index));
}
Internals::JsonArrayData* _data;
MemoryPool* _memoryPool;
};
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,26 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/List.hpp"
#include "Data/ValueSaver.hpp"
#include "JsonVariant.hpp"
#include "Memory/JsonBufferAllocated.hpp"
#include "Polyfills/type_traits.hpp"
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticJsonBuffer.
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
(sizeof(ArduinoJson::Internals::JsonArrayData) + \
(NUMBER_OF_ELEMENTS) * \
sizeof(ArduinoJson::Internals::JsonArrayData::node_type))
namespace ArduinoJson {
namespace Internals {
struct JsonArrayData : List<JsonVariant>, JsonBufferAllocated {
explicit JsonArrayData(JsonBuffer *buf) throw() : List<JsonVariant>(buf) {}
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -7,19 +7,13 @@
#include "JsonArray.hpp"
#include "JsonObject.hpp"
namespace ArduinoJson {
namespace ARDUINOJSON_NAMESPACE {
inline JsonArray JsonArray::createNestedArray() {
if (!_data) return JsonArray();
JsonArray array(_data->_buffer);
if (!array.isNull()) add(array);
return array;
inline JsonArray JsonArray::createNestedArray() const {
return add().to<JsonArray>();
}
inline JsonObject JsonArray::createNestedObject() {
if (!_data) return JsonObject();
JsonObject object(_data->_buffer);
if (!object.isNull()) add(object);
return object;
inline JsonObject JsonArray::createNestedObject() const {
return add().to<JsonObject>();
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,123 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/Slot.hpp"
#include "Data/SlotFunctions.hpp"
#include "JsonVariant.hpp"
namespace ARDUINOJSON_NAMESPACE {
class JsonVariantPtr {
public:
JsonVariantPtr(MemoryPool *memoryPool, JsonVariantData *data)
: _variant(memoryPool, data) {}
JsonVariant *operator->() {
return &_variant;
}
JsonVariant &operator*() {
return _variant;
}
private:
JsonVariant _variant;
};
class JsonArrayIterator {
public:
JsonArrayIterator() : _slot(0) {}
explicit JsonArrayIterator(MemoryPool *memoryPool, Slot *slot)
: _memoryPool(memoryPool), _slot(slot) {}
JsonVariant operator*() const {
return JsonVariant(_memoryPool, &_slot->value);
}
JsonVariantPtr operator->() {
return JsonVariantPtr(_memoryPool, &_slot->value);
}
bool operator==(const JsonArrayIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonArrayIterator &other) const {
return _slot != other._slot;
}
JsonArrayIterator &operator++() {
_slot = _slot->next;
return *this;
}
JsonArrayIterator &operator+=(size_t distance) {
_slot = slotAdvance(_slot, distance);
return *this;
}
Slot *internal() {
return _slot;
}
private:
MemoryPool *_memoryPool;
Slot *_slot;
};
class JsonVariantConstPtr {
public:
JsonVariantConstPtr(const JsonVariantData *data) : _variant(data) {}
JsonVariantConst *operator->() {
return &_variant;
}
JsonVariantConst &operator*() {
return _variant;
}
private:
JsonVariantConst _variant;
};
class JsonArrayConstIterator {
public:
JsonArrayConstIterator() : _slot(0) {}
explicit JsonArrayConstIterator(const Slot *slot) : _slot(slot) {}
JsonVariantConst operator*() const {
return JsonVariantConst(&_slot->value);
}
JsonVariantConstPtr operator->() {
return JsonVariantConstPtr(&_slot->value);
}
bool operator==(const JsonArrayConstIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonArrayConstIterator &other) const {
return _slot != other._slot;
}
JsonArrayConstIterator &operator++() {
_slot = _slot->next;
return *this;
}
JsonArrayConstIterator &operator+=(size_t distance) {
_slot = slotAdvance(_slot, distance);
return *this;
}
const Slot *internal() {
return _slot;
}
private:
const Slot *_slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -12,15 +12,15 @@
#pragma warning(disable : 4522)
#endif
namespace ArduinoJson {
namespace Internals {
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
namespace ARDUINOJSON_NAMESPACE {
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript>,
public Visitable {
public:
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
: _array(array), _index(index) {}
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
_array.set(_index, src);
get_impl().set(src.as<JsonVariantConst>());
return *this;
}
@ -31,7 +31,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
// std::string, String, JsonArray, JsonObject
template <typename T>
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
_array.set(_index, src);
get_impl().set(src);
return *this;
}
//
@ -39,7 +39,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
FORCE_INLINE JsonArraySubscript& operator=(T* src) {
_array.set(_index, src);
get_impl().set(src);
return *this;
}
@ -57,55 +57,56 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
return _array.is<T>(_index);
}
template <typename T>
FORCE_INLINE typename JsonVariantTo<T>::type to() const {
return _array.get<JsonVariant>(_index).to<T>();
}
// Replaces the value
//
// bool set(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue>
FORCE_INLINE bool set(const TValue& value) {
return _array.set(_index, value);
FORCE_INLINE bool set(const TValue& value) const {
return get_impl().set(value);
}
//
// bool set(TValue)
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(TValue* value) {
return _array.set(_index, value);
FORCE_INLINE bool set(TValue* value) const {
return get_impl().set(value);
}
template <typename Visitor>
void visit(Visitor& visitor) const {
return _array.get<JsonVariant>(_index).visit(visitor);
void accept(Visitor& visitor) const {
return get_impl().accept(visitor);
}
FORCE_INLINE size_t size() const {
return get_impl().size();
}
private:
JsonVariant get_impl() const {
return _array.get<JsonVariant>(_index);
}
JsonArray _array;
const size_t _index;
};
template <typename TImpl>
inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
size_t index) {
return impl()->template as<JsonArray>()[index];
}
template <typename TImpl>
inline const JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
size_t index) const {
return impl()->template as<JsonArray>()[index];
}
} // namespace Internals
inline Internals::JsonArraySubscript JsonArray::operator[](size_t index) {
return Internals::JsonArraySubscript(*this, index);
inline JsonArraySubscript JsonArray::operator[](size_t index) const {
return JsonArraySubscript(*this, index);
}
inline const Internals::JsonArraySubscript JsonArray::operator[](
size_t index) const {
return Internals::JsonArraySubscript(*this, index);
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)

View File

@ -0,0 +1,131 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/JsonVariantTo.hpp"
#include "JsonVariant.hpp"
#include "Memory/DynamicMemoryPool.hpp"
#include "Memory/StaticMemoryPool.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TMemoryPool>
class JsonDocument : public Visitable {
public:
uint8_t nestingLimit;
JsonDocument() : nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
template <typename Visitor>
void accept(Visitor& visitor) const {
return getVariant().accept(visitor);
}
template <typename T>
typename JsonVariantAs<T>::type as() {
return getVariant().template as<T>();
}
template <typename T>
typename JsonVariantConstAs<T>::type as() const {
return getVariant().template as<T>();
}
void clear() {
_memoryPool.clear();
_rootData.type = JSON_NULL;
}
template <typename T>
bool is() const {
return getVariant().template is<T>();
}
size_t memoryUsage() const {
return _memoryPool.size();
}
TMemoryPool& memoryPool() {
return _memoryPool;
}
template <typename T>
typename JsonVariantTo<T>::type to() {
_memoryPool.clear();
return getVariant().template to<T>();
}
protected:
template <typename T>
void copy(const JsonDocument<T>& src) {
nestingLimit = src.nestingLimit;
to<JsonVariant>().set(src.template as<JsonVariant>());
}
private:
JsonVariant getVariant() {
return JsonVariant(&_memoryPool, &_rootData);
}
JsonVariantConst getVariant() const {
return JsonVariantConst(&_rootData);
}
TMemoryPool _memoryPool;
JsonVariantData _rootData;
};
class DynamicJsonDocument : public JsonDocument<DynamicMemoryPool> {
public:
DynamicJsonDocument() {}
DynamicJsonDocument(size_t capacity) {
memoryPool().reserve(capacity);
}
DynamicJsonDocument(const DynamicJsonDocument& src) {
memoryPool().reserve(src.memoryUsage());
copy(src);
}
template <typename T>
DynamicJsonDocument(const JsonDocument<T>& src) {
memoryPool().reserve(src.memoryUsage());
copy(src);
}
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
copy(src);
return *this;
}
template <typename T>
DynamicJsonDocument& operator=(const JsonDocument<T>& src) {
copy(src);
return *this;
}
};
template <size_t CAPACITY>
class StaticJsonDocument : public JsonDocument<StaticMemoryPool<CAPACITY> > {
public:
StaticJsonDocument() {}
template <typename T>
StaticJsonDocument(const JsonDocument<T>& src) {
this->copy(src);
}
StaticMemoryPoolBase& memoryPool() {
return JsonDocument<StaticMemoryPool<CAPACITY> >::memoryPool();
}
template <typename T>
StaticJsonDocument operator=(const JsonDocument<T>& src) {
this->copy(src);
return *this;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@ -4,82 +4,185 @@
#pragma once
#include "./JsonObjectData.hpp"
#include "Data/ObjectFunctions.hpp"
#include "JsonObjectIterator.hpp"
namespace ArduinoJson {
// Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::Slot))
class JsonObject {
friend class JsonVariant;
namespace ARDUINOJSON_NAMESPACE {
template <typename TData>
class JsonObjectProxy {
public:
typedef Internals::JsonObjectData::iterator iterator;
typedef Internals::JsonObjectData::const_iterator const_iterator;
JsonObject() : _data(0) {}
JsonObject(Internals::JsonObjectData* object) : _data(object) {}
JsonObject(Internals::JsonBuffer* buf)
: _data(new (buf) Internals::JsonObjectData(buf)) {}
iterator begin() {
if (!_data) return iterator();
return _data->begin();
}
const_iterator begin() const {
if (!_data) return const_iterator();
return _data->begin();
}
// Tells weither the specified key is present and associated with a value.
//
// bool containsKey(TKey);
// TKey = const std::string&, const String&
template <typename TString>
bool containsKey(const TString& key) const {
return containsKey_impl<const TString&>(key);
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 TString>
bool containsKey(TString* key) const {
return containsKey_impl<TString*>(key);
template <typename TKey>
FORCE_INLINE bool containsKey(TKey* key) const {
return objectContainsKey(_data, makeString(key));
}
iterator end() {
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();
}
const_iterator end() const {
return const_iterator();
// Gets the value associated with the specified key.
//
// TValue get<TValue>(TKey) const;
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArrayConst, JsonObjectConst
template <typename TValue, typename TKey>
FORCE_INLINE typename JsonVariantAs<TValue>::type get(const TKey& key) const {
return get_impl(makeString(key)).template as<TValue>();
}
//
// TValue get<TValue>(TKey) const;
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArrayConst, JsonObjectConst
template <typename TValue, typename TKey>
FORCE_INLINE typename JsonVariantAs<TValue>::type get(TKey* key) const {
return get_impl(makeString(key)).template as<TValue>();
}
//
// JsonVariantConst operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey>::value, JsonVariantConst>::type
operator[](const TKey& key) const {
return get_impl(makeString(key));
}
//
// JsonVariantConst operator[](TKey) const;
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TKey>
FORCE_INLINE
typename enable_if<IsString<TKey*>::value, JsonVariantConst>::type
operator[](TKey* key) const {
return get_impl(makeString(key));
}
FORCE_INLINE bool operator==(JsonObjectConst rhs) const {
return objectEquals(_data, rhs._data);
}
private:
template <typename TKey>
FORCE_INLINE JsonVariantConst get_impl(TKey key) const {
return JsonVariantConst(objectGet(_data, key));
}
};
class JsonObject : public JsonObjectProxy<JsonObjectData>, public Visitable {
typedef JsonObjectProxy<JsonObjectData> proxy_type;
public:
typedef JsonObjectIterator iterator;
FORCE_INLINE JsonObject() : proxy_type(0), _memoryPool(0) {}
FORCE_INLINE JsonObject(MemoryPool* buf, JsonObjectData* data)
: proxy_type(data), _memoryPool(buf) {}
operator JsonVariant() const {
return JsonVariant(_memoryPool, getVariantData(_data));
}
operator JsonObjectConst() const {
return JsonObjectConst(_data);
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_memoryPool, _data->head);
}
FORCE_INLINE iterator end() const {
return iterator();
}
void clear() const {
objectClear(_data);
}
FORCE_INLINE bool copyFrom(JsonObjectConst src) {
return objectCopy(_data, src._data, _memoryPool);
}
// Creates and adds a JsonArray.
//
// JsonArray createNestedArray(TKey);
// TKey = const std::string&, const String&
template <typename TString>
JsonArray createNestedArray(const TString& key);
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 TString>
JsonArray createNestedArray(TString* key);
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 TString>
JsonObject createNestedObject(const TString& key) {
if (!_data) return JsonObject();
return createNestedObject_impl<const TString&>(key);
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 TString>
JsonObject createNestedObject(TString* key) {
return createNestedObject_impl<TString*>(key);
template <typename TKey>
FORCE_INLINE JsonObject createNestedObject(TKey* key) const {
return set(key).template to<JsonObject>();
}
// Gets the value associated with the specified key.
@ -88,19 +191,18 @@ class JsonObject {
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
typename Internals::JsonVariantAs<TValue>::type get(
const TString& key) const {
return get_impl<const TString&, TValue>(key);
template <typename TValue, typename TKey>
FORCE_INLINE typename JsonVariantAs<TValue>::type get(const TKey& key) const {
return get_impl(makeString(key)).template as<TValue>();
}
//
// TValue get<TValue>(TKey) const;
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
typename Internals::JsonVariantAs<TValue>::type get(TString* key) const {
return get_impl<TString*, TValue>(key);
template <typename TValue, typename TKey>
FORCE_INLINE typename JsonVariantAs<TValue>::type get(TKey* key) const {
return get_impl(makeString(key)).template as<TValue>();
}
// Checks the type of the value associated with the specified key.
@ -110,78 +212,59 @@ class JsonObject {
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
bool is(const TString& key) const {
return is_impl<const TString&, TValue>(key);
template <typename TValue, typename TKey>
FORCE_INLINE bool is(const TKey& key) const {
return get_impl(makeString(key)).template is<TValue>();
}
//
// bool is<TValue>(TKey) const;
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
bool is(TString* key) const {
return is_impl<TString*, TValue>(key);
template <typename TValue, typename TKey>
FORCE_INLINE bool is(TKey* key) const {
return get_impl(makeString(key)).template is<TValue>();
}
// Gets or sets the value associated with the specified key.
//
// JsonObjectSubscript operator[](TKey)
// TKey = const std::string&, const String&
template <typename TString>
Internals::JsonObjectSubscript<const TString&> operator[](
const TString& key) {
return Internals::JsonObjectSubscript<const TString&>(*this, key);
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 TString>
Internals::JsonObjectSubscript<TString*> operator[](TString* key) {
return Internals::JsonObjectSubscript<TString*>(*this, key);
template <typename TKey>
FORCE_INLINE JsonObjectSubscript<TKey*> operator[](TKey* key) const {
return JsonObjectSubscript<TKey*>(*this, key);
}
// Gets the value associated with the specified key.
//
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
const Internals::JsonObjectSubscript<const TString&> operator[](
const TString& key) const {
return Internals::JsonObjectSubscript<const TString&>(*this, key);
}
//
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
const Internals::JsonObjectSubscript<TString*> operator[](
TString* key) const {
return Internals::JsonObjectSubscript<TString*>(*this, key);
FORCE_INLINE bool operator==(JsonObject rhs) const {
return objectEquals(_data, rhs._data);
}
bool operator==(const JsonObject& rhs) const {
return _data == rhs._data;
}
void remove(iterator it) {
if (!_data) return;
_data->remove(it);
FORCE_INLINE void remove(iterator it) const {
objectRemove(_data, it.internal());
}
// Removes the specified key and the associated value.
//
// void remove(TKey);
// TKey = const std::string&, const String&
template <typename TString>
void remove(const TString& key) {
remove_impl<const TString&>(key);
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 TString>
void remove(TString* key) {
remove_impl<TString*>(key);
template <typename TKey>
FORCE_INLINE void remove(TKey* key) const {
remove_impl(makeString(key));
}
// Sets the specified key with the specified value.
@ -190,122 +273,71 @@ class JsonObject {
// TKey = const std::string&, const String&
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
bool set(const TString& key, const TValue& value) {
return set_impl<const TString&, const TValue&>(key, value);
template <typename TValue, typename TKey>
FORCE_INLINE bool set(const TKey& key, const TValue& value) const {
return set(key).set(value);
}
//
// bool set(TKey, TValue);
// TKey = const std::string&, const String&
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue, typename TString>
bool set(const TString& key, TValue* value) {
return set_impl<const TString&, TValue*>(key, value);
template <typename TValue, typename TKey>
FORCE_INLINE bool set(const TKey& key, TValue* value) const {
return set(key).set(value);
}
//
// bool set(TKey, const TValue&);
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
bool set(TString* key, const TValue& value) {
return set_impl<TString*, const TValue&>(key, value);
template <typename TValue, typename TKey>
FORCE_INLINE bool set(TKey* key, const TValue& value) const {
return set(key).set(value);
}
//
// bool set(TKey, TValue);
// TKey = char*, const char*, const FlashStringHelper*
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue, typename TString>
bool set(TString* key, TValue* value) {
return set_impl<TString*, TValue*>(key, value);
template <typename TValue, typename TKey>
FORCE_INLINE bool set(TKey* key, TValue* value) const {
return set(key).set(value);
}
size_t size() const {
if (!_data) return 0;
return _data->size();
template <typename TKey>
FORCE_INLINE JsonVariant set(TKey* key) const {
return set_impl(makeString(key));
}
bool isNull() const {
return _data == 0;
template <typename TKey>
FORCE_INLINE JsonVariant set(const TKey& key) const {
return set_impl(makeString(key));
}
FORCE_INLINE JsonVariant set(const StringInMemoryPool& key) const {
return set_impl(key);
}
template <typename Visitor>
void visit(Visitor& visitor) const {
if (_data)
visitor.acceptObject(*this);
else
return visitor.acceptNull();
FORCE_INLINE void accept(Visitor& visitor) const {
JsonObjectConst(_data).accept(visitor);
}
private:
template <typename TStringRef>
bool containsKey_impl(TStringRef key) const {
return findKey<TStringRef>(key) != end();
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>
JsonArray createNestedArray_impl(TStringRef key);
template <typename TStringRef>
JsonObject createNestedObject_impl(TStringRef key);
// Returns the list node that matches the specified key.
template <typename TStringRef>
iterator findKey(TStringRef key) {
iterator it;
for (it = begin(); it != end(); ++it) {
if (Internals::makeString(key).equals(it->key)) break;
}
return it;
}
template <typename TStringRef>
const_iterator findKey(TStringRef key) const {
return const_cast<JsonObject*>(this)->findKey<TStringRef>(key);
FORCE_INLINE void remove_impl(TStringRef key) const {
objectRemove(_data, objectFindSlot(_data, key));
}
template <typename TStringRef, typename TValue>
typename Internals::JsonVariantAs<TValue>::type get_impl(
TStringRef key) const {
const_iterator it = findKey<TStringRef>(key);
return it != end() ? it->value.as<TValue>()
: Internals::JsonVariantDefault<TValue>::get();
}
template <typename TStringRef, typename TValue>
bool is_impl(TStringRef key) const {
const_iterator it = findKey<TStringRef>(key);
return it != end() ? it->value.is<TValue>() : false;
}
template <typename TStringRef>
void remove_impl(TStringRef key) {
if (!_data) return;
_data->remove(findKey<TStringRef>(key));
}
template <typename TStringRef, typename TValueRef>
bool set_impl(TStringRef key, TValueRef value) {
if (!_data) return false;
// ignore null key
if (Internals::makeString(key).is_null()) return false;
// search a matching key
iterator it = findKey<TStringRef>(key);
if (it == end()) {
// add the key
it = _data->add();
if (it == end()) return false;
bool key_ok =
Internals::ValueSaver<TStringRef>::save(_data->_buffer, it->key, key);
if (!key_ok) return false;
}
// save the value
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, it->value,
value);
}
Internals::JsonObjectData* _data;
MemoryPool* _memoryPool;
};
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,26 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/List.hpp"
#include "Data/ValueSaver.hpp"
#include "JsonPair.hpp"
#include "Memory/JsonBufferAllocated.hpp"
#include "Polyfills/type_traits.hpp"
// Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticJsonBuffer.
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
(sizeof(ArduinoJson::Internals::JsonObjectData) + \
(NUMBER_OF_ELEMENTS) * \
sizeof(ArduinoJson::Internals::JsonObjectData::node_type))
namespace ArduinoJson {
namespace Internals {
struct JsonObjectData : List<JsonPair>, JsonBufferAllocated {
explicit JsonObjectData(JsonBuffer* buf) throw() : List<JsonPair>(buf) {}
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -7,31 +7,15 @@
#include "JsonArray.hpp"
#include "JsonObject.hpp"
namespace ArduinoJson {
namespace ARDUINOJSON_NAMESPACE {
template <typename TString>
inline JsonArray JsonObject::createNestedArray(const TString& key) {
return createNestedArray_impl<const TString&>(key);
inline JsonArray JsonObject::createNestedArray(const TString& key) const {
return set(key).template to<JsonArray>();
}
template <typename TString>
inline JsonArray JsonObject::createNestedArray(TString* key) {
return createNestedArray_impl<TString*>(key);
inline JsonArray JsonObject::createNestedArray(TString* key) const {
return set(key).template to<JsonArray>();
}
template <typename TStringRef>
inline JsonArray JsonObject::createNestedArray_impl(TStringRef key) {
if (!_data) return JsonArray();
JsonArray array(_data->_buffer);
if (!array.isNull()) set(key, array);
return array;
}
template <typename TStringRef>
inline JsonObject JsonObject::createNestedObject_impl(TStringRef key) {
if (!_data) return JsonObject();
JsonObject object(_data->_buffer);
if (!object.isNull()) set(key, object);
return object;
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,123 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/SlotFunctions.hpp"
#include "JsonPair.hpp"
namespace ARDUINOJSON_NAMESPACE {
class JsonPairPtr {
public:
JsonPairPtr(MemoryPool *memoryPool, Slot *slot) : _pair(memoryPool, slot) {}
const JsonPair *operator->() const {
return &_pair;
}
const JsonPair &operator*() const {
return _pair;
}
private:
JsonPair _pair;
};
class JsonObjectIterator {
public:
JsonObjectIterator() : _slot(0) {}
explicit JsonObjectIterator(MemoryPool *memoryPool, Slot *slot)
: _memoryPool(memoryPool), _slot(slot) {}
JsonPair operator*() const {
return JsonPair(_memoryPool, _slot);
}
JsonPairPtr operator->() {
return JsonPairPtr(_memoryPool, _slot);
}
bool operator==(const JsonObjectIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonObjectIterator &other) const {
return _slot != other._slot;
}
JsonObjectIterator &operator++() {
if (_slot) _slot = _slot->next;
return *this;
}
JsonObjectIterator &operator+=(size_t distance) {
_slot = slotAdvance(_slot, distance);
return *this;
}
Slot *internal() {
return _slot;
}
private:
MemoryPool *_memoryPool;
Slot *_slot;
};
class JsonPairConstPtr {
public:
JsonPairConstPtr(const Slot *slot) : _pair(slot) {}
const JsonPairConst *operator->() const {
return &_pair;
}
const JsonPairConst &operator*() const {
return _pair;
}
private:
JsonPairConst _pair;
};
class JsonObjectConstIterator {
public:
JsonObjectConstIterator() : _slot(0) {}
explicit JsonObjectConstIterator(const Slot *slot) : _slot(slot) {}
JsonPairConst operator*() const {
return JsonPairConst(_slot);
}
JsonPairConstPtr operator->() {
return JsonPairConstPtr(_slot);
}
bool operator==(const JsonObjectConstIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonObjectConstIterator &other) const {
return _slot != other._slot;
}
JsonObjectConstIterator &operator++() {
if (_slot) _slot = _slot->next;
return *this;
}
JsonObjectConstIterator &operator+=(size_t distance) {
_slot = slotAdvance(_slot, distance);
return *this;
}
const Slot *internal() {
return _slot;
}
private:
const Slot *_slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -13,20 +13,24 @@
#pragma warning(disable : 4522)
#endif
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TStringRef>
class JsonObjectSubscript
: public JsonVariantBase<JsonObjectSubscript<TStringRef> > {
: public JsonVariantBase<JsonObjectSubscript<TStringRef> >,
public Visitable {
typedef JsonObjectSubscript<TStringRef> this_type;
public:
FORCE_INLINE JsonObjectSubscript(JsonObject object, TStringRef key)
: _object(object), _key(key) {}
operator JsonVariantConst() const {
return get_impl();
}
FORCE_INLINE this_type &operator=(const this_type &src) {
_object.set(_key, src);
set_impl().set(src);
return *this;
}
@ -38,7 +42,7 @@ class JsonObjectSubscript
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
operator=(const TValue &src) {
_object.set(_key, src);
set_impl().set(src);
return *this;
}
//
@ -46,22 +50,27 @@ class JsonObjectSubscript
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE this_type &operator=(TValue *src) {
_object.set(_key, src);
set_impl().set(src);
return *this;
}
FORCE_INLINE bool isNull() const {
return !_object.containsKey(_key);
return get_impl().isNull();
}
template <typename TValue>
FORCE_INLINE typename JsonVariantAs<TValue>::type as() const {
return _object.get<TValue>(_key);
return get_impl().template as<TValue>();
}
template <typename TValue>
FORCE_INLINE bool is() const {
return _object.is<TValue>(_key);
return get_impl().template is<TValue>();
}
template <typename TValue>
FORCE_INLINE typename JsonVariantTo<TValue>::type to() {
return set_impl().template to<TValue>();
}
// Sets the specified value.
@ -73,39 +82,39 @@ class JsonObjectSubscript
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
const TValue &value) {
return _object.set(_key, value);
return set_impl().set(value);
}
//
// bool set(TValue);
// TValue = char*, const char, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(const TValue *value) {
return _object.set(_key, value);
return set_impl().set(value);
}
template <typename Visitor>
void visit(Visitor &visitor) const {
return _object.get<JsonVariant>(_key).visit(visitor);
void accept(Visitor &visitor) const {
return get_impl().accept(visitor);
}
private:
JsonVariant get_impl() const {
return _object.get<JsonVariant>(_key);
}
JsonVariant set_impl() const {
return _object.set(_key);
}
JsonObject _object;
TStringRef _key;
};
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
const JsonObjectSubscript<const TString &> >::type
JsonVariantSubscripts<TImpl>::operator[](const TString &key) const {
return impl()->template as<JsonObject>()[key];
}
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
JsonObjectSubscript<const TString &> >::type
JsonVariantSubscripts<TImpl>::operator[](const TString &key) {
JsonVariantSubscripts<TImpl>::operator[](const TString &key) const {
return impl()->template as<JsonObject>()[key];
}
@ -113,20 +122,11 @@ template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString *>::value,
JsonObjectSubscript<TString *> >::type
JsonVariantSubscripts<TImpl>::operator[](TString *key) {
return impl()->template as<JsonObject>()[key];
}
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString *>::value,
const JsonObjectSubscript<TString *> >::type
JsonVariantSubscripts<TImpl>::operator[](TString *key) const {
return impl()->template as<JsonObject>()[key];
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)

View File

@ -4,13 +4,50 @@
#pragma once
#include "JsonKey.hpp"
#include "JsonVariant.hpp"
namespace ArduinoJson {
namespace ARDUINOJSON_NAMESPACE {
// A key value pair for JsonObjectData.
struct JsonPair {
const char* key;
JsonVariant value;
class JsonPair {
public:
JsonPair(MemoryPool* memoryPool, Slot* slot) : _key(slot) {
if (slot) {
_value = JsonVariant(memoryPool, &slot->value);
}
}
JsonKey key() const {
return _key;
}
JsonVariant value() const {
return _value;
}
private:
JsonKey _key;
JsonVariant _value;
};
} // namespace ArduinoJson
class JsonPairConst {
public:
JsonPairConst(const Slot* slot) : _key(slot) {
if (slot) {
_value = JsonVariantConst(&slot->value);
}
}
JsonKey key() const {
return _key;
}
JsonVariantConst value() const {
return _value;
}
private:
JsonKey _key;
JsonVariantConst _value;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -7,190 +7,28 @@
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include "Data/JsonVariantContent.hpp"
#include "Data/JsonVariantDefault.hpp"
#include "Data/JsonVariantType.hpp"
#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 "Serialization/DynamicStringWriter.hpp"
#include "SerializedValue.hpp"
#include "Visitable.hpp"
namespace ArduinoJson {
namespace ARDUINOJSON_NAMESPACE {
// Forward declarations.
class JsonArray;
class JsonObject;
// A variant that can be a any value serializable to a JSON value.
//
// It can be set to:
// - a boolean
// - a char, short, int or a long (signed or unsigned)
// - a string (const char*)
// - a reference to a JsonArray or JsonObject
class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
// Contains the methods shared by JsonVariant and JsonVariantConst
template <typename TData>
class JsonVariantProxy {
public:
// Creates an uninitialized JsonVariant
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
// Create a JsonVariant containing a boolean value.
// It will be serialized as "true" or "false" in JSON.
JsonVariant(bool value) {
using namespace Internals;
_type = JSON_BOOLEAN;
_content.asInteger = static_cast<JsonUInt>(value);
}
// Create a JsonVariant containing a floating point value.
// JsonVariant(double value);
// JsonVariant(float value);
template <typename T>
JsonVariant(T value,
typename Internals::enable_if<
Internals::is_floating_point<T>::value>::type * = 0) {
using namespace Internals;
_type = JSON_FLOAT;
_content.asFloat = static_cast<JsonFloat>(value);
}
// Create a JsonVariant containing an integer value.
// JsonVariant(char)
// JsonVariant(signed short)
// JsonVariant(signed int)
// JsonVariant(signed long)
// JsonVariant(signed char)
template <typename T>
JsonVariant(
T value,
typename Internals::enable_if<Internals::is_integral<T>::value &&
Internals::is_signed<T>::value>::type * =
0) {
using namespace Internals;
if (value >= 0) {
_type = JSON_POSITIVE_INTEGER;
_content.asInteger = static_cast<JsonUInt>(value);
} else {
_type = JSON_NEGATIVE_INTEGER;
_content.asInteger = ~static_cast<JsonUInt>(value) + 1;
}
}
// JsonVariant(unsigned short)
// JsonVariant(unsigned int)
// JsonVariant(unsigned long)
template <typename T>
JsonVariant(
T value,
typename Internals::enable_if<Internals::is_integral<T>::value &&
Internals::is_unsigned<T>::value>::type * =
0) {
using namespace Internals;
_type = JSON_POSITIVE_INTEGER;
_content.asInteger = static_cast<JsonUInt>(value);
}
// Create a JsonVariant containing a string.
// JsonVariant(const char*);
// JsonVariant(const signed char*);
// JsonVariant(const unsigned char*);
template <typename TChar>
JsonVariant(const TChar *value,
typename Internals::enable_if<sizeof(TChar) == 1>::type * = 0) {
_type = Internals::JSON_STRING;
_content.asString = reinterpret_cast<const char *>(value);
}
// Create a JsonVariant containing an unparsed string
JsonVariant(Internals::SerializedValue<const char *> value) {
_type = Internals::JSON_UNPARSED;
_content.asRaw.data = value.data();
_content.asRaw.size = value.size();
}
JsonVariant(JsonArray array);
JsonVariant(JsonObject object);
// Get the variant as the specified type.
//
// char as<char>() const;
// signed char as<signed char>() const;
// signed short as<signed short>() const;
// signed int as<signed int>() const;
// signed long as<signed long>() const;
// unsigned char as<unsigned char>() const;
// unsigned short as<unsigned short>() const;
// unsigned int as<unsigned int>() const;
// unsigned long as<unsigned long>() const;
template <typename T>
const typename Internals::enable_if<Internals::is_integral<T>::value, T>::type
as() const {
return variantAsInteger<T>();
}
// bool as<bool>() const
template <typename T>
const typename Internals::enable_if<Internals::is_same<T, bool>::value,
T>::type
as() const {
return variantAsInteger<int>() != 0;
}
//
// double as<double>() const;
// float as<float>() const;
template <typename T>
const typename Internals::enable_if<Internals::is_floating_point<T>::value,
T>::type
as() const {
return variantAsFloat<T>();
}
//
// const char* as<const char*>() const;
// const char* as<char*>() const;
template <typename T>
typename Internals::enable_if<Internals::is_same<T, const char *>::value ||
Internals::is_same<T, char *>::value,
const char *>::type
as() const {
return variantAsString();
}
//
// std::string as<std::string>() const;
// String as<String>() const;
template <typename T>
typename Internals::enable_if<Internals::IsWriteableString<T>::value, T>::type
as() const {
const char *cstr = variantAsString();
if (cstr) return T(cstr);
T s;
serializeJson(*this, s);
return s;
}
//
// JsonArray as<JsonArray>() const;
// const JsonArray as<const JsonArray>() const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonArray>::value,
JsonArray>::type
as() const;
//
// JsonObject as<JsonObject>() const;
// const JsonObject as<const JsonObject>() const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonObject>::value,
T>::type
as() const;
//
// JsonVariant as<JsonVariant> const;
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
T>::type
as() const {
return *this;
}
// Tells weither the variant has the specified type.
// Tells wether the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
//
// bool is<char>() const;
@ -203,122 +41,297 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T>
typename Internals::enable_if<Internals::is_integral<T>::value, bool>::type
is() const {
return variantIsInteger();
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>
typename Internals::enable_if<Internals::is_floating_point<T>::value,
bool>::type
is() const {
return variantIsFloat();
FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
const {
return variantIsFloat(_data);
}
//
// bool is<bool>() const
template <typename T>
typename Internals::enable_if<Internals::is_same<T, bool>::value, bool>::type
is() const {
return variantIsBoolean();
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>
typename Internals::enable_if<Internals::is_same<T, const char *>::value ||
Internals::is_same<T, char *>::value,
bool>::type
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();
return variantIsString(_data);
}
//
// bool is<JsonArray> const;
// bool is<const JsonArray> const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonArray>::value,
bool>::type
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, JsonArray>::value, bool>::type
is() const {
return variantIsArray();
return variantIsArray(_data);
}
//
// bool is<JsonObject> const;
// bool is<const JsonObject> const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonObject>::value,
bool>::type
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, JsonObject>::value, bool>::type
is() const {
return variantIsObject();
return variantIsObject(_data);
}
// Returns true if the variant has a value
bool isNull() const {
return _type == Internals::JSON_UNDEFINED;
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);
}
// 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));
}
// 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 variantSetSignedInteger(_data, static_cast<JsonUInt>(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, _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);
}
// set(const char*);
FORCE_INLINE bool set(StringInMemoryPool value) const {
return variantSetString(_data, value, _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 visit(Visitor &visitor) const {
using namespace Internals;
switch (_type) {
case JSON_FLOAT:
return visitor.acceptFloat(_content.asFloat);
void accept(Visitor &visitor) const;
case JSON_ARRAY:
return visitor.acceptArray(_content.asArray);
FORCE_INLINE bool operator==(JsonVariant lhs) const {
return variantEquals(_data, lhs._data);
}
case JSON_OBJECT:
return visitor.acceptObject(_content.asObject);
FORCE_INLINE bool operator!=(JsonVariant lhs) const {
return !variantEquals(_data, lhs._data);
}
case JSON_STRING:
return visitor.acceptString(_content.asString);
// 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;
case JSON_UNPARSED:
return visitor.acceptRawJson(_content.asRaw.data, _content.asRaw.size);
private:
MemoryPool *_memoryPool;
};
case JSON_NEGATIVE_INTEGER:
return visitor.acceptNegativeInteger(_content.asInteger);
class JsonVariantConst : public JsonVariantProxy<const JsonVariantData>,
public JsonVariantBase<JsonVariantConst>,
public Visitable {
typedef JsonVariantProxy<const JsonVariantData> proxy_type;
friend class JsonVariant;
case JSON_POSITIVE_INTEGER:
return visitor.acceptPositiveInteger(_content.asInteger);
public:
JsonVariantConst() : proxy_type(0) {}
JsonVariantConst(const JsonVariantData *data) : proxy_type(data) {}
JsonVariantConst(JsonVariant var) : proxy_type(var._data) {}
case JSON_BOOLEAN:
return visitor.acceptBoolean(_content.asInteger != 0);
template <typename Visitor>
void accept(Visitor &visitor) const;
default: // JSON_UNDEFINED
return visitor.acceptNull();
}
// 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)));
}
};
class JsonVariantLocal : public JsonVariant {
public:
explicit JsonVariantLocal(MemoryPool *memoryPool)
: JsonVariant(memoryPool, &_localData) {
_localData.type = JSON_NULL;
}
private:
JsonArray variantAsArray() const;
JsonObject variantAsObject() const;
const char *variantAsString() const;
template <typename T>
T variantAsFloat() const;
template <typename T>
T variantAsInteger() const;
bool variantIsBoolean() const;
bool variantIsFloat() const;
bool variantIsInteger() const;
bool variantIsArray() const {
return _type == Internals::JSON_ARRAY;
}
bool variantIsObject() const {
return _type == Internals::JSON_OBJECT;
}
bool variantIsString() const {
return _type == Internals::JSON_STRING;
}
// The current type of the variant
Internals::JsonVariantType _type;
// The various alternatives for the value of the variant.
Internals::JsonVariantContent _content;
JsonVariantData _localData;
};
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -9,14 +9,11 @@
#include "JsonVariantOr.hpp"
#include "JsonVariantSubscripts.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TImpl>
class JsonVariantBase : public JsonVariantCasts<TImpl>,
public JsonVariantComparisons<TImpl>,
public JsonVariantOr<TImpl>,
public JsonVariantSubscripts<TImpl>,
public JsonVariantTag {};
} // namespace Internals
} // namespace ArduinoJson
public JsonVariantSubscripts<TImpl> {};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -7,8 +7,7 @@
#include "Data/JsonVariantAs.hpp"
#include "Polyfills/attributes.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TImpl>
class JsonVariantCasts {
@ -23,5 +22,4 @@ class JsonVariantCasts {
return static_cast<const TImpl *>(this);
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,136 +4,158 @@
#pragma once
#include "Data/IsVariant.hpp"
#include "Polyfills/type_traits.hpp"
#include "Strings/StringTypes.hpp"
#include "JsonVariant.hpp"
namespace ArduinoJson {
class JsonArray;
class JsonObject;
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
struct is_simple_value {
static const bool value = is_integral<T>::value ||
is_floating_point<T>::value ||
is_same<T, bool>::value;
};
namespace Internals {
template <typename TImpl>
template <typename TVariant>
class JsonVariantComparisons {
public:
template <typename TComparand>
friend bool operator==(const JsonVariantComparisons &variant,
TComparand comparand) {
return variant.equals(comparand);
}
template <typename TComparand>
friend typename enable_if<!IsVariant<TComparand>::value, bool>::type
operator==(TComparand comparand, const JsonVariantComparisons &variant) {
return variant.equals(comparand);
}
template <typename TComparand>
friend bool operator!=(const JsonVariantComparisons &variant,
TComparand comparand) {
return !variant.equals(comparand);
}
template <typename TComparand>
friend typename enable_if<!IsVariant<TComparand>::value, bool>::type
operator!=(TComparand comparand, const JsonVariantComparisons &variant) {
return !variant.equals(comparand);
}
template <typename TComparand>
friend bool operator<=(const JsonVariantComparisons &left, TComparand right) {
return left.as<TComparand>() <= right;
}
template <typename TComparand>
friend bool operator<=(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand <= variant.as<TComparand>();
}
template <typename TComparand>
friend bool operator>=(const JsonVariantComparisons &variant,
TComparand comparand) {
return variant.as<TComparand>() >= comparand;
}
template <typename TComparand>
friend bool operator>=(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand >= variant.as<TComparand>();
}
template <typename TComparand>
friend bool operator<(const JsonVariantComparisons &varian,
TComparand comparand) {
return varian.as<TComparand>() < comparand;
}
template <typename TComparand>
friend bool operator<(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand < variant.as<TComparand>();
}
template <typename TComparand>
friend bool operator>(const JsonVariantComparisons &variant,
TComparand comparand) {
return variant.as<TComparand>() > comparand;
}
template <typename TComparand>
friend bool operator>(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand > variant.as<TComparand>();
}
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
// const char* == TVariant
template <typename T>
const typename JsonVariantAs<T>::type as() const {
return impl()->template as<T>();
friend typename enable_if<IsString<T *>::value, bool>::type operator==(
T *lhs, TVariant rhs) {
return makeString(lhs).equals(rhs.template as<const char *>());
}
// std::string == TVariant
template <typename T>
bool is() const {
return impl()->template is<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 *>());
}
template <typename TString>
typename enable_if<IsString<TString>::value, bool>::type equals(
const TString &comparand) const {
return makeString(comparand).equals(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 *>());
}
template <typename TComparand>
typename enable_if<
!IsVariant<TComparand>::value && !IsString<TComparand>::value, bool>::type
equals(const TComparand &comparand) const {
return as<TComparand>() == comparand;
// 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 *>());
}
template <typename TVariant2>
bool equals(const JsonVariantComparisons<TVariant2> &right) const {
using namespace Internals;
if (is<bool>() && right.template is<bool>())
return as<bool>() == right.template as<bool>();
if (is<JsonInteger>() && right.template is<JsonInteger>())
return as<JsonInteger>() == right.template as<JsonInteger>();
if (is<JsonFloat>() && right.template is<JsonFloat>())
return as<JsonFloat>() == right.template as<JsonFloat>();
if (is<JsonArray>() && right.template is<JsonArray>())
return as<JsonArray>() == right.template as<JsonArray>();
if (is<JsonObject>() && right.template is<JsonObject>())
return as<JsonObject>() == right.template as<JsonObject>();
if (is<char *>() && right.template is<char *>())
return makeString(as<char *>()).equals(right.template as<char *>());
// bool/int/float == TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator==(
const T &lhs, TVariant rhs) {
return lhs == rhs.template as<T>();
}
return false;
// TVariant == bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator==(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() == rhs;
}
// 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 *>());
}
// 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 *>());
}
// 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 *>());
}
// 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 *>());
}
// bool/int/float != TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator!=(
const T &lhs, TVariant rhs) {
return lhs != rhs.template as<T>();
}
// TVariant != bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator!=(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() != rhs;
}
// bool/int/float < TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator<(
const T &lhs, TVariant rhs) {
return lhs < rhs.template as<T>();
}
// TVariant < bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator<(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() < rhs;
}
// bool/int/float <= TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator<=(
const T &lhs, TVariant rhs) {
return lhs <= rhs.template as<T>();
}
// TVariant <= bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator<=(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() <= rhs;
}
// bool/int/float > TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator>(
const T &lhs, TVariant rhs) {
return lhs > rhs.template as<T>();
}
// TVariant > bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator>(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() > rhs;
}
// bool/int/float >= TVariant
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator>=(
const T &lhs, TVariant rhs) {
return lhs >= rhs.template as<T>();
}
// TVariant >= bool/int/float
template <typename T>
friend typename enable_if<is_simple_value<T>::value, bool>::type operator>=(
TVariant lhs, const T &rhs) {
return lhs.template as<T>() >= rhs;
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -5,123 +5,114 @@
#pragma once
#include "Configuration.hpp"
#include "JsonArrayData.hpp"
#include "JsonObjectData.hpp"
#include "JsonVariant.hpp"
#include "Numbers/isFloat.hpp"
#include "Numbers/isInteger.hpp"
#include "Numbers/parseFloat.hpp"
#include "Numbers/parseInteger.hpp"
#include <string.h> // for strcmp
namespace ArduinoJson {
namespace ARDUINOJSON_NAMESPACE {
inline JsonVariant::JsonVariant(JsonArray array) {
if (!array.isNull()) {
_type = Internals::JSON_ARRAY;
_content.asArray = array._data;
} else {
_type = Internals::JSON_UNDEFINED;
}
inline bool JsonVariant::set(JsonArray array) const {
return to<JsonArray>().copyFrom(array);
}
inline JsonVariant::JsonVariant(JsonObject object) {
if (!object.isNull()) {
_type = Internals::JSON_OBJECT;
_content.asObject = object._data;
} else {
_type = Internals::JSON_UNDEFINED;
}
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 Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonArray>::value,
JsonArray>::type
inline typename enable_if<is_same<T, JsonArray>::value, T>::type
JsonVariant::as() const {
return variantAsArray();
return JsonArray(_memoryPool, variantAsArray(_data));
}
template <typename T>
inline typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonObject>::value,
T>::type
inline typename enable_if<is_same<T, JsonObject>::value, T>::type
JsonVariant::as() const {
return variantAsObject();
}
inline JsonArray JsonVariant::variantAsArray() const {
if (_type == Internals::JSON_ARRAY) return _content.asArray;
return JsonArray();
}
inline JsonObject JsonVariant::variantAsObject() const {
if (_type == Internals::JSON_OBJECT) return _content.asObject;
return JsonObject();
return JsonObject(_memoryPool, variantAsObject(_data));
}
template <typename T>
inline T JsonVariant::variantAsInteger() const {
using namespace Internals;
switch (_type) {
case JSON_UNDEFINED:
case JSON_UNPARSED:
return 0;
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return T(_content.asInteger);
case JSON_NEGATIVE_INTEGER:
return T(~_content.asInteger + 1);
case JSON_STRING:
return parseInteger<T>(_content.asString);
default:
return T(_content.asFloat);
}
}
inline const char *JsonVariant::variantAsString() const {
using namespace Internals;
return _type == JSON_STRING ? _content.asString : NULL;
inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type
JsonVariant::to() const {
return JsonArray(_memoryPool, variantToArray(_data));
}
template <typename T>
inline T JsonVariant::variantAsFloat() const {
using namespace Internals;
switch (_type) {
case JSON_UNDEFINED:
case JSON_UNPARSED:
return 0;
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return static_cast<T>(_content.asInteger);
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type
JsonVariant::to() const {
return JsonObject(_memoryPool, variantToObject(_data));
}
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type
JsonVariant::to() const {
variantSetNull(_data);
return *this;
}
template <typename Visitor>
inline void JsonVariant::accept(Visitor& visitor) const {
return JsonVariantConst(_data).accept(visitor);
}
template <typename Visitor>
inline void JsonVariantConst::accept(Visitor& visitor) const {
if (!_data) return visitor.visitNull();
switch (_data->type) {
case JSON_FLOAT:
return visitor.visitFloat(_data->content.asFloat);
case JSON_ARRAY:
return visitor.visitArray(JsonArrayConst(&_data->content.asArray));
case JSON_OBJECT:
return visitor.visitObject(JsonObjectConst(&_data->content.asObject));
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return visitor.visitString(_data->content.asString);
case JSON_LINKED_RAW:
case JSON_OWNED_RAW:
return visitor.visitRawJson(_data->content.asRaw.data,
_data->content.asRaw.size);
case JSON_NEGATIVE_INTEGER:
return -static_cast<T>(_content.asInteger);
case JSON_STRING:
return parseFloat<T>(_content.asString);
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 static_cast<T>(_content.asFloat);
return visitor.visitNull();
}
}
inline bool JsonVariant::variantIsBoolean() const {
using namespace Internals;
return _type == JSON_BOOLEAN;
inline JsonVariantConst JsonVariantConst::operator[](size_t index) const {
return JsonArrayConst(variantAsArray(_data))[index];
}
inline bool JsonVariant::variantIsInteger() const {
using namespace Internals;
return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER;
}
inline bool JsonVariant::variantIsFloat() const {
using namespace Internals;
return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER ||
_type == JSON_NEGATIVE_INTEGER;
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,8 +8,7 @@
#include "Polyfills/attributes.hpp"
#include "Polyfills/type_traits.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TImpl>
class JsonVariantOr {
@ -47,5 +46,4 @@ class JsonVariantOr {
return static_cast<const TImpl *>(this);
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -9,10 +9,9 @@
#include "Polyfills/type_traits.hpp"
#include "Strings/StringTypes.hpp"
namespace ArduinoJson {
namespace ARDUINOJSON_NAMESPACE {
class JsonArray;
class JsonObject;
namespace Internals {
// Forward declarations.
class JsonArraySubscript;
@ -22,50 +21,26 @@ class JsonObjectSubscript;
template <typename TImpl>
class JsonVariantSubscripts {
public:
// Mimics an array or an object.
// Returns the size of the array or object if the variant has that type.
// Returns 0 if the variant is neither an array nor an object
size_t size() const {
return impl()->template as<JsonArray>().size() +
impl()->template as<JsonObject>().size();
}
// Mimics an array.
// Returns the element at specified index if the variant is an array.
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
FORCE_INLINE JsonArraySubscript operator[](size_t index);
FORCE_INLINE JsonArraySubscript operator[](size_t index) const;
// Mimics an object.
// Returns the value associated with the specified key if the variant is
// an object.
//
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value,
const JsonObjectSubscript<const TString &> >::type
operator[](const TString &key) const;
//
// const JsonObjectSubscript operator[](TKey) const;
// JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
JsonObjectSubscript<const TString &> >::type
operator[](const TString &key);
operator[](const TString &key) const;
//
// JsonObjectSubscript operator[](TKey);
// JsonObjectSubscript 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
operator[](TString *key);
//
// JsonObjectSubscript operator[](TKey);
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString *>::value,
const JsonObjectSubscript<TString *> >::type
operator[](TString *key) const;
private:
@ -73,5 +48,4 @@ class JsonVariantSubscripts {
return static_cast<const TImpl *>(this);
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,19 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "MemoryPool.hpp"
namespace ARDUINOJSON_NAMESPACE {
class AllocableInMemoryPool {
public:
void *operator new(size_t n, MemoryPool *memoryPool) NOEXCEPT {
return memoryPool->alloc(n);
}
void operator delete(void *, MemoryPool *)NOEXCEPT {}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,9 +4,10 @@
#pragma once
#include "JsonBuffer.hpp"
#include "../Strings/StringInMemoryPool.hpp"
#include "MemoryPool.hpp"
#include <stdlib.h>
#include <stdlib.h> // malloc, free
#if defined(__clang__)
#pragma clang diagnostic push
@ -18,8 +19,7 @@
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class DefaultAllocator {
public:
void* allocate(size_t size) {
@ -31,7 +31,7 @@ class DefaultAllocator {
};
template <typename TAllocator>
class DynamicJsonBufferBase : public JsonBuffer {
class DynamicMemoryPoolBase : public MemoryPool {
struct Block;
struct EmptyBlock {
Block* next;
@ -45,27 +45,31 @@ class DynamicJsonBufferBase : public JsonBuffer {
public:
enum { EmptyBlockSize = sizeof(EmptyBlock) };
DynamicJsonBufferBase(size_t initialSize = 256)
DynamicMemoryPoolBase(size_t initialSize = ARDUINOJSON_DEFAULT_POOL_SIZE)
: _head(NULL), _nextBlockCapacity(initialSize) {}
~DynamicJsonBufferBase() {
~DynamicMemoryPoolBase() {
clear();
}
// Gets the number of bytes occupied in the buffer
void reserve(size_t capacity) {
_nextBlockCapacity = capacity;
}
// Gets the number of bytes occupied in the memoryPool
size_t size() const {
size_t total = 0;
for (const Block* b = _head; b; b = b->next) total += b->size;
return total;
}
// Allocates the specified amount of bytes in the buffer
// Allocates the specified amount of bytes in the memoryPool
virtual void* alloc(size_t bytes) {
alignNextAlloc();
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
}
// Resets the buffer.
// Resets the memoryPool.
// USE WITH CAUTION: this invalidates all previously allocated data
void clear() {
Block* currentBlock = _head;
@ -78,9 +82,9 @@ class DynamicJsonBufferBase : public JsonBuffer {
_head = 0;
}
class String {
class StringBuilder {
public:
String(DynamicJsonBufferBase* parent)
explicit StringBuilder(DynamicMemoryPoolBase* parent)
: _parent(parent), _start(NULL), _length(0) {}
void append(char c) {
@ -98,19 +102,19 @@ class DynamicJsonBufferBase : public JsonBuffer {
_length++;
}
const char* c_str() {
StringInMemoryPool complete() {
append(0);
return _start;
}
private:
DynamicJsonBufferBase* _parent;
DynamicMemoryPoolBase* _parent;
char* _start;
size_t _length;
};
String startString() {
return String(this);
StringBuilder startString() {
return StringBuilder(this);
}
private:
@ -152,12 +156,11 @@ class DynamicJsonBufferBase : public JsonBuffer {
size_t _nextBlockCapacity;
};
// Implements a JsonBuffer with dynamic memory allocation.
// You are strongly encouraged to consider using StaticJsonBuffer which is much
// Implements a MemoryPool with dynamic memory allocation.
// You are strongly encouraged to consider using StaticMemoryPool which is much
// more suitable for embedded systems.
typedef Internals::DynamicJsonBufferBase<Internals::DefaultAllocator>
DynamicJsonBuffer;
} // namespace Internals
typedef DynamicMemoryPoolBase<DefaultAllocator> DynamicMemoryPool;
} // namespace ARDUINOJSON_NAMESPACE
#if defined(__clang__)
#pragma clang diagnostic pop
@ -166,4 +169,3 @@ typedef Internals::DynamicJsonBufferBase<Internals::DefaultAllocator>
#pragma GCC diagnostic pop
#endif
#endif
} // namespace ArduinoJson

View File

@ -1,22 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonBuffer.hpp"
namespace ArduinoJson {
namespace Internals {
class JsonBufferAllocated {
public:
void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() {
if (!jsonBuffer) return NULL;
return jsonBuffer->alloc(n);
}
void operator delete(void *, JsonBuffer *)throw();
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -11,14 +11,13 @@
#include "../Configuration.hpp"
#include "../Polyfills/attributes.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// Handle the memory management (done in derived classes) and calls the parser.
// This abstract class is implemented by StaticJsonBuffer which implements a
// This abstract class is implemented by StaticMemoryPool which implements a
// fixed memory allocation.
class JsonBuffer {
class MemoryPool {
public:
// Allocates n bytes in the JsonBuffer.
// Allocates n bytes in the MemoryPool.
// Return a pointer to the allocated memory or NULL if allocation fails.
virtual void *alloc(size_t size) = 0;
@ -26,7 +25,7 @@ class JsonBuffer {
// CAUTION: NO VIRTUAL DESTRUCTOR!
// If we add a virtual constructor the Arduino compiler will add malloc()
// and free() to the binary, adding 706 useless bytes.
~JsonBuffer() {}
~MemoryPool() {}
// Preserve aligment if necessary
static FORCE_INLINE size_t round_size_up(size_t bytes) {
@ -38,5 +37,4 @@ class JsonBuffer {
#endif
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -5,16 +5,16 @@
#pragma once
#include "../Polyfills/mpl/max.hpp"
#include "JsonBuffer.hpp"
#include "../Strings/StringInMemoryPool.hpp"
#include "MemoryPool.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class StaticJsonBufferBase : public JsonBuffer {
class StaticMemoryPoolBase : public MemoryPool {
public:
class String {
class StringBuilder {
public:
String(StaticJsonBufferBase* parent) : _parent(parent) {
explicit StringBuilder(StaticMemoryPoolBase* parent) : _parent(parent) {
_start = parent->_buffer + parent->_size;
}
@ -25,7 +25,7 @@ class StaticJsonBufferBase : public JsonBuffer {
}
}
const char* c_str() const {
StringInMemoryPool complete() const {
if (_parent->canAlloc(1)) {
char* last = static_cast<char*>(_parent->doAlloc(1));
*last = '\0';
@ -36,42 +36,42 @@ class StaticJsonBufferBase : public JsonBuffer {
}
private:
StaticJsonBufferBase* _parent;
StaticMemoryPoolBase* _parent;
char* _start;
};
StaticJsonBufferBase(char* buffer, size_t capa)
: _buffer(buffer), _capacity(capa), _size(0) {}
// Gets the capacity of the buffer in bytes
// Gets the capacity of the memoryPool in bytes
size_t capacity() const {
return _capacity;
}
// Gets the current usage of the buffer in bytes
// Gets the current usage of the memoryPool in bytes
size_t size() const {
return _size;
}
// Allocates the specified amount of bytes in the buffer
// Allocates the specified amount of bytes in the memoryPool
virtual void* alloc(size_t bytes) {
alignNextAlloc();
if (!canAlloc(bytes)) return NULL;
return doAlloc(bytes);
}
// Resets the buffer.
// Resets the memoryPool.
// USE WITH CAUTION: this invalidates all previously allocated data
void clear() {
_size = 0;
}
String startString() {
return String(this);
StringBuilder startString() {
return StringBuilder(this);
}
protected:
~StaticJsonBufferBase() {}
StaticMemoryPoolBase(char* memoryPool, size_t capa)
: _buffer(memoryPool), _capacity(capa), _size(0) {}
~StaticMemoryPoolBase() {}
private:
void alignNextAlloc() {
@ -103,22 +103,21 @@ class StaticJsonBufferBase : public JsonBuffer {
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
// Implements a JsonBuffer with fixed memory allocation.
// The template paramenter CAPACITY specifies the capacity of the buffer in
// Implements a MemoryPool with fixed memory allocation.
// The template paramenter CAPACITY specifies the capacity of the memoryPool in
// bytes.
template <size_t CAPACITY>
class StaticJsonBuffer : public Internals::StaticJsonBufferBase {
static const size_t ACTUAL_CAPACITY = Internals::Max<1, CAPACITY>::value;
class StaticMemoryPool : public StaticMemoryPoolBase {
static const size_t ACTUAL_CAPACITY = Max<1, CAPACITY>::value;
public:
explicit StaticJsonBuffer()
: Internals::StaticJsonBufferBase(_buffer, ACTUAL_CAPACITY) {}
explicit StaticMemoryPool()
: StaticMemoryPoolBase(_buffer, ACTUAL_CAPACITY) {}
private:
char _buffer[ACTUAL_CAPACITY];
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE
#if defined(__clang__)
#pragma clang diagnostic pop

View File

@ -6,35 +6,37 @@
#include "../Deserialization/deserialize.hpp"
#include "../JsonVariant.hpp"
#include "../Memory/JsonBuffer.hpp"
#include "../Memory/MemoryPool.hpp"
#include "../Polyfills/type_traits.hpp"
#include "./endianess.hpp"
#include "./ieee754.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TReader, typename TStringStorage>
class MsgPackDeserializer {
typedef typename remove_reference<TStringStorage>::type::StringBuilder
StringBuilder;
public:
MsgPackDeserializer(JsonBuffer *buffer, TReader reader,
MsgPackDeserializer(MemoryPool &memoryPool, TReader reader,
TStringStorage stringStorage, uint8_t nestingLimit)
: _buffer(buffer),
: _memoryPool(&memoryPool),
_reader(reader),
_stringStorage(stringStorage),
_nestingLimit(nestingLimit) {}
DeserializationError parse(JsonVariant &variant) {
DeserializationError parse(JsonVariant variant) {
uint8_t code;
if (!readByte(code)) return DeserializationError::IncompleteInput;
if ((code & 0x80) == 0) {
variant = code;
variant.set(code);
return DeserializationError::Ok;
}
if ((code & 0xe0) == 0xe0) {
variant = static_cast<int8_t>(code);
variant.set(static_cast<int8_t>(code));
return DeserializationError::Ok;
}
@ -48,15 +50,15 @@ class MsgPackDeserializer {
switch (code) {
case 0xc0:
variant = static_cast<char *>(0);
// already null
return DeserializationError::Ok;
case 0xc2:
variant = false;
variant.set(false);
return DeserializationError::Ok;
case 0xc3:
variant = true;
variant.set(true);
return DeserializationError::Ok;
case 0xcc:
@ -69,7 +71,7 @@ class MsgPackDeserializer {
return readInteger<uint32_t>(variant);
case 0xcf:
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
#if ARDUINOJSON_USE_LONG_LONG
return readInteger<uint64_t>(variant);
#else
readInteger<uint32_t>();
@ -86,7 +88,7 @@ class MsgPackDeserializer {
return readInteger<int32_t>(variant);
case 0xd3:
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
#if ARDUINOJSON_USE_LONG_LONG
return readInteger<int64_t>(variant);
#else
if (!skip(4)) return DeserializationError::IncompleteInput;
@ -171,78 +173,76 @@ class MsgPackDeserializer {
}
template <typename T>
DeserializationError readInteger(JsonVariant &variant) {
DeserializationError readInteger(JsonVariant variant) {
T value;
if (!readInteger(value)) return DeserializationError::IncompleteInput;
variant = value;
variant.set(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, DeserializationError>::type readFloat(
JsonVariant &variant) {
JsonVariant variant) {
T value;
if (!readBytes(value)) return DeserializationError::IncompleteInput;
fixEndianess(value);
variant = value;
variant.set(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 8, DeserializationError>::type readDouble(
JsonVariant &variant) {
JsonVariant variant) {
T value;
if (!readBytes(value)) return DeserializationError::IncompleteInput;
fixEndianess(value);
variant = value;
variant.set(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, DeserializationError>::type readDouble(
JsonVariant &variant) {
JsonVariant variant) {
uint8_t i[8]; // input is 8 bytes
T value; // output is 4 bytes
uint8_t *o = reinterpret_cast<uint8_t *>(&value);
if (!readBytes(i, 8)) return DeserializationError::IncompleteInput;
doubleToFloat(i, o);
fixEndianess(value);
variant = value;
variant.set(value);
return DeserializationError::Ok;
}
template <typename T>
DeserializationError readString(JsonVariant &variant) {
DeserializationError readString(JsonVariant variant) {
T size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readString(variant, size);
}
DeserializationError readString(JsonVariant &variant, size_t n) {
typename remove_reference<TStringStorage>::type::String str =
_stringStorage.startString();
DeserializationError readString(JsonVariant variant, size_t n) {
StringBuilder str = _stringStorage.startString();
for (; n; --n) {
uint8_t c;
if (!readBytes(c)) return DeserializationError::IncompleteInput;
str.append(static_cast<char>(c));
}
const char *s = str.c_str();
if (s == NULL) return DeserializationError::NoMemory;
variant = s;
StringInMemoryPool s = str.complete();
if (s.isNull()) return DeserializationError::NoMemory;
variant.set(s);
return DeserializationError::Ok;
}
template <typename TSize>
DeserializationError readArray(JsonVariant &variant) {
DeserializationError readArray(JsonVariant variant) {
TSize size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readArray(variant, size);
}
DeserializationError readArray(JsonVariant &variant, size_t n) {
JsonArray array(_buffer);
DeserializationError readArray(JsonVariant variant, size_t n) {
JsonArray array = variant.to<JsonArray>();
if (array.isNull()) return DeserializationError::NoMemory;
variant = array;
return readArray(array, n);
}
@ -250,26 +250,27 @@ class MsgPackDeserializer {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {
JsonVariant variant;
DeserializationError err = parse(variant);
JsonVariant value = array.add();
if (value.isInvalid()) return DeserializationError::NoMemory;
DeserializationError err = parse(value);
if (err) return err;
if (!array.add(variant)) return DeserializationError::NoMemory;
}
++_nestingLimit;
return DeserializationError::Ok;
}
template <typename TSize>
DeserializationError readObject(JsonVariant &variant) {
DeserializationError readObject(JsonVariant variant) {
TSize size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readObject(variant, size);
}
DeserializationError readObject(JsonVariant &variant, size_t n) {
JsonObject object(_buffer);
DeserializationError readObject(JsonVariant variant, size_t n) {
JsonObject object = variant.to<JsonObject>();
if (object.isNull()) return DeserializationError::NoMemory;
variant = object;
return readObject(object, n);
}
@ -277,49 +278,45 @@ class MsgPackDeserializer {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {
DeserializationError err;
JsonVariant variant;
err = parse(variant);
JsonVariantLocal key(_memoryPool);
DeserializationError err = parse(key);
if (err) return err;
const char *key = variant.as<char *>();
if (!key) return DeserializationError::NotSupported;
err = parse(variant);
if (!key.is<char *>()) return DeserializationError::NotSupported;
JsonVariant value = object.set(StringInMemoryPool(key.as<char *>()));
if (value.isInvalid()) return DeserializationError::NoMemory;
err = parse(value);
if (err) return err;
if (!object.set(key, variant)) return DeserializationError::NoMemory;
}
++_nestingLimit;
return DeserializationError::Ok;
}
JsonBuffer *_buffer;
MemoryPool *_memoryPool;
TReader _reader;
TStringStorage _stringStorage;
uint8_t _nestingLimit;
};
} // namespace Internals
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, const TInput &input) {
using namespace Internals;
return deserialize<MsgPackDeserializer>(doc, input);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input) {
using namespace Internals;
return deserialize<MsgPackDeserializer>(doc, input);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input,
size_t inputSize) {
using namespace Internals;
return deserialize<MsgPackDeserializer>(doc, input, inputSize);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, TInput &input) {
using namespace Internals;
return deserialize<MsgPackDeserializer>(doc, input);
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -10,8 +10,7 @@
#include "../Serialization/serialize.hpp"
#include "./endianess.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class MsgPackSerializer {
@ -19,13 +18,13 @@ class MsgPackSerializer {
MsgPackSerializer(TWriter& writer) : _writer(&writer), _bytesWritten(0) {}
template <typename T>
typename enable_if<sizeof(T) == 4>::type acceptFloat(T value32) {
typename enable_if<sizeof(T) == 4>::type visitFloat(T value32) {
writeByte(0xCA);
writeInteger(value32);
}
template <typename T>
typename enable_if<sizeof(T) == 8>::type acceptFloat(T value64) {
typename enable_if<sizeof(T) == 8>::type visitFloat(T value64) {
float value32 = float(value64);
if (value32 == value64) {
writeByte(0xCA);
@ -36,7 +35,7 @@ class MsgPackSerializer {
}
}
void acceptArray(const JsonArray& array) {
void visitArray(JsonArrayConst array) {
size_t n = array.size();
if (n < 0x10) {
writeByte(uint8_t(0x90 + array.size()));
@ -47,13 +46,12 @@ class MsgPackSerializer {
writeByte(0xDD);
writeInteger(uint32_t(n));
}
for (JsonArray::const_iterator it = array.begin(); it != array.end();
++it) {
it->visit(*this);
for (JsonArrayConst::iterator it = array.begin(); it != array.end(); ++it) {
it->accept(*this);
}
}
void acceptObject(const JsonObject& object) {
void visitObject(JsonObjectConst object) {
size_t n = object.size();
if (n < 0x10) {
writeByte(uint8_t(0x80 + n));
@ -64,14 +62,14 @@ class MsgPackSerializer {
writeByte(0xDF);
writeInteger(uint32_t(n));
}
for (JsonObject::const_iterator it = object.begin(); it != object.end();
for (JsonObjectConst::iterator it = object.begin(); it != object.end();
++it) {
acceptString(it->key);
it->value.visit(*this);
visitString(it->key());
it->value().accept(*this);
}
}
void acceptString(const char* value) {
void visitString(const char* value) {
if (!value) return writeByte(0xC0); // nil
size_t n = strlen(value);
@ -91,11 +89,11 @@ class MsgPackSerializer {
writeBytes(reinterpret_cast<const uint8_t*>(value), n);
}
void acceptRawJson(const char* data, size_t size) {
void visitRawJson(const char* data, size_t size) {
writeBytes(reinterpret_cast<const uint8_t*>(data), size);
}
void acceptNegativeInteger(JsonUInt value) {
void visitNegativeInteger(JsonUInt value) {
JsonUInt negated = JsonUInt(~value + 1);
if (value <= 0x20) {
writeInteger(int8_t(negated));
@ -109,7 +107,7 @@ class MsgPackSerializer {
writeByte(0xD2);
writeInteger(int32_t(negated));
}
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
#if ARDUINOJSON_USE_LONG_LONG
else {
writeByte(0xD3);
writeInteger(int64_t(negated));
@ -117,7 +115,7 @@ class MsgPackSerializer {
#endif
}
void acceptPositiveInteger(JsonUInt value) {
void visitPositiveInteger(JsonUInt value) {
if (value <= 0x7F) {
writeInteger(uint8_t(value));
} else if (value <= 0xFF) {
@ -130,7 +128,7 @@ class MsgPackSerializer {
writeByte(0xCE);
writeInteger(uint32_t(value));
}
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
#if ARDUINOJSON_USE_LONG_LONG
else {
writeByte(0xCF);
writeInteger(uint64_t(value));
@ -138,11 +136,11 @@ class MsgPackSerializer {
#endif
}
void acceptBoolean(bool value) {
void visitBoolean(bool value) {
writeByte(value ? 0xC3 : 0xC2);
}
void acceptNull() {
void visitNull() {
writeByte(0xC0);
}
@ -168,25 +166,21 @@ class MsgPackSerializer {
TWriter* _writer;
size_t _bytesWritten;
};
} // namespace Internals
template <typename TSource, typename TDestination>
inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
using namespace Internals;
return serialize<MsgPackSerializer>(source, output);
}
template <typename TSource, typename TDestination>
inline size_t serializeMsgPack(const TSource& source, TDestination* output,
size_t size) {
using namespace Internals;
return serialize<MsgPackSerializer>(source, output, size);
}
template <typename TSource>
inline size_t measureMsgPack(const TSource& source) {
using namespace Internals;
return measure<MsgPackSerializer>(source);
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -7,8 +7,7 @@
#include "../Polyfills/type_traits.hpp"
#include "../Polyfills/utility.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 8>) {
swap(p[0], p[7]);
@ -36,5 +35,4 @@ inline void fixEndianess(T& value) {
#endif
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {
f[0] = uint8_t((d[0] & 0xC0) | (d[0] << 3 & 0x3f) | (d[1] >> 5));
@ -14,5 +13,4 @@ inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {
f[3] = uint8_t((d[3] << 3) | (d[4] >> 5));
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,22 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "version.hpp"
#include "Configuration.hpp"
#define ARDUINOJSON_DO_CONCAT(A, B) A##B
#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_DO_CONCAT(A, B)
#define ARDUINOJSON_CONCAT4(A, B, C, D) \
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
#define ARDUINOJSON_CONCAT8(A, B, C, D, E, F, G, H) \
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT4(A, B, C, D), \
ARDUINOJSON_CONCAT4(E, F, G, H))
#define ARDUINOJSON_NAMESPACE \
ARDUINOJSON_CONCAT8(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
ARDUINOJSON_VERSION_MINOR, ARDUINOJSON_VERSION_REVISION, \
_, ARDUINOJSON_USE_LONG_LONG, _, ARDUINOJSON_USE_DOUBLE)

View File

@ -8,8 +8,7 @@
#include "../Polyfills/math.hpp"
#include "./FloatTraits.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TFloat>
struct FloatParts {
@ -85,5 +84,4 @@ struct FloatParts {
return powersOf10;
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,13 +4,12 @@
#pragma once
#include <stddef.h> // for size_t
#include <stdint.h>
#include <stdlib.h> // for size_t
#include "../Configuration.hpp"
#include "../Polyfills/math.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename T, size_t = sizeof(T)>
struct FloatTraits {};
@ -167,5 +166,4 @@ struct FloatTraits<T, 4 /*32bits*/> {
return forge(0x7f800000);
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -7,8 +7,7 @@
#include <string.h> // for strcmp
#include "../Polyfills/ctype.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
inline bool isFloat(const char* s) {
if (!s) return false;
@ -34,5 +33,4 @@ inline bool isFloat(const char* s) {
return *s == '\0';
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,8 +6,7 @@
#include "../Polyfills/ctype.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
inline bool isInteger(const char* s) {
if (!s || !*s) return false;
@ -15,5 +14,4 @@ inline bool isInteger(const char* s) {
while (isdigit(*s)) s++;
return *s == '\0';
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,8 +8,7 @@
#include "../Polyfills/ctype.hpp"
#include "../Polyfills/math.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline T parseFloat(const char* s) {
@ -86,5 +85,4 @@ inline T parseFloat(const char* s) {
return negative_result ? -result : result;
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,13 +4,10 @@
#pragma once
#include <stdlib.h>
#include "../Configuration.hpp"
#include "../Polyfills/ctype.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
T parseInteger(const char *s) {
if (!s) return 0; // NULL
@ -37,5 +34,4 @@ T parseInteger(const char *s) {
return negative_result ? T(~result + 1) : result;
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -27,3 +27,9 @@
#define DEPRECATED(msg)
#endif
#if __cplusplus >= 201103L
#define NOEXCEPT noexcept
#else
#define NOEXCEPT throw()
#endif

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
inline bool isdigit(char c) {
return '0' <= c && c <= '9';
@ -14,5 +13,4 @@ inline bool isdigit(char c) {
inline bool issign(char c) {
return '-' == c || c == '+';
}
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// Some libraries #define isnan() and isinf() so we need to check before
// using this name
@ -23,5 +22,4 @@ bool isinf(T x) {
return x != 0.0 && x * 2 == x;
}
#endif
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,10 +4,9 @@
#pragma once
#include <stdlib.h> // for size_t
#include <stddef.h> // for size_t
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that returns the highest value
template <size_t X, size_t Y, bool MaxIsX = (X > Y)>
@ -22,5 +21,4 @@ template <size_t X, size_t Y>
struct Max<X, Y, false> {
static const size_t value = Y;
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that return the type T if Condition is true.
template <bool Condition, typename T = void>
@ -15,5 +14,4 @@ template <typename T>
struct enable_if<true, T> {
typedef T type;
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename T, T v>
struct integral_constant {
@ -15,5 +14,4 @@ struct integral_constant {
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
struct is_array : false_type {};
@ -15,5 +14,4 @@ struct is_array<T[]> : true_type {};
template <typename T, size_t N>
struct is_array<T[N]> : true_type {};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that returns true if Derived inherits from TBase is an
// integral type.
@ -19,9 +18,7 @@ class is_base_of {
static No &probe(...);
public:
enum {
value = sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes)
};
static const bool value =
sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes);
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,8 +6,7 @@
#include "integral_constant.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that return the type T without the const modifier
template <typename T>
@ -15,5 +14,4 @@ struct is_const : false_type {};
template <typename T>
struct is_const<const T> : true_type {};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,8 +6,7 @@
#include "integral_constant.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename>
struct is_floating_point : false_type {};
@ -17,5 +16,4 @@ struct is_floating_point<float> : true_type {};
template <>
struct is_floating_point<double> : true_type {};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,10 +4,10 @@
#pragma once
#include "../../Configuration.hpp"
#include "is_same.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that returns true if T is an integral type.
template <typename T>
@ -17,19 +17,19 @@ struct is_integral {
is_same<T, signed short>::value || is_same<T, unsigned short>::value ||
is_same<T, signed int>::value || is_same<T, unsigned int>::value ||
is_same<T, signed long>::value || is_same<T, unsigned long>::value ||
#if ARDUINOJSON_USE_LONG_LONG
is_same<T, unsigned long long>::value ||
#if ARDUINOJSON_HAS_LONG_LONG
is_same<T, signed long long>::value ||
is_same<T, unsigned long long>::value ||
#endif
#if ARDUINOJSON_USE_INT64
is_same<T, unsigned __int64>::value ||
#if ARDUINOJSON_HAS_INT64
is_same<T, signed __int64>::value ||
is_same<T, unsigned __int64>::value ||
#endif
is_same<T, char>::value;
// CAUTION: differs from std::is_integral as it doesn't include bool
};
template <typename T>
struct is_integral<const T> : is_integral<T> {};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,8 +6,7 @@
#include "integral_constant.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that returns true if types T and U are the same.
template <typename T, typename U>
@ -15,5 +14,4 @@ struct is_same : false_type {};
template <typename T>
struct is_same<T, T> : true_type {};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -5,8 +5,7 @@
#pragma once
#include "integral_constant.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename>
struct is_signed : false_type {};
@ -32,13 +31,13 @@ struct is_signed<float> : true_type {};
template <>
struct is_signed<double> : true_type {};
#if ARDUINOJSON_USE_LONG_LONG
#if ARDUINOJSON_HAS_LONG_LONG
template <>
struct is_signed<signed long long> : true_type {};
#endif
#if ARDUINOJSON_USE_INT64
#if ARDUINOJSON_HAS_INT64
template <>
struct is_signed<signed __int64> : true_type {};
#endif
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -5,8 +5,7 @@
#pragma once
#include "integral_constant.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename>
struct is_unsigned : false_type {};
@ -26,13 +25,13 @@ struct is_unsigned<unsigned int> : true_type {};
template <>
struct is_unsigned<unsigned long> : true_type {};
#if ARDUINOJSON_USE_LONG_LONG
template <>
struct is_unsigned<unsigned long long> : true_type {};
#endif
#if ARDUINOJSON_USE_INT64
#if ARDUINOJSON_HAS_INT64
template <>
struct is_unsigned<unsigned __int64> : true_type {};
#endif
} // namespace Internals
} // namespace ArduinoJson
#if ARDUINOJSON_HAS_LONG_LONG
template <>
struct is_unsigned<unsigned long long> : true_type {};
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that return the type T without the const modifier
template <typename T>
@ -16,5 +15,4 @@ template <typename T>
struct remove_const<const T> {
typedef T type;
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// A meta-function that return the type T without the reference modifier.
template <typename T>
@ -16,5 +15,4 @@ template <typename T>
struct remove_reference<T&> {
typedef T type;
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,13 +4,11 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline void swap(T& a, T& b) {
T t(a);
a = b;
b = t;
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class DummyWriter {
public:
@ -17,5 +16,4 @@ class DummyWriter {
return n;
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -14,8 +14,7 @@
#include <string>
#endif
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename>
struct IsWriteableString : false_type {};
@ -77,5 +76,4 @@ class DynamicStringWriter<std::string> {
std::string *_str;
};
#endif
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,8 +4,7 @@
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
// A Print implementation that allows to write in a char[]
class StaticStringWriter {
@ -35,5 +34,4 @@ class StaticStringWriter {
char *end;
char *p;
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

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