mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +01:00 
			
		
		
		
	Added a return value to visitors
This commit is contained in:
		| @@ -12,12 +12,13 @@ inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) { | ||||
|   return arr ? arr->addElement(pool) : 0; | ||||
| } | ||||
|  | ||||
| template <typename Visitor> | ||||
| inline void arrayAccept(const CollectionData *arr, Visitor &visitor) { | ||||
| template <typename TVisitor> | ||||
| 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) { | ||||
|   | ||||
| @@ -27,9 +27,9 @@ class ArrayRefBase { | ||||
|     return VariantConstRef(reinterpret_cast<const VariantData*>(data)); | ||||
|   } | ||||
|  | ||||
|   template <typename Visitor> | ||||
|   FORCE_INLINE void accept(Visitor& visitor) const { | ||||
|     arrayAccept(_data, visitor); | ||||
|   template <typename TVisitor> | ||||
|   FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const { | ||||
|     return arrayAccept(_data, visitor); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE bool isNull() const { | ||||
|   | ||||
| @@ -98,8 +98,8 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | ||||
|     return getOrAddUpstreamElement().set(value); | ||||
|   } | ||||
|  | ||||
|   template <typename Visitor> | ||||
|   void accept(Visitor& visitor) const { | ||||
|   template <typename TVisitor> | ||||
|   typename TVisitor::result_type accept(TVisitor& visitor) const { | ||||
|     return getUpstreamElement().accept(visitor); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -65,40 +65,61 @@ inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) { | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| class ArrayCopier1D { | ||||
| class ArrayCopier1D : public Visitor<size_t> { | ||||
|  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<T>(slot->data()); | ||||
|     while (slot != 0 && size < _capacity) { | ||||
|       _destination[size++] = variantAs<T>(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 <typename T, size_t N1, size_t N2> | ||||
| class ArrayCopier2D { | ||||
| class ArrayCopier2D : public Visitor<void> { | ||||
|  public: | ||||
|   ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {} | ||||
|  | ||||
| @@ -136,8 +157,8 @@ inline typename enable_if<!is_array<T>::value, size_t>::type copyArray( | ||||
| template <typename TSource, typename T> | ||||
| inline size_t copyArray(const TSource& src, T* dst, size_t len) { | ||||
|   ArrayCopier1D<T> copier(dst, len); | ||||
|   src.accept(copier); | ||||
|   return copier.result(); | ||||
|  | ||||
|   return src.accept(copier); | ||||
| } | ||||
|  | ||||
| // Copy a JsonArray to a 2D array | ||||
|   | ||||
| @@ -15,8 +15,8 @@ namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| class JsonDocument : public Visitable { | ||||
|  public: | ||||
|   template <typename Visitor> | ||||
|   void accept(Visitor& visitor) const { | ||||
|   template <typename TVisitor> | ||||
|   typename TVisitor::result_type accept(TVisitor& visitor) const { | ||||
|     return getVariant().accept(visitor); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -12,11 +12,11 @@ | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TWriter> | ||||
| class JsonSerializer { | ||||
| class JsonSerializer : public Visitor<size_t> { | ||||
|  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); | ||||
|   } | ||||
|   | ||||
| @@ -18,44 +18,48 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> { | ||||
|  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: | ||||
|   | ||||
| @@ -12,17 +12,18 @@ | ||||
| #include <ArduinoJson/Numbers/Integer.hpp> | ||||
| #include <ArduinoJson/Polyfills/assert.hpp> | ||||
| #include <ArduinoJson/Polyfills/attributes.hpp> | ||||
| #include <ArduinoJson/Serialization/CountingDecorator.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TWriter> | ||||
| 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<const uint8_t *>(s), strlen(s)); | ||||
|     _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s)); | ||||
|   } | ||||
|  | ||||
|   void writeRaw(const char *s, size_t n) { | ||||
|     _length += _writer.write(reinterpret_cast<const uint8_t *>(s), n); | ||||
|     _writer.write(reinterpret_cast<const uint8_t *>(s), n); | ||||
|   } | ||||
|  | ||||
|   void writeRaw(const char *begin, const char *end) { | ||||
|     _length += _writer.write(reinterpret_cast<const uint8_t *>(begin), | ||||
|                              static_cast<size_t>(end - begin)); | ||||
|     _writer.write(reinterpret_cast<const uint8_t *>(begin), | ||||
|                   static_cast<size_t>(end - begin)); | ||||
|   } | ||||
|  | ||||
|   template <size_t N> | ||||
|   void writeRaw(const char (&s)[N]) { | ||||
|     _length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1); | ||||
|     _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1); | ||||
|   } | ||||
|   void writeRaw(char c) { | ||||
|     _length += _writer.write(static_cast<uint8_t>(c)); | ||||
|     _writer.write(static_cast<uint8_t>(c)); | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   TWriter _writer; | ||||
|   CountingDecorator<TWriter> _writer; | ||||
|   size_t _length; | ||||
|  | ||||
|  private: | ||||
|   | ||||
| @@ -8,6 +8,11 @@ | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TResult> | ||||
| struct Visitor { | ||||
|   typedef TResult result_type; | ||||
| }; | ||||
|  | ||||
| struct Visitable { | ||||
|   // template<Visitor> | ||||
|   // void accept(Visitor&) const; | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| #include <ArduinoJson/MsgPack/endianess.hpp> | ||||
| #include <ArduinoJson/Polyfills/assert.hpp> | ||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||
| #include <ArduinoJson/Serialization/CountingDecorator.hpp> | ||||
| #include <ArduinoJson/Serialization/measure.hpp> | ||||
| #include <ArduinoJson/Serialization/serialize.hpp> | ||||
| #include <ArduinoJson/Variant/VariantData.hpp> | ||||
| @@ -14,19 +15,20 @@ | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TWriter> | ||||
| class MsgPackSerializer { | ||||
| class MsgPackSerializer : public Visitor<size_t> { | ||||
|  public: | ||||
|   MsgPackSerializer(TWriter writer) : _writer(writer), _bytesWritten(0) {} | ||||
|   MsgPackSerializer(TWriter writer) : _writer(writer) {} | ||||
|  | ||||
|   template <typename T> | ||||
|   typename enable_if<sizeof(T) == 4>::type visitFloat(T value32) { | ||||
|   typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) { | ||||
|     writeByte(0xCA); | ||||
|     writeInteger(value32); | ||||
|     return bytesWritten(); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   ARDUINOJSON_NO_SANITIZE("float-cast-overflow") | ||||
|   typename enable_if<sizeof(T) == 8>::type visitFloat(T value64) { | ||||
|   typename enable_if<sizeof(T) == 8, size_t>::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<const uint8_t*>(value), n); | ||||
|     return bytesWritten(); | ||||
|   } | ||||
|  | ||||
|   void visitRawJson(const char* data, size_t size) { | ||||
|   size_t visitRawJson(const char* data, size_t size) { | ||||
|     writeBytes(reinterpret_cast<const uint8_t*>(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 <typename T> | ||||
| @@ -170,8 +181,7 @@ class MsgPackSerializer { | ||||
|     writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value)); | ||||
|   } | ||||
|  | ||||
|   TWriter _writer; | ||||
|   size_t _bytesWritten; | ||||
|   CountingDecorator<TWriter> _writer; | ||||
| }; | ||||
|  | ||||
| template <typename TSource, typename TDestination> | ||||
|   | ||||
| @@ -120,8 +120,8 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >, | ||||
|     return getOrAddUpstreamMember().set(value); | ||||
|   } | ||||
|  | ||||
|   template <typename Visitor> | ||||
|   void accept(Visitor &visitor) const { | ||||
|   template <typename TVisitor> | ||||
|   typename TVisitor::result_type accept(TVisitor &visitor) const { | ||||
|     return getUpstreamMember().accept(visitor); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -8,12 +8,13 @@ | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename Visitor> | ||||
| void objectAccept(const CollectionData *obj, Visitor &visitor) { | ||||
| template <typename TVisitor> | ||||
| 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) { | ||||
|   | ||||
| @@ -22,9 +22,9 @@ class ObjectRefBase { | ||||
|     return VariantConstRef(reinterpret_cast<const VariantData*>(data)); | ||||
|   } | ||||
|  | ||||
|   template <typename Visitor> | ||||
|   FORCE_INLINE void accept(Visitor& visitor) const { | ||||
|     objectAccept(_data, visitor); | ||||
|   template <typename TVisitor> | ||||
|   typename TVisitor::result_type accept(TVisitor& visitor) const { | ||||
|     return objectAccept(_data, visitor); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE bool isNull() const { | ||||
|   | ||||
							
								
								
									
										33
									
								
								src/ArduinoJson/Serialization/CountingDecorator.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/ArduinoJson/Serialization/CountingDecorator.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| // ArduinoJson - arduinojson.org | ||||
| // Copyright Benoit Blanchon 2014-2020 | ||||
| // MIT License | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <ArduinoJson/Namespace.hpp> | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TWriter> | ||||
| 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 | ||||
| @@ -12,8 +12,7 @@ template <template <typename> class TSerializer, typename TSource> | ||||
| size_t measure(const TSource &source) { | ||||
|   DummyWriter dp; | ||||
|   TSerializer<DummyWriter> serializer(dp); | ||||
|   source.accept(serializer); | ||||
|   return serializer.bytesWritten(); | ||||
|   return source.accept(serializer); | ||||
| } | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -12,8 +12,7 @@ template <template <typename> class TSerializer, typename TSource, | ||||
|           typename TWriter> | ||||
| size_t doSerialize(const TSource &source, TWriter writer) { | ||||
|   TSerializer<TWriter> serializer(writer); | ||||
|   source.accept(serializer); | ||||
|   return serializer.bytesWritten(); | ||||
|   return source.accept(serializer); | ||||
| } | ||||
|  | ||||
| template <template <typename> class TSerializer, typename TSource, | ||||
|   | ||||
| @@ -14,20 +14,34 @@ namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| class CollectionData; | ||||
|  | ||||
| struct ComparerBase { | ||||
|   CompareResult result; | ||||
|  | ||||
|   ComparerBase() : result(COMPARE_RESULT_DIFFER) {} | ||||
|  | ||||
|   void visitArray(const CollectionData &) {} | ||||
|   void visitBoolean(bool) {} | ||||
|   void visitFloat(Float) {} | ||||
|   void visitNegativeInteger(UInt) {} | ||||
|   void visitNull() {} | ||||
|   void visitObject(const CollectionData &) {} | ||||
|   void visitPositiveInteger(UInt) {} | ||||
|   void visitRawJson(const char *, size_t) {} | ||||
|   void visitString(const char *) {} | ||||
| struct ComparerBase : Visitor<CompareResult> { | ||||
|   CompareResult visitArray(const CollectionData &) { | ||||
|     return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
|   CompareResult visitBoolean(bool) { | ||||
|     return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
|   CompareResult visitFloat(Float) { | ||||
|     return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
|   CompareResult visitNegativeInteger(UInt) { | ||||
|     return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
|   CompareResult visitNull() { | ||||
|     return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
|   CompareResult visitObject(const CollectionData &) { | ||||
|     return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
|   CompareResult visitPositiveInteger(UInt) { | ||||
|     return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
|   CompareResult visitRawJson(const char *, size_t) { | ||||
|     return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
|   CompareResult visitString(const char *) { | ||||
|     return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename T, typename Enable = void> | ||||
| @@ -40,19 +54,21 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type> | ||||
|  | ||||
|   explicit Comparer(T value) : rhs(value) {} | ||||
|  | ||||
|   void visitString(const char *lhs) { | ||||
|   CompareResult visitString(const char *lhs) { | ||||
|     int i = adaptString(rhs).compare(lhs); | ||||
|     if (i < 0) | ||||
|       result = COMPARE_RESULT_GREATER; | ||||
|       return COMPARE_RESULT_GREATER; | ||||
|     else if (i > 0) | ||||
|       result = COMPARE_RESULT_LESS; | ||||
|       return COMPARE_RESULT_LESS; | ||||
|     else | ||||
|       result = COMPARE_RESULT_EQUAL; | ||||
|       return COMPARE_RESULT_EQUAL; | ||||
|   } | ||||
|  | ||||
|   void visitNull() { | ||||
|   CompareResult visitNull() { | ||||
|     if (adaptString(rhs).isNull()) | ||||
|       result = COMPARE_RESULT_EQUAL; | ||||
|       return COMPARE_RESULT_EQUAL; | ||||
|     else | ||||
|       return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -64,26 +80,26 @@ struct Comparer<T, typename enable_if<is_integral<T>::value || | ||||
|  | ||||
|   explicit Comparer(T value) : rhs(value) {} | ||||
|  | ||||
|   void visitFloat(Float lhs) { | ||||
|     result = arithmeticCompare(lhs, rhs); | ||||
|   CompareResult visitFloat(Float lhs) { | ||||
|     return arithmeticCompare(lhs, rhs); | ||||
|   } | ||||
|  | ||||
|   void visitNegativeInteger(UInt lhs) { | ||||
|     result = arithmeticCompareNegateLeft(lhs, rhs); | ||||
|   CompareResult visitNegativeInteger(UInt lhs) { | ||||
|     return arithmeticCompareNegateLeft(lhs, rhs); | ||||
|   } | ||||
|  | ||||
|   void visitPositiveInteger(UInt lhs) { | ||||
|     result = arithmeticCompare(lhs, rhs); | ||||
|   CompareResult visitPositiveInteger(UInt lhs) { | ||||
|     return arithmeticCompare(lhs, rhs); | ||||
|   } | ||||
|  | ||||
|   void visitBoolean(bool lhs) { | ||||
|     visitPositiveInteger(static_cast<UInt>(lhs)); | ||||
|   CompareResult visitBoolean(bool lhs) { | ||||
|     return visitPositiveInteger(static_cast<UInt>(lhs)); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| struct NullComparer : ComparerBase { | ||||
|   void visitNull() { | ||||
|     result = COMPARE_RESULT_EQUAL; | ||||
|   CompareResult visitNull() { | ||||
|     return COMPARE_RESULT_EQUAL; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -99,9 +115,11 @@ struct ArrayComparer : ComparerBase { | ||||
|  | ||||
|   explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {} | ||||
|  | ||||
|   void visitArray(const CollectionData &lhs) { | ||||
|   CompareResult visitArray(const CollectionData &lhs) { | ||||
|     if (lhs.equalsArray(*_rhs)) | ||||
|       result = COMPARE_RESULT_EQUAL; | ||||
|       return COMPARE_RESULT_EQUAL; | ||||
|     else | ||||
|       return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -110,20 +128,20 @@ struct NegativeIntegerComparer : ComparerBase { | ||||
|  | ||||
|   explicit NegativeIntegerComparer(UInt rhs) : _rhs(rhs) {} | ||||
|  | ||||
|   void visitFloat(Float lhs) { | ||||
|     result = arithmeticCompareNegateRight(lhs, _rhs); | ||||
|   CompareResult visitFloat(Float lhs) { | ||||
|     return arithmeticCompareNegateRight(lhs, _rhs); | ||||
|   } | ||||
|  | ||||
|   void visitNegativeInteger(UInt lhs) { | ||||
|     result = arithmeticCompare(_rhs, lhs); | ||||
|   CompareResult visitNegativeInteger(UInt lhs) { | ||||
|     return arithmeticCompare(_rhs, lhs); | ||||
|   } | ||||
|  | ||||
|   void visitPositiveInteger(UInt) { | ||||
|     result = COMPARE_RESULT_GREATER; | ||||
|   CompareResult visitPositiveInteger(UInt) { | ||||
|     return COMPARE_RESULT_GREATER; | ||||
|   } | ||||
|  | ||||
|   void visitBoolean(bool) { | ||||
|     result = COMPARE_RESULT_GREATER; | ||||
|   CompareResult visitBoolean(bool) { | ||||
|     return COMPARE_RESULT_GREATER; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -132,9 +150,11 @@ struct ObjectComparer : ComparerBase { | ||||
|  | ||||
|   explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {} | ||||
|  | ||||
|   void visitObject(const CollectionData &lhs) { | ||||
|   CompareResult visitObject(const CollectionData &lhs) { | ||||
|     if (lhs.equalsObject(*_rhs)) | ||||
|       result = COMPARE_RESULT_EQUAL; | ||||
|       return COMPARE_RESULT_EQUAL; | ||||
|     else | ||||
|       return COMPARE_RESULT_DIFFER; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -145,15 +165,15 @@ struct RawComparer : ComparerBase { | ||||
|   explicit RawComparer(const char *rhsData, size_t rhsSize) | ||||
|       : _rhsData(rhsData), _rhsSize(rhsSize) {} | ||||
|  | ||||
|   void visitRawJson(const char *lhsData, size_t lhsSize) { | ||||
|   CompareResult visitRawJson(const char *lhsData, size_t lhsSize) { | ||||
|     size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize; | ||||
|     int n = memcmp(lhsData, _rhsData, size); | ||||
|     if (n < 0) | ||||
|       result = COMPARE_RESULT_LESS; | ||||
|       return COMPARE_RESULT_LESS; | ||||
|     else if (n > 0) | ||||
|       result = COMPARE_RESULT_GREATER; | ||||
|       return COMPARE_RESULT_GREATER; | ||||
|     else | ||||
|       result = COMPARE_RESULT_EQUAL; | ||||
|       return COMPARE_RESULT_EQUAL; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -164,65 +184,62 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type> | ||||
|  | ||||
|   explicit Comparer(T value) : rhs(value) {} | ||||
|  | ||||
|   void visitArray(const CollectionData &lhs) { | ||||
|   CompareResult visitArray(const CollectionData &lhs) { | ||||
|     ArrayComparer comparer(lhs); | ||||
|     accept(comparer); | ||||
|     return accept(comparer); | ||||
|   } | ||||
|  | ||||
|   void visitObject(const CollectionData &lhs) { | ||||
|   CompareResult visitObject(const CollectionData &lhs) { | ||||
|     ObjectComparer comparer(lhs); | ||||
|     accept(comparer); | ||||
|     return accept(comparer); | ||||
|   } | ||||
|  | ||||
|   void visitFloat(Float lhs) { | ||||
|   CompareResult visitFloat(Float lhs) { | ||||
|     Comparer<Float> comparer(lhs); | ||||
|     accept(comparer); | ||||
|     return accept(comparer); | ||||
|   } | ||||
|  | ||||
|   void visitString(const char *lhs) { | ||||
|   CompareResult visitString(const char *lhs) { | ||||
|     Comparer<const char *> comparer(lhs); | ||||
|     accept(comparer); | ||||
|     return accept(comparer); | ||||
|   } | ||||
|  | ||||
|   void visitRawJson(const char *lhsData, size_t lhsSize) { | ||||
|   CompareResult visitRawJson(const char *lhsData, size_t lhsSize) { | ||||
|     RawComparer comparer(lhsData, lhsSize); | ||||
|     accept(comparer); | ||||
|     return accept(comparer); | ||||
|   } | ||||
|  | ||||
|   void visitNegativeInteger(UInt lhs) { | ||||
|   CompareResult visitNegativeInteger(UInt lhs) { | ||||
|     NegativeIntegerComparer comparer(lhs); | ||||
|     accept(comparer); | ||||
|     return accept(comparer); | ||||
|   } | ||||
|  | ||||
|   void visitPositiveInteger(UInt lhs) { | ||||
|   CompareResult visitPositiveInteger(UInt lhs) { | ||||
|     Comparer<UInt> comparer(lhs); | ||||
|     accept(comparer); | ||||
|     return accept(comparer); | ||||
|   } | ||||
|  | ||||
|   void visitBoolean(bool lhs) { | ||||
|   CompareResult visitBoolean(bool lhs) { | ||||
|     Comparer<bool> comparer(lhs); | ||||
|     accept(comparer); | ||||
|     return accept(comparer); | ||||
|   } | ||||
|  | ||||
|   void visitNull() { | ||||
|   CompareResult visitNull() { | ||||
|     NullComparer comparer; | ||||
|     accept(comparer); | ||||
|     return accept(comparer); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   template <typename TComparer> | ||||
|   void accept(TComparer &comparer) { | ||||
|     rhs.accept(comparer); | ||||
|     switch (comparer.result) { | ||||
|   CompareResult accept(TComparer &comparer) { | ||||
|     CompareResult reversedResult = rhs.accept(comparer); | ||||
|     switch (reversedResult) { | ||||
|       case COMPARE_RESULT_GREATER: | ||||
|         result = COMPARE_RESULT_LESS; | ||||
|         break; | ||||
|         return COMPARE_RESULT_LESS; | ||||
|       case COMPARE_RESULT_LESS: | ||||
|         result = COMPARE_RESULT_GREATER; | ||||
|         break; | ||||
|         return COMPARE_RESULT_GREATER; | ||||
|       default: | ||||
|         result = comparer.result; | ||||
|         break; | ||||
|         return reversedResult; | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| @@ -230,8 +247,7 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type> | ||||
| template <typename T1, typename T2> | ||||
| CompareResult compare(const T1 &lhs, const T2 &rhs) { | ||||
|   Comparer<T2> comparer(rhs); | ||||
|   lhs.accept(comparer); | ||||
|   return comparer.result; | ||||
|   return lhs.accept(comparer); | ||||
| } | ||||
|  | ||||
| inline int variantCompare(const VariantData *a, const VariantData *b) { | ||||
|   | ||||
| @@ -34,8 +34,8 @@ class VariantData { | ||||
|   // - no virtual | ||||
|   // - no inheritance | ||||
|  | ||||
|   template <typename Visitor> | ||||
|   void accept(Visitor &visitor) const { | ||||
|   template <typename TVisitor> | ||||
|   typename TVisitor::result_type accept(TVisitor &visitor) const { | ||||
|     switch (type()) { | ||||
|       case VALUE_IS_FLOAT: | ||||
|         return visitor.visitFloat(_content.asFloat); | ||||
|   | ||||
| @@ -9,12 +9,13 @@ | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename Visitor> | ||||
| inline void variantAccept(const VariantData *var, Visitor &visitor) { | ||||
| template <typename TVisitor> | ||||
| inline typename TVisitor::result_type variantAccept(const VariantData *var, | ||||
|                                                     TVisitor &visitor) { | ||||
|   if (var != 0) | ||||
|     var->accept(visitor); | ||||
|     return var->accept(visitor); | ||||
|   else | ||||
|     visitor.visitNull(); | ||||
|     return visitor.visitNull(); | ||||
| } | ||||
|  | ||||
| inline const CollectionData *variantAsArray(const VariantData *var) { | ||||
|   | ||||
| @@ -261,9 +261,9 @@ class VariantRef : public VariantRefBase<VariantData>, | ||||
|     return variantAs<T>(_data, _pool); | ||||
|   } | ||||
|  | ||||
|   template <typename Visitor> | ||||
|   void accept(Visitor &visitor) const { | ||||
|     variantAccept(_data, visitor); | ||||
|   template <typename TVisitor> | ||||
|   typename TVisitor::result_type accept(TVisitor &visitor) const { | ||||
|     return variantAccept(_data, visitor); | ||||
|   } | ||||
|  | ||||
|   // Change the type of the variant | ||||
| @@ -347,9 +347,9 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | ||||
|   VariantConstRef(const VariantData *data) : base_type(data) {} | ||||
|   VariantConstRef(VariantRef var) : base_type(var._data) {} | ||||
|  | ||||
|   template <typename Visitor> | ||||
|   void accept(Visitor &visitor) const { | ||||
|     variantAccept(_data, visitor); | ||||
|   template <typename TVisitor> | ||||
|   typename TVisitor::result_type accept(TVisitor &visitor) const { | ||||
|     return variantAccept(_data, visitor); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user