diff --git a/src/ArduinoJson/Json/JsonSerializer.hpp b/src/ArduinoJson/Json/JsonSerializer.hpp index c47f339a..a4894bbe 100644 --- a/src/ArduinoJson/Json/JsonSerializer.hpp +++ b/src/ArduinoJson/Json/JsonSerializer.hpp @@ -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 -inline std::ostream &operator<<(std::ostream &os, - const JsonObjectSubscript &source) { +template +inline typename enable_if::value, std::ostream &>::type +operator<<(std::ostream &os, const T &source) { serializeJson(source, os); return os; } diff --git a/src/ArduinoJson/JsonArray.hpp b/src/ArduinoJson/JsonArray.hpp index f3a85e73..a4b73ea8 100644 --- a/src/ArduinoJson/JsonArray.hpp +++ b/src/ArduinoJson/JsonArray.hpp @@ -38,13 +38,22 @@ class JsonArrayProxy { TData* _data; }; -class JsonArrayConst : public JsonArrayProxy { +class JsonArrayConst : public JsonArrayProxy, + public Visitable { friend class JsonArray; typedef JsonArrayProxy proxy_type; public: typedef JsonArrayConstIterator iterator; + template + 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 { } }; -class JsonArray : public JsonArrayProxy { +class JsonArray : public JsonArrayProxy, public Visitable { typedef JsonArrayProxy proxy_type; public: @@ -224,10 +233,7 @@ class JsonArray : public JsonArrayProxy { template FORCE_INLINE void accept(Visitor& visitor) const { - if (_data) - visitor.visitArray(*this); - else - visitor.visitNull(); + JsonArrayConst(_data).accept(visitor); } private: diff --git a/src/ArduinoJson/JsonArraySubscript.hpp b/src/ArduinoJson/JsonArraySubscript.hpp index a44c0202..1ea37e76 100644 --- a/src/ArduinoJson/JsonArraySubscript.hpp +++ b/src/ArduinoJson/JsonArraySubscript.hpp @@ -13,7 +13,8 @@ #endif namespace ARDUINOJSON_NAMESPACE { -class JsonArraySubscript : public JsonVariantBase { +class JsonArraySubscript : public JsonVariantBase, + public Visitable { public: FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index) : _array(array), _index(index) {} diff --git a/src/ArduinoJson/JsonDocument.hpp b/src/ArduinoJson/JsonDocument.hpp index b5478372..57ce63a5 100644 --- a/src/ArduinoJson/JsonDocument.hpp +++ b/src/ArduinoJson/JsonDocument.hpp @@ -12,7 +12,7 @@ namespace ARDUINOJSON_NAMESPACE { template -class JsonDocument { +class JsonDocument : public Visitable { public: uint8_t nestingLimit; diff --git a/src/ArduinoJson/JsonObject.hpp b/src/ArduinoJson/JsonObject.hpp index 964e02b2..a7f3fa0d 100644 --- a/src/ArduinoJson/JsonObject.hpp +++ b/src/ArduinoJson/JsonObject.hpp @@ -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 { +class JsonObjectConst : public JsonObjectProxy, + public Visitable { friend class JsonObject; typedef JsonObjectProxy proxy_type; @@ -52,6 +57,14 @@ class JsonObjectConst : public JsonObjectProxy { JsonObjectConst() : proxy_type(0) {} JsonObjectConst(const JsonObjectData* data) : proxy_type(data) {} + template + 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 { } }; -class JsonObject : public JsonObjectProxy { +class JsonObject : public JsonObjectProxy, public Visitable { typedef JsonObjectProxy proxy_type; public: @@ -304,16 +317,9 @@ class JsonObject : public JsonObjectProxy { return set_impl(key); } - FORCE_INLINE bool isNull() const { - return _data == 0; - } - template FORCE_INLINE void accept(Visitor& visitor) const { - if (_data) - visitor.visitObject(JsonObjectConst(_data)); - else - visitor.visitNull(); + JsonObjectConst(_data).accept(visitor); } private: diff --git a/src/ArduinoJson/JsonObjectSubscript.hpp b/src/ArduinoJson/JsonObjectSubscript.hpp index f75df9eb..bcba2c48 100644 --- a/src/ArduinoJson/JsonObjectSubscript.hpp +++ b/src/ArduinoJson/JsonObjectSubscript.hpp @@ -17,7 +17,8 @@ namespace ARDUINOJSON_NAMESPACE { template class JsonObjectSubscript - : public JsonVariantBase > { + : public JsonVariantBase >, + public Visitable { typedef JsonObjectSubscript this_type; public: diff --git a/src/ArduinoJson/JsonVariant.hpp b/src/ArduinoJson/JsonVariant.hpp index 4562ffab..e611ea52 100644 --- a/src/ArduinoJson/JsonVariant.hpp +++ b/src/ArduinoJson/JsonVariant.hpp @@ -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, - public JsonVariantBase { + public JsonVariantBase, + public Visitable { typedef JsonVariantProxy proxy_type; friend class JsonVariantConst; @@ -279,7 +281,8 @@ class JsonVariant : public JsonVariantProxy, }; class JsonVariantConst : public JsonVariantProxy, - public JsonVariantBase { + public JsonVariantBase, + public Visitable { typedef JsonVariantProxy proxy_type; public: @@ -318,15 +321,4 @@ class JsonVariantConst : public JsonVariantProxy, 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 diff --git a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp index 92e87e29..936c3075 100644 --- a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp @@ -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()) return DeserializationError::NotSupported; diff --git a/src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp b/src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp index dc3750ee..bb4896db 100644 --- a/src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp +++ b/src/ArduinoJson/Polyfills/type_traits/is_base_of.hpp @@ -18,8 +18,7 @@ class is_base_of { static No &probe(...); public: - enum { - value = sizeof(probe(reinterpret_cast(0))) == sizeof(Yes) - }; + static const bool value = + sizeof(probe(reinterpret_cast(0))) == sizeof(Yes); }; } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Visitable.hpp b/src/ArduinoJson/Visitable.hpp new file mode 100644 index 00000000..f7a47686 --- /dev/null +++ b/src/ArduinoJson/Visitable.hpp @@ -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 + // void accept(Visitor&) const; +}; + +template +struct IsVisitable : is_base_of {}; +} // namespace ARDUINOJSON_NAMESPACE diff --git a/test/JsonArray/isNull.cpp b/test/JsonArray/isNull.cpp index b2bf2456..5ceb55ac 100644 --- a/test/JsonArray/isNull.cpp +++ b/test/JsonArray/isNull.cpp @@ -6,39 +6,29 @@ #include 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 doc; - JsonArray array = doc.to(); - REQUIRE(array.isNull() == false); + SECTION("returns false") { + JsonArray arr = doc.to(); + REQUIRE(arr.isNull() == false); } - - /* SECTION("returns true when allocation fails") { - StaticJsonDocument<1> doc; - JsonArray array = doc.to(); - 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 doc; - JsonArrayConst array = doc.to(); - REQUIRE(array.isNull() == false); + SECTION("returns false") { + JsonArrayConst arr = doc.to(); + REQUIRE(arr.isNull() == false); } - - /* SECTION("returns true when allocation fails") { - StaticJsonDocument<1> doc; - JsonArray array = doc.to(); - REQUIRE(array.isNull() == true); - }*/ } diff --git a/test/JsonObject/isNull.cpp b/test/JsonObject/isNull.cpp index 176b9dae..6c7e0a9a 100644 --- a/test/JsonObject/isNull.cpp +++ b/test/JsonObject/isNull.cpp @@ -6,20 +6,29 @@ #include 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 doc; - JsonObject array = doc.to(); - REQUIRE(array.isNull() == false); + SECTION("returns false") { + JsonObject obj = doc.to(); + REQUIRE(obj.isNull() == false); + } +} + +TEST_CASE("JsonObjectConst::isNull()") { + DynamicJsonDocument doc; + + SECTION("returns true") { + JsonObjectConst obj; + REQUIRE(obj.isNull() == true); + } + + SECTION("returns false") { + JsonObjectConst obj = doc.to(); + REQUIRE(obj.isNull() == false); } - - /* SECTION("returns true when allocation fails") { - StaticJsonDocument<1> doc; - JsonObject array = doc.to(); - REQUIRE(array.isNull() == true); - }*/ } diff --git a/test/Misc/TypeTraits.cpp b/test/Misc/TypeTraits.cpp index 884f2f9e..5bd84c84 100644 --- a/test/Misc/TypeTraits.cpp +++ b/test/Misc/TypeTraits.cpp @@ -50,4 +50,19 @@ TEST_CASE("Polyfills/type_traits") { CHECK(is_unsigned::value == false); CHECK(is_unsigned::value == false); } + + SECTION("IsVisitable") { + CHECK(IsVisitable::value == false); + CHECK(IsVisitable::value == false); + CHECK(IsVisitable::value == true); + CHECK(IsVisitable::value == true); + CHECK(IsVisitable::value == true); + CHECK(IsVisitable::value == true); + CHECK(IsVisitable::value == true); + CHECK(IsVisitable::value == true); + CHECK(IsVisitable >::value == true); + CHECK(IsVisitable::value == true); + CHECK(IsVisitable::value == true); + CHECK(IsVisitable >::value == true); + } }