Added Visitable to reduce the number of definitions of operator<<

This commit is contained in:
Benoit Blanchon
2018-10-12 17:59:50 +02:00
parent b0560cbd99
commit 02d809f3f4
13 changed files with 118 additions and 102 deletions

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@
namespace ARDUINOJSON_NAMESPACE {
template <typename TMemoryPool>
class JsonDocument {
class JsonDocument : public Visitable {
public:
uint8_t nestingLimit;

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

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