forked from bblanchon/ArduinoJson
Added Visitable to reduce the number of definitions of operator<<
This commit is contained in:
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
#include "../Serialization/measure.hpp"
|
#include "../Serialization/measure.hpp"
|
||||||
#include "../Serialization/serialize.hpp"
|
#include "../Serialization/serialize.hpp"
|
||||||
#include "./JsonWriter.hpp"
|
#include "../Visitable.hpp"
|
||||||
|
#include "JsonWriter.hpp"
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
@ -103,32 +104,9 @@ size_t measureJson(const TSource &source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
inline std::ostream &operator<<(std::ostream &os, const JsonArray &source) {
|
template <typename T>
|
||||||
serializeJson(source, os);
|
inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type
|
||||||
return os;
|
operator<<(std::ostream &os, const T &source) {
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
inline std::ostream &operator<<(std::ostream &os, JsonVariantConst source) {
|
|
||||||
os << serializeJson(source, os);
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
serializeJson(source, os);
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
@ -38,13 +38,22 @@ class JsonArrayProxy {
|
|||||||
TData* _data;
|
TData* _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonArrayConst : public JsonArrayProxy<const JsonArrayData> {
|
class JsonArrayConst : public JsonArrayProxy<const JsonArrayData>,
|
||||||
|
public Visitable {
|
||||||
friend class JsonArray;
|
friend class JsonArray;
|
||||||
typedef JsonArrayProxy<const JsonArrayData> proxy_type;
|
typedef JsonArrayProxy<const JsonArrayData> proxy_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef JsonArrayConstIterator iterator;
|
typedef JsonArrayConstIterator iterator;
|
||||||
|
|
||||||
|
template <typename Visitor>
|
||||||
|
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||||
|
if (_data)
|
||||||
|
visitor.visitArray(*this);
|
||||||
|
else
|
||||||
|
visitor.visitNull();
|
||||||
|
}
|
||||||
|
|
||||||
FORCE_INLINE iterator begin() const {
|
FORCE_INLINE iterator begin() const {
|
||||||
if (!_data) return iterator();
|
if (!_data) return iterator();
|
||||||
return iterator(_data->head);
|
return iterator(_data->head);
|
||||||
@ -62,7 +71,7 @@ class JsonArrayConst : public JsonArrayProxy<const JsonArrayData> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonArray : public JsonArrayProxy<JsonArrayData> {
|
class JsonArray : public JsonArrayProxy<JsonArrayData>, public Visitable {
|
||||||
typedef JsonArrayProxy<JsonArrayData> proxy_type;
|
typedef JsonArrayProxy<JsonArrayData> proxy_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -224,10 +233,7 @@ class JsonArray : public JsonArrayProxy<JsonArrayData> {
|
|||||||
|
|
||||||
template <typename Visitor>
|
template <typename Visitor>
|
||||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||||
if (_data)
|
JsonArrayConst(_data).accept(visitor);
|
||||||
visitor.visitArray(*this);
|
|
||||||
else
|
|
||||||
visitor.visitNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript>,
|
||||||
|
public Visitable {
|
||||||
public:
|
public:
|
||||||
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
|
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
|
||||||
: _array(array), _index(index) {}
|
: _array(array), _index(index) {}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TMemoryPool>
|
template <typename TMemoryPool>
|
||||||
class JsonDocument {
|
class JsonDocument : public Visitable {
|
||||||
public:
|
public:
|
||||||
uint8_t nestingLimit;
|
uint8_t nestingLimit;
|
||||||
|
|
||||||
|
@ -33,6 +33,10 @@ class JsonObjectProxy {
|
|||||||
return objectContainsKey(_data, makeString(key));
|
return objectContainsKey(_data, makeString(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE bool isNull() const {
|
||||||
|
return _data == 0;
|
||||||
|
}
|
||||||
|
|
||||||
FORCE_INLINE size_t size() const {
|
FORCE_INLINE size_t size() const {
|
||||||
return objectSize(_data);
|
return objectSize(_data);
|
||||||
}
|
}
|
||||||
@ -42,7 +46,8 @@ class JsonObjectProxy {
|
|||||||
TData* _data;
|
TData* _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonObjectConst : public JsonObjectProxy<const JsonObjectData> {
|
class JsonObjectConst : public JsonObjectProxy<const JsonObjectData>,
|
||||||
|
public Visitable {
|
||||||
friend class JsonObject;
|
friend class JsonObject;
|
||||||
typedef JsonObjectProxy<const JsonObjectData> proxy_type;
|
typedef JsonObjectProxy<const JsonObjectData> proxy_type;
|
||||||
|
|
||||||
@ -52,6 +57,14 @@ class JsonObjectConst : public JsonObjectProxy<const JsonObjectData> {
|
|||||||
JsonObjectConst() : proxy_type(0) {}
|
JsonObjectConst() : proxy_type(0) {}
|
||||||
JsonObjectConst(const JsonObjectData* data) : proxy_type(data) {}
|
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 {
|
FORCE_INLINE iterator begin() const {
|
||||||
if (!_data) return iterator();
|
if (!_data) return iterator();
|
||||||
return iterator(_data->head);
|
return iterator(_data->head);
|
||||||
@ -110,7 +123,7 @@ class JsonObjectConst : public JsonObjectProxy<const JsonObjectData> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonObject : public JsonObjectProxy<JsonObjectData> {
|
class JsonObject : public JsonObjectProxy<JsonObjectData>, public Visitable {
|
||||||
typedef JsonObjectProxy<JsonObjectData> proxy_type;
|
typedef JsonObjectProxy<JsonObjectData> proxy_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -304,16 +317,9 @@ class JsonObject : public JsonObjectProxy<JsonObjectData> {
|
|||||||
return set_impl(key);
|
return set_impl(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE bool isNull() const {
|
|
||||||
return _data == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename Visitor>
|
||||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||||
if (_data)
|
JsonObjectConst(_data).accept(visitor);
|
||||||
visitor.visitObject(JsonObjectConst(_data));
|
|
||||||
else
|
|
||||||
visitor.visitNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -17,7 +17,8 @@ namespace ARDUINOJSON_NAMESPACE {
|
|||||||
|
|
||||||
template <typename TStringRef>
|
template <typename TStringRef>
|
||||||
class JsonObjectSubscript
|
class JsonObjectSubscript
|
||||||
: public JsonVariantBase<JsonObjectSubscript<TStringRef> > {
|
: public JsonVariantBase<JsonObjectSubscript<TStringRef> >,
|
||||||
|
public Visitable {
|
||||||
typedef JsonObjectSubscript<TStringRef> this_type;
|
typedef JsonObjectSubscript<TStringRef> this_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "Numbers/parseFloat.hpp"
|
#include "Numbers/parseFloat.hpp"
|
||||||
#include "Numbers/parseInteger.hpp"
|
#include "Numbers/parseInteger.hpp"
|
||||||
#include "Polyfills/type_traits.hpp"
|
#include "Polyfills/type_traits.hpp"
|
||||||
|
#include "Visitable.hpp"
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
@ -117,7 +118,8 @@ class JsonVariantProxy {
|
|||||||
// - a string (const char*)
|
// - a string (const char*)
|
||||||
// - a reference to a JsonArray or JsonObject
|
// - a reference to a JsonArray or JsonObject
|
||||||
class JsonVariant : public JsonVariantProxy<JsonVariantData>,
|
class JsonVariant : public JsonVariantProxy<JsonVariantData>,
|
||||||
public JsonVariantBase<JsonVariant> {
|
public JsonVariantBase<JsonVariant>,
|
||||||
|
public Visitable {
|
||||||
typedef JsonVariantProxy<JsonVariantData> proxy_type;
|
typedef JsonVariantProxy<JsonVariantData> proxy_type;
|
||||||
friend class JsonVariantConst;
|
friend class JsonVariantConst;
|
||||||
|
|
||||||
@ -279,7 +281,8 @@ class JsonVariant : public JsonVariantProxy<JsonVariantData>,
|
|||||||
};
|
};
|
||||||
|
|
||||||
class JsonVariantConst : public JsonVariantProxy<const JsonVariantData>,
|
class JsonVariantConst : public JsonVariantProxy<const JsonVariantData>,
|
||||||
public JsonVariantBase<JsonVariantConst> {
|
public JsonVariantBase<JsonVariantConst>,
|
||||||
|
public Visitable {
|
||||||
typedef JsonVariantProxy<const JsonVariantData> proxy_type;
|
typedef JsonVariantProxy<const JsonVariantData> proxy_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -318,15 +321,4 @@ class JsonVariantConst : public JsonVariantProxy<const JsonVariantData>,
|
|||||||
return JsonVariantConst(objectGet(variantAsObject(_data), makeString(key)));
|
return JsonVariantConst(objectGet(variantAsObject(_data), makeString(key)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonVariantLocal : public JsonVariant {
|
|
||||||
public:
|
|
||||||
explicit JsonVariantLocal(MemoryPool *memoryPool)
|
|
||||||
: JsonVariant(memoryPool, &_localData) {
|
|
||||||
_localData.type = JSON_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
JsonVariantData _localData;
|
|
||||||
};
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -278,7 +278,8 @@ class MsgPackDeserializer {
|
|||||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||||
--_nestingLimit;
|
--_nestingLimit;
|
||||||
for (; n; --n) {
|
for (; n; --n) {
|
||||||
JsonVariantLocal key(_memoryPool);
|
JsonVariantData keyData;
|
||||||
|
JsonVariant key(_memoryPool, &keyData);
|
||||||
DeserializationError err = parse(key);
|
DeserializationError err = parse(key);
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
if (!key.is<char *>()) return DeserializationError::NotSupported;
|
if (!key.is<char *>()) return DeserializationError::NotSupported;
|
||||||
|
@ -18,8 +18,7 @@ class is_base_of {
|
|||||||
static No &probe(...);
|
static No &probe(...);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum {
|
static const bool value =
|
||||||
value = sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes)
|
sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes);
|
||||||
};
|
|
||||||
};
|
};
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
18
src/ArduinoJson/Visitable.hpp
Normal file
18
src/ArduinoJson/Visitable.hpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Polyfills/type_traits.hpp"
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
struct Visitable {
|
||||||
|
// template<Visitor>
|
||||||
|
// void accept(Visitor&) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct IsVisitable : is_base_of<Visitable, T> {};
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -6,39 +6,29 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
TEST_CASE("JsonArray::isNull()") {
|
TEST_CASE("JsonArray::isNull()") {
|
||||||
SECTION("returns true for undefined JsonArray") {
|
DynamicJsonDocument doc;
|
||||||
JsonArray array;
|
|
||||||
REQUIRE(array.isNull() == true);
|
SECTION("returns true") {
|
||||||
|
JsonArray arr;
|
||||||
|
REQUIRE(arr.isNull() == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("returns false when allocation succeeds") {
|
SECTION("returns false") {
|
||||||
StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc;
|
JsonArray arr = doc.to<JsonArray>();
|
||||||
JsonArray array = doc.to<JsonArray>();
|
REQUIRE(arr.isNull() == false);
|
||||||
REQUIRE(array.isNull() == false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SECTION("returns true when allocation fails") {
|
|
||||||
StaticJsonDocument<1> doc;
|
|
||||||
JsonArray array = doc.to<JsonArray>();
|
|
||||||
REQUIRE(array.isNull() == true);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("JsonArrayConst::isNull()") {
|
TEST_CASE("JsonArrayConst::isNull()") {
|
||||||
SECTION("returns true for undefined JsonArray") {
|
DynamicJsonDocument doc;
|
||||||
JsonArrayConst array;
|
|
||||||
REQUIRE(array.isNull() == true);
|
SECTION("returns true") {
|
||||||
|
JsonArrayConst arr;
|
||||||
|
REQUIRE(arr.isNull() == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("returns false when allocation succeeds") {
|
SECTION("returns false") {
|
||||||
StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc;
|
JsonArrayConst arr = doc.to<JsonArray>();
|
||||||
JsonArrayConst array = doc.to<JsonArray>();
|
REQUIRE(arr.isNull() == false);
|
||||||
REQUIRE(array.isNull() == false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SECTION("returns true when allocation fails") {
|
|
||||||
StaticJsonDocument<1> doc;
|
|
||||||
JsonArray array = doc.to<JsonArray>();
|
|
||||||
REQUIRE(array.isNull() == true);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
@ -6,20 +6,29 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
TEST_CASE("JsonObject::isNull()") {
|
TEST_CASE("JsonObject::isNull()") {
|
||||||
SECTION("returns true for undefined JsonObject") {
|
DynamicJsonDocument doc;
|
||||||
JsonObject array;
|
|
||||||
REQUIRE(array.isNull() == true);
|
SECTION("returns true") {
|
||||||
|
JsonObject obj;
|
||||||
|
REQUIRE(obj.isNull() == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("returns false when allocation succeeds") {
|
SECTION("returns false") {
|
||||||
StaticJsonDocument<JSON_OBJECT_SIZE(0)> doc;
|
JsonObject obj = doc.to<JsonObject>();
|
||||||
JsonObject array = doc.to<JsonObject>();
|
REQUIRE(obj.isNull() == false);
|
||||||
REQUIRE(array.isNull() == false);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonObjectConst::isNull()") {
|
||||||
|
DynamicJsonDocument doc;
|
||||||
|
|
||||||
|
SECTION("returns true") {
|
||||||
|
JsonObjectConst obj;
|
||||||
|
REQUIRE(obj.isNull() == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("returns false") {
|
||||||
|
JsonObjectConst obj = doc.to<JsonObject>();
|
||||||
|
REQUIRE(obj.isNull() == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SECTION("returns true when allocation fails") {
|
|
||||||
StaticJsonDocument<1> doc;
|
|
||||||
JsonObject array = doc.to<JsonObject>();
|
|
||||||
REQUIRE(array.isNull() == true);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
@ -50,4 +50,19 @@ TEST_CASE("Polyfills/type_traits") {
|
|||||||
CHECK(is_unsigned<float>::value == false);
|
CHECK(is_unsigned<float>::value == false);
|
||||||
CHECK(is_unsigned<double>::value == false);
|
CHECK(is_unsigned<double>::value == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("IsVisitable") {
|
||||||
|
CHECK(IsVisitable<DeserializationError>::value == false);
|
||||||
|
CHECK(IsVisitable<JsonPair>::value == false);
|
||||||
|
CHECK(IsVisitable<JsonVariant>::value == true);
|
||||||
|
CHECK(IsVisitable<JsonVariantConst>::value == true);
|
||||||
|
CHECK(IsVisitable<JsonArray>::value == true);
|
||||||
|
CHECK(IsVisitable<JsonArraySubscript>::value == true);
|
||||||
|
CHECK(IsVisitable<JsonArrayConst>::value == true);
|
||||||
|
CHECK(IsVisitable<JsonObject>::value == true);
|
||||||
|
CHECK(IsVisitable<JsonObjectSubscript<const char*> >::value == true);
|
||||||
|
CHECK(IsVisitable<JsonObjectConst>::value == true);
|
||||||
|
CHECK(IsVisitable<DynamicJsonDocument>::value == true);
|
||||||
|
CHECK(IsVisitable<StaticJsonDocument<10> >::value == true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user