Return JsonArray and JsonObject by value (closes #309)

This commit is contained in:
Benoit Blanchon
2018-07-02 09:35:21 +02:00
parent 4fe2b1100e
commit b105e6f7c4
93 changed files with 983 additions and 1091 deletions

View File

@ -7,13 +7,20 @@
#include "ArduinoJson/version.hpp"
#include "ArduinoJson/DynamicJsonDocument.hpp"
#include "ArduinoJson/StaticJsonDocument.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/JsonArrayImpl.hpp"
#include "ArduinoJson/JsonArraySubscript.hpp"
#include "ArduinoJson/JsonObjectSubscript.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp"
#include "ArduinoJson/Json/JsonDeserializer.hpp"
#include "ArduinoJson/Json/JsonSerializer.hpp"
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
#include "ArduinoJson/StaticJsonDocument.hpp"
#include "ArduinoJson/JsonArrayImpl.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp"

View File

@ -19,24 +19,5 @@ struct JsonVariantAs<char*> {
typedef const char* type;
};
template <>
struct JsonVariantAs<JsonArray> {
typedef JsonArray& type;
};
template <>
struct JsonVariantAs<const JsonArray> {
typedef const JsonArray& type;
};
template <>
struct JsonVariantAs<JsonObject> {
typedef JsonObject& type;
};
template <>
struct JsonVariantAs<const JsonObject> {
typedef const JsonObject& type;
};
}
}
} // namespace Internals
} // namespace ArduinoJson

View File

@ -8,20 +8,19 @@
#include "JsonInteger.hpp"
namespace ArduinoJson {
// Forward declarations
class JsonArray;
class JsonObject;
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
const char* asString; // asString can be null
JsonArray* asArray; // asArray cannot be null
JsonObject* asObject; // asObject cannot be null
JsonFloat asFloat; // used for double and float
JsonUInt asInteger; // used for bool, char, short, int and longs
const char* asString; // asString can be null
JsonArrayData* asArray; // asArray cannot be null
JsonObjectData* asObject; // asObject cannot be null
};
}
}
} // namespace Internals
} // namespace ArduinoJson

View File

