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/serialize.hpp"
|
||||
#include "./JsonWriter.hpp"
|
||||
#include "../Visitable.hpp"
|
||||
#include "JsonWriter.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
@ -103,32 +104,9 @@ size_t measureJson(const TSource &source) {
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonArray &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;
|
||||
}
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
@ -38,13 +38,22 @@ class JsonArrayProxy {
|
||||
TData* _data;
|
||||
};
|
||||
|
||||
class JsonArrayConst : public JsonArrayProxy<const JsonArrayData> {
|
||||
class JsonArrayConst : public JsonArrayProxy<const JsonArrayData>,
|
||||
public Visitable {
|
||||
friend class JsonArray;
|
||||
typedef JsonArrayProxy<const JsonArrayData> proxy_type;
|
||||
|
||||
public:
|
||||
typedef JsonArrayConstIterator iterator;
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
if (_data)
|
||||
visitor.visitArray(*this);
|
||||
else
|
||||
visitor.visitNull();
|
||||
}
|
||||
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data) return iterator();
|
||||
return iterator(_data->head);
|
||||
@ -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;
|
||||
|
||||
public:
|
||||
@ -224,10 +233,7 @@ class JsonArray : public JsonArrayProxy<JsonArrayData> {
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
if (_data)
|
||||
visitor.visitArray(*this);
|
||||
else
|
||||
visitor.visitNull();
|
||||
JsonArrayConst(_data).accept(visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -13,7 +13,8 @@
|
||||
#endif
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript>,
|
||||
public Visitable {
|
||||
public:
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
@ -12,7 +12,7 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TMemoryPool>
|
||||
class JsonDocument {
|
||||
class JsonDocument : public Visitable {
|
||||
public:
|
||||
uint8_t nestingLimit;
|
||||
|
||||
|
@ -33,6 +33,10 @@ class JsonObjectProxy {
|
||||
return objectContainsKey(_data, makeString(key));
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t size() const {
|
||||
return objectSize(_data);
|
||||
}
|
||||
@ -42,7 +46,8 @@ class JsonObjectProxy {
|
||||
TData* _data;
|
||||
};
|
||||
|
||||
class JsonObjectConst : public JsonObjectProxy<const JsonObjectData> {
|
||||
class JsonObjectConst : public JsonObjectProxy<const JsonObjectData>,
|
||||
public Visitable {
|
||||
friend class JsonObject;
|
||||
typedef JsonObjectProxy<const JsonObjectData> proxy_type;
|
||||
|
||||
@ -52,6 +57,14 @@ class JsonObjectConst : public JsonObjectProxy<const JsonObjectData> {
|
||||
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);
|
||||
@ -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;
|
||||
|
||||
public:
|
||||
@ -304,16 +317,9 @@ class JsonObject : public JsonObjectProxy<JsonObjectData> {
|
||||
return set_impl(key);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
if (_data)
|
||||
visitor.visitObject(JsonObjectConst(_data));
|
||||
else
|
||||
visitor.visitNull();
|
||||
JsonObjectConst(_data).accept(visitor);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -17,7 +17,8 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TStringRef>
|
||||
class JsonObjectSubscript
|
||||
: public JsonVariantBase<JsonObjectSubscript<TStringRef> > {
|
||||
: public JsonVariantBase<JsonObjectSubscript<TStringRef> >,
|
||||
public Visitable {
|
||||
typedef JsonObjectSubscript<TStringRef> this_type;
|
||||
|
||||
public:
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "Numbers/parseFloat.hpp"
|
||||
#include "Numbers/parseInteger.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "Visitable.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
@ -117,7 +118,8 @@ class JsonVariantProxy {
|
||||
// - a string (const char*)
|
||||
// - a reference to a JsonArray or JsonObject
|
||||
class JsonVariant : public JsonVariantProxy<JsonVariantData>,
|
||||
public JsonVariantBase<JsonVariant> {
|
||||
public JsonVariantBase<JsonVariant>,
|
||||
public Visitable {
|
||||
typedef JsonVariantProxy<JsonVariantData> proxy_type;
|
||||
friend class JsonVariantConst;
|
||||
|
||||
@ -279,7 +281,8 @@ class JsonVariant : public JsonVariantProxy<JsonVariantData>,
|
||||
};
|
||||
|
||||
class JsonVariantConst : public JsonVariantProxy<const JsonVariantData>,
|
||||
public JsonVariantBase<JsonVariantConst> {
|
||||
public JsonVariantBase<JsonVariantConst>,
|
||||
public Visitable {
|
||||
typedef JsonVariantProxy<const JsonVariantData> proxy_type;
|
||||
|
||||
public:
|
||||
@ -318,15 +321,4 @@ class JsonVariantConst : public JsonVariantProxy<const JsonVariantData>,
|
||||
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
|
||||
|
@ -278,7 +278,8 @@ class MsgPackDeserializer {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
--_nestingLimit;
|
||||
for (; n; --n) {
|
||||
JsonVariantLocal key(_memoryPool);
|
||||
JsonVariantData keyData;
|
||||
JsonVariant key(_memoryPool, &keyData);
|
||||
DeserializationError err = parse(key);
|
||||
if (err) return err;
|
||||
if (!key.is<char *>()) return DeserializationError::NotSupported;
|
||||
|
@ -18,8 +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 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>
|
||||
|
||||
TEST_CASE("JsonArray::isNull()") {
|
||||
SECTION("returns true for undefined JsonArray") {
|
||||
JsonArray array;
|
||||
REQUIRE(array.isNull() == true);
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("returns true") {
|
||||
JsonArray arr;
|
||||
REQUIRE(arr.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false when allocation succeeds") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc;
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
REQUIRE(array.isNull() == false);
|
||||
SECTION("returns false") {
|
||||
JsonArray arr = doc.to<JsonArray>();
|
||||
REQUIRE(arr.isNull() == false);
|
||||
}
|
||||
|
||||
/* SECTION("returns true when allocation fails") {
|
||||
StaticJsonDocument<1> doc;
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
REQUIRE(array.isNull() == true);
|
||||
}*/
|
||||
}
|
||||
|
||||
TEST_CASE("JsonArrayConst::isNull()") {
|
||||
SECTION("returns true for undefined JsonArray") {
|
||||
JsonArrayConst array;
|
||||
REQUIRE(array.isNull() == true);
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("returns true") {
|
||||
JsonArrayConst arr;
|
||||
REQUIRE(arr.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false when allocation succeeds") {
|
||||
StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc;
|
||||
JsonArrayConst array = doc.to<JsonArray>();
|
||||
REQUIRE(array.isNull() == false);
|
||||
SECTION("returns false") {
|
||||
JsonArrayConst arr = doc.to<JsonArray>();
|
||||
REQUIRE(arr.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>
|
||||
|
||||
TEST_CASE("JsonObject::isNull()") {
|
||||
SECTION("returns true for undefined JsonObject") {
|
||||
JsonObject array;
|
||||
REQUIRE(array.isNull() == true);
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
SECTION("returns true") {
|
||||
JsonObject obj;
|
||||
REQUIRE(obj.isNull() == true);
|
||||
}
|
||||
|
||||
SECTION("returns false when allocation succeeds") {
|
||||
StaticJsonDocument<JSON_OBJECT_SIZE(0)> doc;
|
||||
JsonObject array = doc.to<JsonObject>();
|
||||
REQUIRE(array.isNull() == false);
|
||||
SECTION("returns false") {
|
||||
JsonObject 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);
|
||||
}*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -50,4 +50,19 @@ TEST_CASE("Polyfills/type_traits") {
|
||||
CHECK(is_unsigned<float>::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