diff --git a/src/ArduinoJson/Array/ArrayFunctions.hpp b/src/ArduinoJson/Array/ArrayFunctions.hpp index c8335d28..517d0b89 100644 --- a/src/ArduinoJson/Array/ArrayFunctions.hpp +++ b/src/ArduinoJson/Array/ArrayFunctions.hpp @@ -12,12 +12,13 @@ inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) { return arr ? arr->addElement(pool) : 0; } -template -inline void arrayAccept(const CollectionData *arr, Visitor &visitor) { +template +inline typename TVisitor::result_type arrayAccept(const CollectionData *arr, + TVisitor &visitor) { if (arr) - visitor.visitArray(*arr); + return visitor.visitArray(*arr); else - visitor.visitNull(); + return visitor.visitNull(); } inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) { diff --git a/src/ArduinoJson/Array/ArrayRef.hpp b/src/ArduinoJson/Array/ArrayRef.hpp index bb2fbaa7..2e8e7bfd 100644 --- a/src/ArduinoJson/Array/ArrayRef.hpp +++ b/src/ArduinoJson/Array/ArrayRef.hpp @@ -27,9 +27,9 @@ class ArrayRefBase { return VariantConstRef(reinterpret_cast(data)); } - template - FORCE_INLINE void accept(Visitor& visitor) const { - arrayAccept(_data, visitor); + template + FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const { + return arrayAccept(_data, visitor); } FORCE_INLINE bool isNull() const { diff --git a/src/ArduinoJson/Array/ElementProxy.hpp b/src/ArduinoJson/Array/ElementProxy.hpp index e98e7c79..6d47ef37 100644 --- a/src/ArduinoJson/Array/ElementProxy.hpp +++ b/src/ArduinoJson/Array/ElementProxy.hpp @@ -98,8 +98,8 @@ class ElementProxy : public VariantOperators >, return getOrAddUpstreamElement().set(value); } - template - void accept(Visitor& visitor) const { + template + typename TVisitor::result_type accept(TVisitor& visitor) const { return getUpstreamElement().accept(visitor); } diff --git a/src/ArduinoJson/Array/Utilities.hpp b/src/ArduinoJson/Array/Utilities.hpp index 182f89bd..cd84eb80 100644 --- a/src/ArduinoJson/Array/Utilities.hpp +++ b/src/ArduinoJson/Array/Utilities.hpp @@ -65,40 +65,61 @@ inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) { } template -class ArrayCopier1D { +class ArrayCopier1D : public Visitor { public: ArrayCopier1D(T* destination, size_t capacity) - : _destination(destination), _capacity(capacity), _size(0) {} + : _destination(destination), _capacity(capacity) {} - void visitArray(const CollectionData& array) { + size_t visitArray(const CollectionData& array) { + size_t size = 0; VariantSlot* slot = array.head(); - while (slot != 0 && _size < _capacity) { - _destination[_size++] = variantAs(slot->data()); + while (slot != 0 && size < _capacity) { + _destination[size++] = variantAs(slot->data()); slot = slot->next(); } + return size; } - void visitObject(const CollectionData&) {} - void visitFloat(Float) {} - void visitString(const char*) {} - void visitRawJson(const char*, size_t) {} - void visitNegativeInteger(UInt) {} - void visitPositiveInteger(UInt) {} - void visitBoolean(bool) {} - void visitNull() {} - size_t result() const { - return _size; + size_t visitObject(const CollectionData&) { + return 0; + } + + size_t visitFloat(Float) { + return 0; + } + + size_t visitString(const char*) { + return 0; + } + + size_t visitRawJson(const char*, size_t) { + return 0; + } + + size_t visitNegativeInteger(UInt) { + return 0; + } + + size_t visitPositiveInteger(UInt) { + return 0; + } + + size_t visitBoolean(bool) { + return 0; + } + + size_t visitNull() { + return 0; } private: T* _destination; size_t _capacity; - size_t _size; }; template -class ArrayCopier2D { +class ArrayCopier2D : public Visitor { public: ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {} @@ -136,8 +157,8 @@ inline typename enable_if::value, size_t>::type copyArray( template inline size_t copyArray(const TSource& src, T* dst, size_t len) { ArrayCopier1D copier(dst, len); - src.accept(copier); - return copier.result(); + + return src.accept(copier); } // Copy a JsonArray to a 2D array diff --git a/src/ArduinoJson/Document/JsonDocument.hpp b/src/ArduinoJson/Document/JsonDocument.hpp index cad93318..7c3a844e 100644 --- a/src/ArduinoJson/Document/JsonDocument.hpp +++ b/src/ArduinoJson/Document/JsonDocument.hpp @@ -15,8 +15,8 @@ namespace ARDUINOJSON_NAMESPACE { class JsonDocument : public Visitable { public: - template - void accept(Visitor& visitor) const { + template + typename TVisitor::result_type accept(TVisitor& visitor) const { return getVariant().accept(visitor); } diff --git a/src/ArduinoJson/Json/JsonSerializer.hpp b/src/ArduinoJson/Json/JsonSerializer.hpp index df0cac68..0baf3c52 100644 --- a/src/ArduinoJson/Json/JsonSerializer.hpp +++ b/src/ArduinoJson/Json/JsonSerializer.hpp @@ -12,11 +12,11 @@ namespace ARDUINOJSON_NAMESPACE { template -class JsonSerializer { +class JsonSerializer : public Visitor { public: JsonSerializer(TWriter writer) : _formatter(writer) {} - FORCE_INLINE void visitArray(const CollectionData &array) { + FORCE_INLINE size_t visitArray(const CollectionData &array) { write('['); VariantSlot *slot = array.head(); @@ -32,9 +32,10 @@ class JsonSerializer { } write(']'); + return bytesWritten(); } - void visitObject(const CollectionData &object) { + size_t visitObject(const CollectionData &object) { write('{'); VariantSlot *slot = object.head(); @@ -52,41 +53,49 @@ class JsonSerializer { } write('}'); + return bytesWritten(); } - void visitFloat(Float value) { + size_t visitFloat(Float value) { _formatter.writeFloat(value); + return bytesWritten(); } - void visitString(const char *value) { + size_t visitString(const char *value) { _formatter.writeString(value); + return bytesWritten(); } - void visitRawJson(const char *data, size_t n) { + size_t visitRawJson(const char *data, size_t n) { _formatter.writeRaw(data, n); + return bytesWritten(); } - void visitNegativeInteger(UInt value) { + size_t visitNegativeInteger(UInt value) { _formatter.writeNegativeInteger(value); + return bytesWritten(); } - void visitPositiveInteger(UInt value) { + size_t visitPositiveInteger(UInt value) { _formatter.writePositiveInteger(value); + return bytesWritten(); } - void visitBoolean(bool value) { + size_t visitBoolean(bool value) { _formatter.writeBoolean(value); + return bytesWritten(); } - void visitNull() { + size_t visitNull() { _formatter.writeRaw("null"); + return bytesWritten(); } + protected: size_t bytesWritten() const { return _formatter.bytesWritten(); } - protected: void write(char c) { _formatter.writeRaw(c); } diff --git a/src/ArduinoJson/Json/PrettyJsonSerializer.hpp b/src/ArduinoJson/Json/PrettyJsonSerializer.hpp index 96315d81..b53b920c 100644 --- a/src/ArduinoJson/Json/PrettyJsonSerializer.hpp +++ b/src/ArduinoJson/Json/PrettyJsonSerializer.hpp @@ -18,44 +18,48 @@ class PrettyJsonSerializer : public JsonSerializer { public: PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {} - void visitArray(const CollectionData &array) { + size_t visitArray(const CollectionData &array) { VariantSlot *slot = array.head(); - if (!slot) - return base::write("[]"); + if (slot) { + base::write("[\r\n"); + _nesting++; + while (slot != 0) { + indent(); + slot->data()->accept(*this); - base::write("[\r\n"); - _nesting++; - while (slot != 0) { + slot = slot->next(); + base::write(slot ? ",\r\n" : "\r\n"); + } + _nesting--; indent(); - slot->data()->accept(*this); - - slot = slot->next(); - base::write(slot ? ",\r\n" : "\r\n"); + base::write("]"); + } else { + base::write("[]"); } - _nesting--; - indent(); - base::write("]"); + return this->bytesWritten(); } - void visitObject(const CollectionData &object) { + size_t visitObject(const CollectionData &object) { VariantSlot *slot = object.head(); - if (!slot) - return base::write("{}"); + if (slot) { + base::write("{\r\n"); + _nesting++; + while (slot != 0) { + indent(); + base::visitString(slot->key()); + base::write(": "); + slot->data()->accept(*this); - base::write("{\r\n"); - _nesting++; - while (slot != 0) { + slot = slot->next(); + base::write(slot ? ",\r\n" : "\r\n"); + } + _nesting--; indent(); - base::visitString(slot->key()); - base::write(": "); - slot->data()->accept(*this); - - slot = slot->next(); - base::write(slot ? ",\r\n" : "\r\n"); + base::write("}"); + } else { + base::write("{}"); } - _nesting--; - indent(); - base::write("}"); + return this->bytesWritten(); } private: diff --git a/src/ArduinoJson/Json/TextFormatter.hpp b/src/ArduinoJson/Json/TextFormatter.hpp index 6e0ca70d..eceef9e0 100644 --- a/src/ArduinoJson/Json/TextFormatter.hpp +++ b/src/ArduinoJson/Json/TextFormatter.hpp @@ -12,17 +12,18 @@ #include #include #include +#include namespace ARDUINOJSON_NAMESPACE { template class TextFormatter { public: - explicit TextFormatter(TWriter writer) : _writer(writer), _length(0) {} + explicit TextFormatter(TWriter writer) : _writer(writer) {} // Returns the number of bytes sent to the TWriter implementation. size_t bytesWritten() const { - return _length; + return _writer.count(); } void writeBoolean(bool value) { @@ -128,28 +129,28 @@ class TextFormatter { } void writeRaw(const char *s) { - _length += _writer.write(reinterpret_cast(s), strlen(s)); + _writer.write(reinterpret_cast(s), strlen(s)); } void writeRaw(const char *s, size_t n) { - _length += _writer.write(reinterpret_cast(s), n); + _writer.write(reinterpret_cast(s), n); } void writeRaw(const char *begin, const char *end) { - _length += _writer.write(reinterpret_cast(begin), - static_cast(end - begin)); + _writer.write(reinterpret_cast(begin), + static_cast(end - begin)); } template void writeRaw(const char (&s)[N]) { - _length += _writer.write(reinterpret_cast(s), N - 1); + _writer.write(reinterpret_cast(s), N - 1); } void writeRaw(char c) { - _length += _writer.write(static_cast(c)); + _writer.write(static_cast(c)); } protected: - TWriter _writer; + CountingDecorator _writer; size_t _length; private: diff --git a/src/ArduinoJson/Misc/Visitable.hpp b/src/ArduinoJson/Misc/Visitable.hpp index f259ae5a..65e2d8e6 100644 --- a/src/ArduinoJson/Misc/Visitable.hpp +++ b/src/ArduinoJson/Misc/Visitable.hpp @@ -8,6 +8,11 @@ namespace ARDUINOJSON_NAMESPACE { +template +struct Visitor { + typedef TResult result_type; +}; + struct Visitable { // template // void accept(Visitor&) const; diff --git a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp index b803241d..e1086367 100644 --- a/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackSerializer.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,19 +15,20 @@ namespace ARDUINOJSON_NAMESPACE { template -class MsgPackSerializer { +class MsgPackSerializer : public Visitor { public: - MsgPackSerializer(TWriter writer) : _writer(writer), _bytesWritten(0) {} + MsgPackSerializer(TWriter writer) : _writer(writer) {} template - typename enable_if::type visitFloat(T value32) { + typename enable_if::type visitFloat(T value32) { writeByte(0xCA); writeInteger(value32); + return bytesWritten(); } template ARDUINOJSON_NO_SANITIZE("float-cast-overflow") - typename enable_if::type visitFloat(T value64) { + typename enable_if::type visitFloat(T value64) { float value32 = float(value64); if (value32 == value64) { writeByte(0xCA); @@ -35,9 +37,10 @@ class MsgPackSerializer { writeByte(0xCB); writeInteger(value64); } + return bytesWritten(); } - void visitArray(const CollectionData& array) { + size_t visitArray(const CollectionData& array) { size_t n = array.size(); if (n < 0x10) { writeByte(uint8_t(0x90 + array.size())); @@ -51,9 +54,10 @@ class MsgPackSerializer { for (VariantSlot* slot = array.head(); slot; slot = slot->next()) { slot->data()->accept(*this); } + return bytesWritten(); } - void visitObject(const CollectionData& object) { + size_t visitObject(const CollectionData& object) { size_t n = object.size(); if (n < 0x10) { writeByte(uint8_t(0x80 + n)); @@ -68,9 +72,10 @@ class MsgPackSerializer { visitString(slot->key()); slot->data()->accept(*this); } + return bytesWritten(); } - void visitString(const char* value) { + size_t visitString(const char* value) { ARDUINOJSON_ASSERT(value != NULL); size_t n = strlen(value); @@ -88,13 +93,15 @@ class MsgPackSerializer { writeInteger(uint32_t(n)); } writeBytes(reinterpret_cast(value), n); + return bytesWritten(); } - void visitRawJson(const char* data, size_t size) { + size_t visitRawJson(const char* data, size_t size) { writeBytes(reinterpret_cast(data), size); + return bytesWritten(); } - void visitNegativeInteger(UInt value) { + size_t visitNegativeInteger(UInt value) { UInt negated = UInt(~value + 1); if (value <= 0x20) { writeInteger(int8_t(negated)); @@ -114,9 +121,10 @@ class MsgPackSerializer { writeInteger(int64_t(negated)); } #endif + return bytesWritten(); } - void visitPositiveInteger(UInt value) { + size_t visitPositiveInteger(UInt value) { if (value <= 0x7F) { writeInteger(uint8_t(value)); } else if (value <= 0xFF) { @@ -141,27 +149,30 @@ class MsgPackSerializer { writeInteger(uint64_t(value)); } #endif + return bytesWritten(); } - void visitBoolean(bool value) { + size_t visitBoolean(bool value) { writeByte(value ? 0xC3 : 0xC2); + return bytesWritten(); } - void visitNull() { + size_t visitNull() { writeByte(0xC0); - } - - size_t bytesWritten() const { - return _bytesWritten; + return bytesWritten(); } private: + size_t bytesWritten() const { + return _writer.count(); + } + void writeByte(uint8_t c) { - _bytesWritten += _writer.write(c); + _writer.write(c); } void writeBytes(const uint8_t* p, size_t n) { - _bytesWritten += _writer.write(p, n); + _writer.write(p, n); } template @@ -170,8 +181,7 @@ class MsgPackSerializer { writeBytes(reinterpret_cast(&value), sizeof(value)); } - TWriter _writer; - size_t _bytesWritten; + CountingDecorator _writer; }; template diff --git a/src/ArduinoJson/Object/MemberProxy.hpp b/src/ArduinoJson/Object/MemberProxy.hpp index 46f4beab..a9ee6034 100644 --- a/src/ArduinoJson/Object/MemberProxy.hpp +++ b/src/ArduinoJson/Object/MemberProxy.hpp @@ -120,8 +120,8 @@ class MemberProxy : public VariantOperators >, return getOrAddUpstreamMember().set(value); } - template - void accept(Visitor &visitor) const { + template + typename TVisitor::result_type accept(TVisitor &visitor) const { return getUpstreamMember().accept(visitor); } diff --git a/src/ArduinoJson/Object/ObjectFunctions.hpp b/src/ArduinoJson/Object/ObjectFunctions.hpp index 0c754eb3..1c7d5f3e 100644 --- a/src/ArduinoJson/Object/ObjectFunctions.hpp +++ b/src/ArduinoJson/Object/ObjectFunctions.hpp @@ -8,12 +8,13 @@ namespace ARDUINOJSON_NAMESPACE { -template -void objectAccept(const CollectionData *obj, Visitor &visitor) { +template +typename TVisitor::result_type objectAccept(const CollectionData *obj, + TVisitor &visitor) { if (obj) - visitor.visitObject(*obj); + return visitor.visitObject(*obj); else - visitor.visitNull(); + return visitor.visitNull(); } inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) { diff --git a/src/ArduinoJson/Object/ObjectRef.hpp b/src/ArduinoJson/Object/ObjectRef.hpp index 599a2ae9..e57e088e 100644 --- a/src/ArduinoJson/Object/ObjectRef.hpp +++ b/src/ArduinoJson/Object/ObjectRef.hpp @@ -22,9 +22,9 @@ class ObjectRefBase { return VariantConstRef(reinterpret_cast(data)); } - template - FORCE_INLINE void accept(Visitor& visitor) const { - objectAccept(_data, visitor); + template + typename TVisitor::result_type accept(TVisitor& visitor) const { + return objectAccept(_data, visitor); } FORCE_INLINE bool isNull() const { diff --git a/src/ArduinoJson/Serialization/CountingDecorator.hpp b/src/ArduinoJson/Serialization/CountingDecorator.hpp new file mode 100644 index 00000000..140ada71 --- /dev/null +++ b/src/ArduinoJson/Serialization/CountingDecorator.hpp @@ -0,0 +1,33 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include + +namespace ARDUINOJSON_NAMESPACE { + +template +class CountingDecorator { + public: + explicit CountingDecorator(TWriter& writer) : _writer(writer), _count(0) {} + + void write(uint8_t c) { + _count += _writer.write(c); + } + + void write(const uint8_t* s, size_t n) { + _count += _writer.write(s, n); + } + + size_t count() const { + return _count; + } + + private: + TWriter _writer; + size_t _count; +}; + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Serialization/measure.hpp b/src/ArduinoJson/Serialization/measure.hpp index e2434042..00f79077 100644 --- a/src/ArduinoJson/Serialization/measure.hpp +++ b/src/ArduinoJson/Serialization/measure.hpp @@ -12,8 +12,7 @@ template