@ -5,8 +5,6 @@
#pragma once
namespace ArduinoJson {
class JsonArray;
class JsonObject;
namespace Internals {
@ -19,9 +17,9 @@ enum JsonVariantType {
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 JsonArray
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
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

@ -13,7 +13,7 @@ namespace Internals {
// A singly linked list of T.
// The linked list is composed of ListNode<T>.
// It is derived by JsonArray and JsonObject
// It is derived by JsonArrayData and JsonObjectData
template <typename T>
class List {
public:
@ -22,23 +22,10 @@ class List {
typedef ListIterator<T> iterator;
typedef ListConstIterator<T> const_iterator;
// Creates an empty List<T> attached to a JsonBuffer.
// The JsonBuffer allows to allocate new nodes.
// When buffer is NULL, the List is not able to grow and success() returns
// false. This is used to identify bad memory allocations and parsing
// failures.
explicit List(JsonBuffer *buf) : _buffer(buf), _firstNode(NULL) {}
// Returns true if the object is valid
// Would return false in the following situation:
// - the memory allocation failed (StaticJsonBuffer was too small)
// - the JSON parsing failed
bool success() const {
return _buffer != NULL;
}
// Returns the numbers of elements in the list.
// For a JsonObject, it would return the number of key-value pairs
// 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++;
@ -87,14 +74,13 @@ class List {
JsonBuffer &buffer() const {
return *_buffer;
}
JsonBuffer *_buffer; // TODO!!
protected:
void clear() {
_firstNode = 0;
}
JsonBuffer *_buffer;
private:
node_type *_firstNode;
};

View File

@ -1,24 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
// A type that is meant to be used by reference only (JsonArray and JsonObject)
class ReferenceType {
public:
bool operator==(const ReferenceType& other) const {
// two JsonArray are equal if they are the same instance
// (we don't compare the content)
return this == &other;
}
bool operator!=(const ReferenceType& other) const {
return this != &other;
}
};
}
}

View File

@ -32,28 +32,26 @@ class DynamicJsonDocument {
return _root.as<T>();
}
// JsonObject& to<JsonObject>()
// JsonObject to<JsonObject>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonObject>::value,
JsonObject&>::type
JsonObject>::type
to() {
clear();
JsonObject* object = new (&_buffer) JsonObject(&_buffer);
if (!object) return JsonObject::invalid();
JsonObject object(&_buffer);
_root = object;
return *object;
return object;
}
// JsonArray& to<JsonArray>()
// JsonArray to<JsonArray>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonArray>::value,
JsonArray&>::type
JsonArray>::type
to() {
clear();
JsonArray* array = new (&_buffer) JsonArray(&_buffer);
if (!array) return JsonArray::invalid();
JsonArray array(&_buffer);
_root = array;
return *array;
return array;
}
// JsonVariant& to<JsonVariant>()

View File

@ -66,8 +66,8 @@ class JsonDeserializer {
DeserializationError parseArray(JsonVariant &variant) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return DeserializationError::NoMemory;
JsonArray array(_buffer);
if (array.isNull()) return DeserializationError::NoMemory;
variant = array;
// Check opening braket
@ -88,7 +88,7 @@ class JsonDeserializer {
err = parse(value);
_nestingLimit++;
if (err) return err;
if (!array->add(value)) return DeserializationError::NoMemory;
if (!array.add(value)) return DeserializationError::NoMemory;
// 2 - Skip spaces
err = skipSpacesAndComments();
@ -103,8 +103,8 @@ class JsonDeserializer {
DeserializationError parseObject(JsonVariant &variant) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return DeserializationError::NoMemory;
JsonObject object(_buffer);
if (object.isNull()) return DeserializationError::NoMemory;
variant = object;
// Check opening brace
@ -126,9 +126,7 @@ class JsonDeserializer {
// Skip spaces
err = skipSpacesAndComments();
if (err) return err;
// Colon
if (err) return err; // Colon
if (!eat(':')) return DeserializationError::InvalidInput;
// Parse value
@ -137,7 +135,7 @@ class JsonDeserializer {
err = parse(value);
_nestingLimit++;
if (err) return err;
if (!object->set(key, value)) return DeserializationError::NoMemory;
if (!object.set(key, value)) return DeserializationError::NoMemory;
// Skip spaces
err = skipSpacesAndComments();

View File

@ -75,7 +75,9 @@ class JsonSerializer {
_writer.writeBoolean(value);
}
void acceptUndefined() {}
void acceptNull() {
_writer.writeRaw("null");
}
size_t bytesWritten() const {
return _writer.bytesWritten();

View File

@ -13,13 +13,6 @@
namespace ArduinoJson {
namespace Internals {
// Writes the JSON tokens to a Print implementation
// This class is used by:
// - JsonArray::writeTo()
// - JsonObject::writeTo()
// - JsonVariant::writeTo()
// Its derived by PrettyJsonWriter that overrides some members to add
// indentation.
template <typename Print>
class JsonWriter {
public:

View File

@ -4,91 +4,126 @@
#pragma once
#include "Data/List.hpp"
#include "Data/ReferenceType.hpp"
#include "Data/ValueSaver.hpp"
#include "JsonVariant.hpp"
#include "Memory/JsonBufferAllocated.hpp"
#include "Polyfills/type_traits.hpp"
#include "Strings/StringTraits.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(JsonArray) + (NUMBER_OF_ELEMENTS) * sizeof(JsonArray::node_type))
#include "./JsonArrayData.hpp"
namespace ArduinoJson {
// Forward declarations
class JsonObject;
class JsonBuffer;
namespace Internals {
class JsonArraySubscript;
}
class JsonArray : public Internals::ReferenceType,
public Internals::NonCopyable,
public Internals::List<JsonVariant>,
public Internals::JsonBufferAllocated {
class JsonArray {
friend class JsonVariant;
public:
explicit JsonArray(Internals::JsonBuffer *buf) throw()
: Internals::List<JsonVariant>(buf) {}
typedef Internals::JsonArrayData::iterator iterator;
typedef Internals::JsonArrayData::const_iterator const_iterator;
// Gets the value at the specified index
const Internals::JsonArraySubscript operator[](size_t index) const;
// Gets or sets the value at specified index
Internals::JsonArraySubscript operator[](size_t index);
JsonArray() : _data(0) {}
JsonArray(Internals::JsonArrayData* arr) : _data(arr) {}
JsonArray(Internals::JsonBuffer* buf)
: _data(new (buf) Internals::JsonArrayData(buf)) {}
// Adds the specified value at the end of the array.
//
// bool add(TValue);
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
// std::string, String, JsonArray, JsonObject
// std::string, String, JsonArrayData, JsonObject
template <typename T>
bool add(const T &value) {
return add_impl<const T &>(value);
bool add(const T& value) {
return add_impl<const T&>(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
bool add(T *value) {
return add_impl<T *>(value);
}
//
// bool add(TValue value, uint8_t decimals);
// TValue = float, double
template <typename T>
DEPRECATED("Second argument is not supported anymore")
bool add(T value, uint8_t) {
return add_impl<const JsonVariant &>(JsonVariant(value));
bool add(T* value) {
return add_impl<T*>(value);
}
// Sets the value at specified index.
//
// bool add(size_t index, const TValue&);
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename T>
bool set(size_t index, const T &value) {
return set_impl<const T &>(index, value);
iterator begin() {
if (!_data) return iterator();
return _data->begin();
}
//
// bool add(size_t index, TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
bool set(size_t index, T *value) {
return set_impl<T *>(index, value);
const_iterator begin() const {
if (!_data) return const_iterator();
return _data->begin();
}
//
// bool set(size_t index, TValue value, uint8_t decimals);
// TValue = float, double
iterator end() {
return iterator();
}
const_iterator end() const {
return const_iterator();
}
// Imports a 1D array
template <typename T, size_t N>
bool copyFrom(T (&array)[N]) {
return copyFrom(array, N);
}
// Imports a 1D array
template <typename T>
typename Internals::enable_if<Internals::is_floating_point<T>::value,
bool>::type
set(size_t index, T value, uint8_t decimals) {
return set_impl<const JsonVariant &>(index, JsonVariant(value, decimals));
bool copyFrom(T* array, size_t len) {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= add(array[i]);
}
return ok;
}
// Imports a 2D array
template <typename T, size_t N1, size_t N2>
bool copyFrom(T (&array)[N1][N2]) {
bool ok = true;
for (size_t i = 0; i < N1; i++) {
JsonArray nestedArray = createNestedArray();
for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(array[i][j]);
}
}
return ok;
}
// Exports a 1D array
template <typename T, size_t N>
size_t copyTo(T (&array)[N]) const {
return copyTo(array, N);
}
// Exports a 1D array
template <typename T>
size_t copyTo(T* array, size_t len) const {
size_t i = 0;
for (const_iterator it = begin(); it != end() && i < len; ++it)
array[i++] = *it;
return i;
}
// Exports a 2D array
template <typename T, size_t N1, size_t N2>
void copyTo(T (&array)[N1][N2]) const {
if (!_data) return;
size_t i = 0;
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
it->as<JsonArray>().copyTo(array[i++]);
}
}
JsonArray createNestedArray();
JsonObject createNestedObject();
Internals::JsonArraySubscript operator[](size_t index);
const Internals::JsonArraySubscript operator[](size_t index) const;
bool operator==(const JsonArray& rhs) const {
return _data == rhs._data;
}
// Gets the value at the specified index.
@ -105,82 +140,51 @@ class JsonArray : public Internals::ReferenceType,
return it != end() ? it->is<T>() : false;
}
// Creates a JsonArray and adds a reference at the end of the array.
JsonArray &createNestedArray();
// Creates a JsonObject and adds a reference at the end of the array.
JsonObject &createNestedObject();
// Removes element at specified position.
void remove(iterator it) {
if (!_data) return;
_data->remove(it);
}
// Removes element at specified index.
void remove(size_t index) {
remove(begin() += index);
}
using Internals::List<JsonVariant>::remove;
// Returns a reference an invalid JsonArray.
// This object is meant to replace a NULL pointer.
// This is used when memory allocation or JSON parsing fail.
static JsonArray &invalid() {
static JsonArray instance(NULL);
return instance;
}
// Imports a 1D array
template <typename T, size_t N>
bool copyFrom(T (&array)[N]) {
return copyFrom(array, N);
}
// Imports a 1D array
// Sets the value at specified index.
//
// bool add(size_t index, const TValue&);
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
// std::string, String, JsonArrayData, JsonObject
template <typename T>
bool copyFrom(T *array, size_t len) {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= add(array[i]);
}
return ok;
bool set(size_t index, const T& value) {
if (!_data) return false;
return set_impl<const T&>(index, value);
}
// Imports a 2D array
template <typename T, size_t N1, size_t N2>
bool copyFrom(T (&array)[N1][N2]) {
bool ok = true;
for (size_t i = 0; i < N1; i++) {
JsonArray &nestedArray = createNestedArray();
for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(array[i][j]);
}
}
return ok;
}
// Exports a 1D array
template <typename T, size_t N>
size_t copyTo(T (&array)[N]) const {
return copyTo(array, N);
}
// Exports a 1D array
//
// bool add(size_t index, TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
size_t copyTo(T *array, size_t len) const {
size_t i = 0;
for (const_iterator it = begin(); it != end() && i < len; ++it)
array[i++] = *it;
return i;
bool set(size_t index, T* value) {
if (!_data) return false;
return set_impl<T*>(index, value);
}
// Exports a 2D array
template <typename T, size_t N1, size_t N2>
void copyTo(T (&array)[N1][N2]) const {
size_t i = 0;
for (const_iterator it = begin(); it != end() && i < N1; ++it) {
it->as<JsonArray>().copyTo(array[i++]);
}
size_t size() const {
if (!_data) return 0;
return _data->size();
}
bool isNull() const {
return _data == 0;
}
template <typename Visitor>
void visit(Visitor &visitor) const {
return visitor.acceptArray(*this);
void visit(Visitor& visitor) const {
if (_data)
return visitor.acceptArray(*this);
else
visitor.acceptNull();
}
private:
@ -188,23 +192,17 @@ class JsonArray : public Internals::ReferenceType,
bool set_impl(size_t index, TValueRef value) {
iterator it = begin() += index;
if (it == end()) return false;
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, *it, value);
}
template <typename TValueRef>
bool add_impl(TValueRef value) {
iterator it = Internals::List<JsonVariant>::add();
if (!_data) return false;
iterator it = _data->add();
if (it == end()) return false;
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, *it, value);
}
};
namespace Internals {
template <>
struct JsonVariantDefault<JsonArray> {
static JsonArray &get() {
return JsonArray::invalid();
}
Internals::JsonArrayData* _data;
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -0,0 +1,27 @@
// 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"
#include "Strings/StringTraits.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

@ -5,24 +5,21 @@
#pragma once
#include "JsonArray.hpp"
#include "JsonArraySubscript.hpp"
#include "JsonObject.hpp"
namespace ArduinoJson {
inline JsonArray &JsonArray::createNestedArray() {
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return JsonArray::invalid();
add(array);
return *array;
inline JsonArray JsonArray::createNestedArray() {
if (!_data) return JsonArray();
JsonArray array(_data->_buffer);
if (!array.isNull()) add(array);
return array;
}
inline JsonObject &JsonArray::createNestedObject() {
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return JsonObject::invalid();
add(object);
return *object;
inline JsonObject JsonArray::createNestedObject() {
if (!_data) return JsonObject();
JsonObject object(_data->_buffer);
if (!object.isNull()) add(object);
return object;
}
} // namespace ArduinoJson

View File

@ -16,7 +16,7 @@ namespace ArduinoJson {
namespace Internals {
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
public:
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
: _array(array), _index(index) {}
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
@ -43,8 +43,8 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
return *this;
}
FORCE_INLINE bool success() const {
return _index < _array.size();
FORCE_INLINE bool isNull() const {
return _index >= _array.size();
}
template <typename T>
@ -80,7 +80,7 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
}
private:
JsonArray& _array;
JsonArray _array;
const size_t _index;
};
@ -103,7 +103,7 @@ inline Internals::JsonArraySubscript JsonArray::operator[](size_t index) {
inline const Internals::JsonArraySubscript JsonArray::operator[](
size_t index) const {
return Internals::JsonArraySubscript(*const_cast<JsonArray*>(this), index);
return Internals::JsonArraySubscript(*this, index);
}
} // namespace ArduinoJson

View File

@ -4,110 +4,82 @@
#pragma once
#include "Data/List.hpp"
#include "Data/ReferenceType.hpp"
#include "Data/ValueSaver.hpp"
#include "JsonPair.hpp"
#include "Memory/JsonBufferAllocated.hpp"
#include "Polyfills/type_traits.hpp"
#include "Strings/StringTraits.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(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type))
#include "./JsonObjectData.hpp"
namespace ArduinoJson {
// Forward declarations
class JsonArray;
class JsonBuffer;
namespace Internals {
template <typename>
class JsonObjectSubscript;
}
class JsonObject {
friend class JsonVariant;
class JsonObject : public Internals::ReferenceType,
public Internals::NonCopyable,
public Internals::List<JsonPair>,
public Internals::JsonBufferAllocated {
public:
// Create an empty JsonArray attached to the specified JsonBuffer.
// You should not use this constructor directly.
explicit JsonObject(Internals::JsonBuffer* buf) throw()
: Internals::List<JsonPair>(buf) {}
typedef Internals::JsonObjectData::iterator iterator;
typedef Internals::JsonObjectData::const_iterator const_iterator;
// Gets or sets the value associated with the specified key.
//
// JsonObjectSubscript operator[](TKey)
// TKey = const std::string&, const String&
template <typename TString>
Internals::JsonObjectSubscript<const TString&> operator[](
const TString& key) {
return Internals::JsonObjectSubscript<const TString&>(*this, key);
}
//
// JsonObjectSubscript operator[](TKey)
// TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
template <typename TString>
Internals::JsonObjectSubscript<TString*> operator[](TString* key) {
return Internals::JsonObjectSubscript<TString*>(*this, key);
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();
}
// 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&>(
*const_cast<JsonObject*>(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*>(
*const_cast<JsonObject*>(this), key);
const_iterator begin() const {
if (!_data) return const_iterator();
return _data->begin();
}
// Sets the specified key with the specified value.
// Tells weither the specified key is present and associated with a value.
//
// bool set(TKey, TValue);
// bool containsKey(TKey);
// TKey = const std::string&, const String&
// TValue = bool, long, int, short, float, double, RawJson, 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 TString>
bool containsKey(const TString& key) const {
return containsKey_impl<const TString&>(key);
}
//
// bool set(TKey, TValue);
// bool containsKey(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TString>
bool containsKey(TString* key) const {
return containsKey_impl<TString*>(key);
}
iterator end() {
return iterator();
}
const_iterator end() const {
return const_iterator();
}
// Creates and adds a JsonArray.
//
// JsonArray createNestedArray(TKey);
// TKey = const std::string&, const String&
// 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 TString>
JsonArray createNestedArray(const TString& key);
// JsonArray createNestedArray(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TString>
JsonArray createNestedArray(TString* key);
// Creates and adds a JsonObject.
//
// JsonObject createNestedObject(TKey);
// TKey = const std::string&, const String&
template <typename TString>
JsonObject createNestedObject(const TString& key) {
if (!_data) return JsonObject();
return createNestedObject_impl<const TString&>(key);
}
//
// bool set(TKey, const TValue&);
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
bool set(TString* key, const TValue& value) {
return set_impl<TString*, const TValue&>(key, value);
}
//
// bool set(TKey, TValue);
// TKey = char*, const char*, const FlashStringHelper*
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue, typename TString>
bool set(TString* key, TValue* value) {
return set_impl<TString*, TValue*>(key, value);
// JsonObject createNestedObject(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TString>
JsonObject createNestedObject(TString* key) {
return createNestedObject_impl<TString*>(key);
}
// Gets the value associated with the specified key.
@ -152,51 +124,48 @@ class JsonObject : public Internals::ReferenceType,
return is_impl<TString*, TValue>(key);
}
// Creates and adds a JsonArray.
// Gets or sets the value associated with the specified key.
//
// JsonArray& createNestedArray(TKey);
// JsonObjectSubscript operator[](TKey)
// TKey = const std::string&, const String&
template <typename TString>
JsonArray& createNestedArray(const TString& key) {
return createNestedArray_impl<const TString&>(key);
Internals::JsonObjectSubscript<const TString&> operator[](
const TString& key) {
return Internals::JsonObjectSubscript<const TString&>(*this, key);
}
// JsonArray& createNestedArray(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
//
// JsonObjectSubscript operator[](TKey)
// TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
template <typename TString>
JsonArray& createNestedArray(TString* key) {
return createNestedArray_impl<TString*>(key);
Internals::JsonObjectSubscript<TString*> operator[](TString* key) {
return Internals::JsonObjectSubscript<TString*>(*this, key);
}
// Creates and adds a JsonObject.
// Gets the value associated with the specified key.
//
// JsonObject& createNestedObject(TKey);
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
JsonObject& createNestedObject(const TString& key) {
return createNestedObject_impl<const TString&>(key);
const Internals::JsonObjectSubscript<const TString&> operator[](
const TString& key) const {
return Internals::JsonObjectSubscript<const TString&>(*this, key);
}
//
// JsonObject& createNestedObject(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
JsonObject& createNestedObject(TString* key) {
return createNestedObject_impl<TString*>(key);
const Internals::JsonObjectSubscript<TString*> operator[](
TString* key) const {
return Internals::JsonObjectSubscript<TString*>(*this, key);
}
// 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 findKey<const TString&>(key) != end();
bool operator==(const JsonObject& rhs) const {
return _data == rhs._data;
}
//
// bool containsKey(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TString>
bool containsKey(TString* key) const {
return findKey<TString*>(key) != end();
void remove(iterator it) {
if (!_data) return;
_data->remove(it);
}
// Removes the specified key and the associated value.
@ -205,33 +174,81 @@ class JsonObject : public Internals::ReferenceType,
// TKey = const std::string&, const String&
template <typename TString>
void remove(const TString& key) {
remove(findKey<const TString&>(key));
remove_impl<const TString&>(key);
}
//
// void remove(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TString>
void remove(TString* key) {
remove(findKey<TString*>(key));
remove_impl<TString*>(key);
}
// Sets the specified key with the specified value.
//
// bool set(TKey, TValue);
// TKey = const std::string&, const String&
// TValue = bool, long, int, short, float, double, RawJson, 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);
}
//
// void remove(iterator)
using Internals::List<JsonPair>::remove;
// bool set(TKey, TValue);
// TKey = const std::string&, const String&
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue, typename TString>
bool set(const TString& key, TValue* value) {
return set_impl<const TString&, TValue*>(key, value);
}
//
// bool set(TKey, const TValue&);
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
bool set(TString* key, const TValue& value) {
return set_impl<TString*, const TValue&>(key, value);
}
//
// bool set(TKey, TValue);
// TKey = char*, const char*, const FlashStringHelper*
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue, typename TString>
bool set(TString* key, TValue* value) {
return set_impl<TString*, TValue*>(key, value);
}
// Returns a reference an invalid JsonObject.
// This object is meant to replace a NULL pointer.
// This is used when memory allocation or JSON parsing fail.
static JsonObject& invalid() {
static JsonObject instance(NULL);
return instance;
size_t size() const {
if (!_data) return 0;
return _data->size();
}
bool isNull() const {
return _data == 0;
}
template <typename Visitor>
void visit(Visitor& visitor) const {
return visitor.acceptObject(*this);
if (_data)
visitor.acceptObject(*this);
else
return visitor.acceptNull();
}
private:
template <typename TStringRef>
bool containsKey_impl(TStringRef key) const {
return findKey<TStringRef>(key) != end();
}
template <typename TStringRef>
JsonArray createNestedArray_impl(TStringRef key);
template <typename TStringRef>
JsonObject createNestedObject_impl(TStringRef key);
// Returns the list node that matches the specified key.
template <typename TStringRef>
iterator findKey(TStringRef key) {
@ -254,26 +271,6 @@ class JsonObject : public Internals::ReferenceType,
: Internals::JsonVariantDefault<TValue>::get();
}
template <typename TStringRef, typename TValueRef>
bool set_impl(TStringRef key, TValueRef value) {
// ignore null key
if (Internals::StringTraits<TStringRef>::is_null(key)) return false;
// search a matching key
iterator it = findKey<TStringRef>(key);
if (it == end()) {
// add the key
it = Internals::List<JsonPair>::add();
if (it == end()) return false;
bool key_ok =
Internals::ValueSaver<TStringRef>::save(_buffer, it->key, key);
if (!key_ok) return false;
}
// save the value
return Internals::ValueSaver<TValueRef>::save(_buffer, it->value, value);
}
template <typename TStringRef, typename TValue>
bool is_impl(TStringRef key) const {
const_iterator it = findKey<TStringRef>(key);
@ -281,18 +278,34 @@ class JsonObject : public Internals::ReferenceType,
}
template <typename TStringRef>
JsonArray& createNestedArray_impl(TStringRef key);
template <typename TStringRef>
JsonObject& createNestedObject_impl(TStringRef key);
};
namespace Internals {
template <>
struct JsonVariantDefault<JsonObject> {
static JsonObject& get() {
return JsonObject::invalid();
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::StringTraits<TStringRef>::is_null(key)) return false;
// search a matching key
iterator it = findKey<TStringRef>(key);
if (it == end()) {
// add the key
it = _data->add();
if (it == end()) return false;
bool key_ok =
Internals::ValueSaver<TStringRef>::save(_data->_buffer, it->key, key);
if (!key_ok) return false;
}
// save the value
return Internals::ValueSaver<TValueRef>::save(_data->_buffer, it->value,
value);
}
Internals::JsonObjectData* _data;
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -0,0 +1,27 @@
// 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"
#include "Strings/StringTraits.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

@ -6,23 +6,32 @@
#include "JsonArray.hpp"
#include "JsonObject.hpp"
#include "JsonObjectSubscript.hpp"
namespace ArduinoJson {
template <typename TStringRef>
inline JsonArray &JsonObject::createNestedArray_impl(TStringRef key) {
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return JsonArray::invalid();
set(key, array);
return *array;
template <typename TString>
inline JsonArray JsonObject::createNestedArray(const TString& key) {
return createNestedArray_impl<const TString&>(key);
}
template <typename TString>
inline JsonArray JsonObject::createNestedArray(TString* key) {
return createNestedArray_impl<TString*>(key);
}
template <typename TStringRef>
inline JsonObject &JsonObject::createNestedObject_impl(TStringRef key) {
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return JsonObject::invalid();
set(key, object);
return *object;
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

View File

@ -22,10 +22,10 @@ class JsonObjectSubscript
typedef JsonObjectSubscript<TStringRef> this_type;
public:
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TStringRef key)
FORCE_INLINE JsonObjectSubscript(JsonObject object, TStringRef key)
: _object(object), _key(key) {}
FORCE_INLINE this_type& operator=(const this_type& src) {
FORCE_INLINE this_type &operator=(const this_type &src) {
_object.set(_key, src);
return *this;
}
@ -36,8 +36,8 @@ class JsonObjectSubscript
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type&>::type
operator=(const TValue& src) {
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
operator=(const TValue &src) {
_object.set(_key, src);
return *this;
}
@ -45,13 +45,13 @@ class JsonObjectSubscript
// operator=(TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE this_type& operator=(TValue* src) {
FORCE_INLINE this_type &operator=(TValue *src) {
_object.set(_key, src);
return *this;
}
FORCE_INLINE bool success() const {
return _object.containsKey(_key);
FORCE_INLINE bool isNull() const {
return !_object.containsKey(_key);
}
template <typename TValue>
@ -71,26 +71,59 @@ class JsonObjectSubscript
// std::string, String, JsonArray, JsonObject
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
const TValue& value) {
const TValue &value) {
return _object.set(_key, value);
}
//
// bool set(TValue);
// TValue = char*, const char, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(const TValue* value) {
FORCE_INLINE bool set(const TValue *value) {
return _object.set(_key, value);
}
template <typename Visitor>
void visit(Visitor& visitor) const {
void visit(Visitor &visitor) const {
return _object.get<JsonVariant>(_key).visit(visitor);
}
private:
JsonObject& _object;
JsonObject _object;
TStringRef _key;
};
template <typename TImpl>
template <typename TString>
inline typename enable_if<StringTraits<TString>::has_equals,
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<StringTraits<TString>::has_equals,
JsonObjectSubscript<const TString &> >::type
JsonVariantSubscripts<TImpl>::operator[](const TString &key) {
return impl()->template as<JsonObject>()[key];
}
template <typename TImpl>
template <typename TString>
inline typename enable_if<StringTraits<const TString *>::has_equals,
JsonObjectSubscript<const TString *> >::type
JsonVariantSubscripts<TImpl>::operator[](const TString *key) {
return impl()->template as<JsonObject>()[key];
}
template <typename TImpl>
template <typename TString>
inline typename enable_if<StringTraits<TString *>::has_equals,
const JsonObjectSubscript<const TString *> >::type
JsonVariantSubscripts<TImpl>::operator[](const TString *key) const {
return impl()->template as<JsonObject>()[key];
}
} // namespace Internals
} // namespace ArduinoJson

View File

@ -8,9 +8,9 @@
namespace ArduinoJson {
// A key value pair for JsonObject.
// A key value pair for JsonObjectData.
struct JsonPair {
const char* key;
JsonVariant value;
};
}
} // namespace ArduinoJson

View File

@ -104,25 +104,8 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
_content.asString = value;
}
// Create a JsonVariant containing a reference to an array.
// CAUTION: we are lying about constness, because the array can be modified if
// the variant is converted back to a JsonArray&
JsonVariant(const JsonArray &array);
// Create a JsonVariant containing a reference to an object.
// CAUTION: we are lying about constness, because the object can be modified
// if the variant is converted back to a JsonObject&
JsonVariant(const JsonObject &object);
JsonVariant(JsonArray *array) {
_content.asArray = array;
_type = Internals::JSON_ARRAY;
}
JsonVariant(JsonObject *object) {
_content.asObject = object;
_type = Internals::JSON_OBJECT;
}
JsonVariant(JsonArray array);
JsonVariant(JsonObject object);
// Get the variant as the specified type.
//
@ -179,48 +162,23 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
return s;
}
//
// JsonArray& as<JsonArray> const;
// JsonArray& as<JsonArray&> const;
// JsonArray as<JsonArray>() const;
// const JsonArray as<const JsonArray>() const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<typename Internals::remove_reference<T>::type,
Internals::is_same<typename Internals::remove_const<T>::type,
JsonArray>::value,
JsonArray &>::type
as() const {
return variantAsArray();
}
JsonArray>::type
as() const;
//
// const JsonArray& as<const JsonArray&> const;
// JsonObject as<JsonObject>() const;
// const JsonObject as<const JsonObject>() const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<typename Internals::remove_reference<T>::type,
const JsonArray>::value,
const JsonArray &>::type
as() const {
return variantAsArray();
}
//
// JsonObject& as<JsonObject> const;
// JsonObject& as<JsonObject&> const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<typename Internals::remove_reference<T>::type,
Internals::is_same<typename Internals::remove_const<T>::type,
JsonObject>::value,
JsonObject &>::type
as() const {
return variantAsObject();
}
//
// JsonObject& as<const JsonObject> const;
// JsonObject& as<const JsonObject&> const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<typename Internals::remove_reference<T>::type,
const JsonObject>::value,
const JsonObject &>::type
as() const {
return variantAsObject();
}
T>::type
as() const;
//
// JsonVariant as<JsonVariant> const;
template <typename T>
@ -275,36 +233,30 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
}
//
// bool is<JsonArray> const;
// bool is<JsonArray&> const;
// bool is<const JsonArray&> const;
// bool is<const JsonArray> const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<
typename Internals::remove_const<
typename Internals::remove_reference<T>::type>::type,
JsonArray>::value,
Internals::is_same<typename Internals::remove_const<T>::type,
JsonArray>::value,
bool>::type
is() const {
return variantIsArray();
}
//
// bool is<JsonObject> const;
// bool is<JsonObject&> const;
// bool is<const JsonObject&> const;
// bool is<const JsonObject> const;
template <typename T>
typename Internals::enable_if<
Internals::is_same<
typename Internals::remove_const<
typename Internals::remove_reference<T>::type>::type,
JsonObject>::value,
Internals::is_same<typename Internals::remove_const<T>::type,
JsonObject>::value,
bool>::type
is() const {
return variantIsObject();
}
// Returns true if the variant has a value
bool success() const {
return _type != Internals::JSON_UNDEFINED;
bool isNull() const {
return _type == Internals::JSON_UNDEFINED;
}
template <typename Visitor>
@ -315,10 +267,10 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
return visitor.acceptFloat(_content.asFloat);
case JSON_ARRAY:
return visitor.acceptArray(*_content.asArray);
return visitor.acceptArray(_content.asArray);
case JSON_OBJECT:
return visitor.acceptObject(*_content.asObject);
return visitor.acceptObject(_content.asObject);
case JSON_STRING:
return visitor.acceptString(_content.asString);
@ -336,13 +288,13 @@ class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
return visitor.acceptBoolean(_content.asInteger != 0);
default: // JSON_UNDEFINED
return visitor.acceptUndefined();
return visitor.acceptNull();
}
}
private:
JsonArray &variantAsArray() const;
JsonObject &variantAsObject() const;
JsonArray variantAsArray() const;
JsonObject variantAsObject() const;
const char *variantAsString() const;
template <typename T>
T variantAsFloat() const;

View File

@ -13,21 +13,6 @@ namespace Internals {
template <typename TImpl>
class JsonVariantCasts {
public:
// Gets the variant as an array.
// Returns a reference to the JsonArray or JsonArray::invalid() if the
// variant
// is not an array.
FORCE_INLINE operator JsonArray &() const {
return impl()->template as<JsonArray &>();
}
// Gets the variant as an object.
// Returns a reference to the JsonObject or JsonObject::invalid() if the
// variant is not an object.
FORCE_INLINE operator JsonObject &() const {
return impl()->template as<JsonObject &>();
}
template <typename T>
FORCE_INLINE operator T() const {
return impl()->template as<T>();

View File

@ -9,6 +9,9 @@
#include "Strings/StringTraits.hpp"
namespace ArduinoJson {
class JsonArray;
class JsonObject;
namespace Internals {
template <typename TImpl>

View File

@ -5,8 +5,8 @@
#pragma once
#include "Configuration.hpp"
#include "JsonArray.hpp"
#include "JsonObject.hpp"
#include "JsonArrayData.hpp"
#include "JsonObjectData.hpp"
#include "JsonVariant.hpp"
#include "Numbers/isFloat.hpp"
#include "Numbers/isInteger.hpp"
@ -17,32 +17,50 @@
namespace ArduinoJson {
inline JsonVariant::JsonVariant(const JsonArray &array) {
if (array.success()) {
inline JsonVariant::JsonVariant(JsonArray array) {
if (!array.isNull()) {
_type = Internals::JSON_ARRAY;
_content.asArray = const_cast<JsonArray *>(&array);
_content.asArray = array._data;
} else {
_type = Internals::JSON_UNDEFINED;
}
}
inline JsonVariant::JsonVariant(const JsonObject &object) {
if (object.success()) {
inline JsonVariant::JsonVariant(JsonObject object) {
if (!object.isNull()) {
_type = Internals::JSON_OBJECT;
_content.asObject = const_cast<JsonObject *>(&object);
_content.asObject = object._data;
} else {
_type = Internals::JSON_UNDEFINED;
}
}
inline JsonArray &JsonVariant::variantAsArray() const {
if (_type == Internals::JSON_ARRAY) return *_content.asArray;
return JsonArray::invalid();
template <typename T>
inline typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonArray>::value,
JsonArray>::type
JsonVariant::as() const {
return variantAsArray();
}
inline JsonObject &JsonVariant::variantAsObject() const {
if (_type == Internals::JSON_OBJECT) return *_content.asObject;
return JsonObject::invalid();
template <typename T>
inline typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonObject>::value,
T>::type
JsonVariant::as() const {
return variantAsObject();
}
inline JsonArray JsonVariant::variantAsArray() const {
if (_type == Internals::JSON_ARRAY) return _content.asArray;
return JsonArray();
}
inline JsonObject JsonVariant::variantAsObject() const {
if (_type == Internals::JSON_OBJECT) return _content.asObject;
return JsonObject();
}
template <typename T>

View File

@ -10,6 +10,8 @@
#include "Strings/StringTraits.hpp"
namespace ArduinoJson {
class JsonArray;
class JsonObject;
namespace Internals {
// Forward declarations.
@ -30,14 +32,12 @@ class JsonVariantSubscripts {
// Mimics an array.
// Returns the element at specified index if the variant is an array.
// Returns JsonVariant::invalid() if the variant is not an array.
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
FORCE_INLINE JsonArraySubscript operator[](size_t index);
// Mimics an object.
// Returns the value associated with the specified key if the variant is
// an object.
// Return JsonVariant::invalid() if the variant is not an object.
//
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
@ -45,27 +45,21 @@ class JsonVariantSubscripts {
FORCE_INLINE
typename enable_if<StringTraits<TString>::has_equals,
const JsonObjectSubscript<const TString &> >::type
operator[](const TString &key) const {
return impl()->template as<JsonObject>()[key];
}
operator[](const TString &key) const;
//
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE typename enable_if<StringTraits<TString>::has_equals,
JsonObjectSubscript<const TString &> >::type
operator[](const TString &key) {
return impl()->template as<JsonObject>()[key];
}
operator[](const TString &key);
//
// JsonObjectSubscript operator[](TKey);
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
FORCE_INLINE typename enable_if<StringTraits<const TString *>::has_equals,
JsonObjectSubscript<const TString *> >::type
operator[](const TString *key) {
return impl()->template as<JsonObject>()[key];
}
operator[](const TString *key);
//
// JsonObjectSubscript operator[](TKey);
// TKey = const char*, const char[N], const FlashStringHelper*
@ -73,9 +67,7 @@ class JsonVariantSubscripts {
FORCE_INLINE
typename enable_if<StringTraits<TString *>::has_equals,
const JsonObjectSubscript<const TString *> >::type
operator[](const TString *key) const {
return impl()->template as<JsonObject>()[key];
}
operator[](const TString *key) const;
private:
const TImpl *impl() const {

View File

@ -9,7 +9,6 @@
#include <string.h>
#include "../Configuration.hpp"
#include "../Polyfills/NonCopyable.hpp"
#include "../Polyfills/attributes.hpp"
namespace ArduinoJson {
@ -17,7 +16,7 @@ namespace Internals {
// Handle the memory management (done in derived classes) and calls the parser.
// This abstract class is implemented by StaticJsonBuffer which implements a
// fixed memory allocation.
class JsonBuffer : NonCopyable {
class JsonBuffer {
public:
// Allocates n bytes in the JsonBuffer.
// Return a pointer to the allocated memory or NULL if allocation fails.

View File

@ -240,13 +240,13 @@ class MsgPackDeserializer {
}
DeserializationError readArray(JsonVariant &variant, size_t n) {
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return DeserializationError::NoMemory;
JsonArray array(_buffer);
if (array.isNull()) return DeserializationError::NoMemory;
variant = array;
return readArray(*array, n);
return readArray(array, n);
}
DeserializationError readArray(JsonArray &array, size_t n) {
DeserializationError readArray(JsonArray array, size_t n) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {
@ -267,13 +267,13 @@ class MsgPackDeserializer {
}
DeserializationError readObject(JsonVariant &variant, size_t n) {
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return DeserializationError::NoMemory;
JsonObject object(_buffer);
if (object.isNull()) return DeserializationError::NoMemory;
variant = object;
return readObject(*object, n);
return readObject(object, n);
}
DeserializationError readObject(JsonObject &object, size_t n) {
DeserializationError readObject(JsonObject object, size_t n) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {

View File

@ -140,7 +140,7 @@ class MsgPackSerializer {
writeByte(value ? 0xC3 : 0xC2);
}
void acceptUndefined() {
void acceptNull() {
writeByte(0xC0);
}

View File

@ -1,23 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
// A type that cannot be copied
class NonCopyable {
protected:
NonCopyable() {}
private:
// copy constructor is private
NonCopyable(const NonCopyable&);
// copy operator is private
NonCopyable& operator=(const NonCopyable&);
};
}
}

View File

@ -33,28 +33,26 @@ class StaticJsonDocument {
return _root.as<T>();
}
// JsonObject& to<JsonObject>()
// JsonObject to<JsonObject>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonObject>::value,
JsonObject&>::type
JsonObject>::type
to() {
clear();
JsonObject* object = new (&_buffer) JsonObject(&_buffer);
if (!object) return JsonObject::invalid();
JsonObject object(&_buffer);
_root = object;
return *object;
return object;
}
// JsonArray& to<JsonArray>()
// JsonArray to<JsonArray>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonArray>::value,
JsonArray&>::type
JsonArray>::type
to() {
clear();
JsonArray* array = new (&_buffer) JsonArray(&_buffer);
if (!array) return JsonArray::invalid();
JsonArray array(&_buffer);
_root = array;
return *array;
return array;
}
// JsonVariant to<JsonVariant>()