diff --git a/wled00/src/dependencies/json/ArduinoJson-v6.h b/wled00/src/dependencies/json/ArduinoJson-v6.h index 5d8d40799..3913d7110 100644 --- a/wled00/src/dependencies/json/ArduinoJson-v6.h +++ b/wled00/src/dependencies/json/ArduinoJson-v6.h @@ -164,6 +164,9 @@ #define ARDUINOJSON_DEBUG 0 #endif #endif +#if ARDUINOJSON_HAS_NULLPTR && defined(nullptr) +#error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr +#endif #if !ARDUINOJSON_DEBUG #ifdef __clang__ #pragma clang system_header @@ -171,11 +174,16 @@ #pragma GCC system_header #endif #endif -#define ARDUINOJSON_VERSION "6.16.1" -#define ARDUINOJSON_VERSION_MAJOR 6 -#define ARDUINOJSON_VERSION_MINOR 16 -#define ARDUINOJSON_VERSION_REVISION 1 -#ifndef ARDUINOJSON_NAMESPACE +#define ARDUINOJSON_EXPAND6(a, b, c, d, e, f) a, b, c, d, e, f +#define ARDUINOJSON_EXPAND7(a, b, c, d, e, f, g) a, b, c, d, e, f, g +#define ARDUINOJSON_EXPAND9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i +#define ARDUINOJSON_EXPAND18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, \ + q, r) \ + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r +#define ARDUINOJSON_CONCAT_(A, B) A##B +#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B) +#define ARDUINOJSON_CONCAT4(A, B, C, D) \ + ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D)) #define ARDUINOJSON_HEX_DIGIT_0000() 0 #define ARDUINOJSON_HEX_DIGIT_0001() 1 #define ARDUINOJSON_HEX_DIGIT_0010() 2 @@ -194,21 +202,22 @@ #define ARDUINOJSON_HEX_DIGIT_1111() F #define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D() #define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D) -#define ARDUINOJSON_CONCAT_(A, B) A##B -#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B) -#define ARDUINOJSON_CONCAT4(A, B, C, D) \ - ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D)) -#define ARDUINOJSON_NAMESPACE \ - ARDUINOJSON_CONCAT4( \ - ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \ - ARDUINOJSON_VERSION_MINOR, \ - ARDUINOJSON_VERSION_REVISION), \ - _, \ - ARDUINOJSON_HEX_DIGIT(0, ARDUINOJSON_USE_LONG_LONG, \ - ARDUINOJSON_USE_DOUBLE, \ - ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \ - ARDUINOJSON_HEX_DIGIT( \ - ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \ +#define ARDUINOJSON_VERSION "6.17.0" +#define ARDUINOJSON_VERSION_MAJOR 6 +#define ARDUINOJSON_VERSION_MINOR 17 +#define ARDUINOJSON_VERSION_REVISION 0 +#ifndef ARDUINOJSON_NAMESPACE +#define ARDUINOJSON_NAMESPACE \ + ARDUINOJSON_CONCAT4( \ + ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \ + ARDUINOJSON_VERSION_MINOR, \ + ARDUINOJSON_VERSION_REVISION), \ + _, \ + ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM, \ + ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \ + ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \ + ARDUINOJSON_HEX_DIGIT( \ + ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \ ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE)) #endif #if ARDUINOJSON_DEBUG @@ -264,12 +273,13 @@ class CollectionData { 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) { if (lhs == rhs) @@ -314,13 +324,6 @@ inline T *addPadding(T *p) { size_t address = addPadding(reinterpret_cast(p)); return reinterpret_cast(address); } -} // namespace ARDUINOJSON_NAMESPACE -#define JSON_STRING_SIZE(SIZE) (SIZE + 1) -namespace ARDUINOJSON_NAMESPACE { -struct StringSlot { - char *value; - size_t size; -}; template Y)> struct Max {}; template @@ -334,24 +337,6 @@ struct Max { } // namespace ARDUINOJSON_NAMESPACE #include namespace ARDUINOJSON_NAMESPACE { -template -class not_null { - public: - explicit not_null(T ptr) : _ptr(ptr) { - ARDUINOJSON_ASSERT(ptr != NULL); - } - T get() const { - ARDUINOJSON_ASSERT(_ptr != NULL); - return _ptr; - } - private: - T _ptr; -}; -template -not_null make_not_null(T ptr) { - ARDUINOJSON_ASSERT(ptr != NULL); - return not_null(ptr); -} template struct conditional { typedef TrueType type; @@ -469,6 +454,10 @@ struct is_enum { !is_class::value && !is_integral::value && !is_floating_point::value; }; +template +struct is_pointer : false_type {}; +template +struct is_pointer : true_type {}; template struct is_signed : false_type {}; template <> @@ -694,6 +683,7 @@ class VariantSlot { }; } // namespace ARDUINOJSON_NAMESPACE #include +#define JSON_STRING_SIZE(SIZE) (SIZE + 1) namespace ARDUINOJSON_NAMESPACE { class MemoryPool { public: @@ -701,7 +691,8 @@ class MemoryPool { : _begin(buf), _left(buf), _right(buf ? buf + capa : 0), - _end(buf ? buf + capa : 0) { + _end(buf ? buf + capa : 0), + _overflowed(false) { ARDUINOJSON_ASSERT(isAligned(_begin)); ARDUINOJSON_ASSERT(isAligned(_right)); ARDUINOJSON_ASSERT(isAligned(_end)); @@ -715,6 +706,9 @@ class MemoryPool { size_t size() const { return size_t(_left - _begin + _end - _right); } + bool overflowed() const { + return _overflowed; + } VariantSlot* allocVariant() { return allocRight(); } @@ -750,9 +744,13 @@ class MemoryPool { checkInvariants(); return str; } + void markAsOverflowed() { + _overflowed = true; + } void clear() { _left = _begin; _right = _end; + _overflowed = false; } bool canAlloc(size_t bytes) const { return _left + bytes <= _right; @@ -781,9 +779,6 @@ class MemoryPool { _end += offset; } private: - StringSlot* allocStringSlot() { - return allocRight(); - } void checkInvariants() { ARDUINOJSON_ASSERT(_begin <= _left); ARDUINOJSON_ASSERT(_left <= _right); @@ -805,8 +800,10 @@ class MemoryPool { } #endif char* allocString(size_t n) { - if (!canAlloc(n)) + if (!canAlloc(n)) { + _overflowed = true; return 0; + } char* s = _left; _left += n; checkInvariants(); @@ -817,12 +814,15 @@ class MemoryPool { return reinterpret_cast(allocRight(sizeof(T))); } void* allocRight(size_t bytes) { - if (!canAlloc(bytes)) + if (!canAlloc(bytes)) { + _overflowed = true; return 0; + } _right -= bytes; return _right; } char *_begin, *_left, *_right, *_end; + bool _overflowed; }; inline int safe_strcmp(const char* a, const char* b) { if (a == b) @@ -940,9 +940,9 @@ inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) { #include namespace ARDUINOJSON_NAMESPACE { template -class StlStringAdapter { +class StdStringAdapter { public: - StlStringAdapter(const TString& str) : _str(&str) {} + StdStringAdapter(const TString& str) : _str(&str) {} void copyTo(char* p, size_t n) const { memcpy(p, _str->c_str(), n); } @@ -973,15 +973,14 @@ template struct IsString > : true_type { }; template -inline StlStringAdapter > +inline StdStringAdapter > adaptString(const std::basic_string& str) { - return StlStringAdapter >( + return StdStringAdapter >( str); } } // namespace ARDUINOJSON_NAMESPACE #endif #if ARDUINOJSON_ENABLE_ARDUINO_STRING -#include namespace ARDUINOJSON_NAMESPACE { class ArduinoStringAdapter { public: @@ -1269,6 +1268,44 @@ T alias_cast(F raw_data) { ac.raw = raw_data; return ac.data; } +} // namespace ARDUINOJSON_NAMESPACE +#if ARDUINOJSON_ENABLE_PROGMEM +namespace ARDUINOJSON_NAMESPACE { +template +typename enable_if::value, T>::type pgm_read(const void* p) { + return reinterpret_cast(pgm_read_ptr(p)); +} +template +typename enable_if::value && + sizeof(T) == sizeof(float), // on AVR sizeof(double) == + T>::type +pgm_read(const void* p) { + return pgm_read_float(p); +} +template +typename enable_if::value, T>::type pgm_read( + const void* p) { + return pgm_read_dword(p); +} +} // namespace ARDUINOJSON_NAMESPACE +#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY +#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ + static type const name[] PROGMEM = value; +#endif +#ifndef ARDUINOJSON_READ_STATIC_ARRAY +#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \ + pgm_read(name + index) +#endif +#else // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0 +#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY +#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ + static type const name[] = value; +#endif +#ifndef ARDUINOJSON_READ_STATIC_ARRAY +#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index] +#endif +#endif +namespace ARDUINOJSON_NAMESPACE { template struct FloatTraits {}; template @@ -1298,46 +1335,58 @@ struct FloatTraits { return m; } static T positiveBinaryPowerOfTen(int index) { - static T factors[] = { - 1e1, - 1e2, - 1e4, - 1e8, - 1e16, - forge(0x4693B8B5, 0xB5056E17), // 1e32 - forge(0x4D384F03, 0xE93FF9F5), // 1e64 - forge(0x5A827748, 0xF9301D32), // 1e128 - forge(0x75154FDD, 0x7F73BF3C) // 1e256 - }; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( // + uint32_t, factors, + ARDUINOJSON_EXPAND18({ + 0x40240000, 0x00000000, // 1e1 + 0x40590000, 0x00000000, // 1e2 + 0x40C38800, 0x00000000, // 1e4 + 0x4197D784, 0x00000000, // 1e8 + 0x4341C379, 0x37E08000, // 1e16 + 0x4693B8B5, 0xB5056E17, // 1e32 + 0x4D384F03, 0xE93FF9F5, // 1e64 + 0x5A827748, 0xF9301D32, // 1e128 + 0x75154FDD, 0x7F73BF3C // 1e256 + })); + return forge( + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index), + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1)); } static T negativeBinaryPowerOfTen(int index) { - static T factors[] = { - forge(0x3FB99999, 0x9999999A), // 1e-1 - forge(0x3F847AE1, 0x47AE147B), // 1e-2 - forge(0x3F1A36E2, 0xEB1C432D), // 1e-4 - forge(0x3E45798E, 0xE2308C3A), // 1e-8 - forge(0x3C9CD2B2, 0x97D889BC), // 1e-16 - forge(0x3949F623, 0xD5A8A733), // 1e-32 - forge(0x32A50FFD, 0x44F4A73D), // 1e-64 - forge(0x255BBA08, 0xCF8C979D), // 1e-128 - forge(0x0AC80628, 0x64AC6F43) // 1e-256 - }; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( // + uint32_t, factors, + ARDUINOJSON_EXPAND18({ + 0x3FB99999, 0x9999999A, // 1e-1 + 0x3F847AE1, 0x47AE147B, // 1e-2 + 0x3F1A36E2, 0xEB1C432D, // 1e-4 + 0x3E45798E, 0xE2308C3A, // 1e-8 + 0x3C9CD2B2, 0x97D889BC, // 1e-16 + 0x3949F623, 0xD5A8A733, // 1e-32 + 0x32A50FFD, 0x44F4A73D, // 1e-64 + 0x255BBA08, 0xCF8C979D, // 1e-128 + 0x0AC80628, 0x64AC6F43 // 1e-256 + })); + return forge( + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index), + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1)); } static T negativeBinaryPowerOfTenPlusOne(int index) { - static T factors[] = { - 1e0, - forge(0x3FB99999, 0x9999999A), // 1e-1 - forge(0x3F50624D, 0xD2F1A9FC), // 1e-3 - forge(0x3E7AD7F2, 0x9ABCAF48), // 1e-7 - forge(0x3CD203AF, 0x9EE75616), // 1e-15 - forge(0x398039D6, 0x65896880), // 1e-31 - forge(0x32DA53FC, 0x9631D10D), // 1e-63 - forge(0x25915445, 0x81B7DEC2), // 1e-127 - forge(0x0AFE07B2, 0x7DD78B14) // 1e-255 - }; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( // + uint32_t, factors, + ARDUINOJSON_EXPAND18({ + 0x3FF00000, 0x00000000, // 1e0 + 0x3FB99999, 0x9999999A, // 1e-1 + 0x3F50624D, 0xD2F1A9FC, // 1e-3 + 0x3E7AD7F2, 0x9ABCAF48, // 1e-7 + 0x3CD203AF, 0x9EE75616, // 1e-15 + 0x398039D6, 0x65896880, // 1e-31 + 0x32DA53FC, 0x9631D10D, // 1e-63 + 0x25915445, 0x81B7DEC2, // 1e-127 + 0x0AFE07B2, 0x7DD78B14 // 1e-255 + })); + return forge( + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index), + ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1)); } static T nan() { return forge(0x7ff80000, 0x00000000); @@ -1382,16 +1431,22 @@ struct FloatTraits { return m; } static T positiveBinaryPowerOfTen(int index) { - static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( + T, factors, + ARDUINOJSON_EXPAND6({1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f})); + return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index); } static T negativeBinaryPowerOfTen(int index) { - static T factors[] = {1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( + T, factors, + ARDUINOJSON_EXPAND6({1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f})); + return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index); } static T negativeBinaryPowerOfTenPlusOne(int index) { - static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( + T, factors, + ARDUINOJSON_EXPAND6({1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f})); + return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index); } static T forge(uint32_t bits) { return alias_cast(bits); @@ -1524,8 +1579,11 @@ class VariantData { VariantContent _content; // must be first to allow cast from array to variant uint8_t _flags; public: - template - void accept(Visitor &visitor) const { + void init() { + _flags = 0; + } + template + typename TVisitor::result_type accept(TVisitor &visitor) const { switch (type()) { case VALUE_IS_FLOAT: return visitor.visitFloat(_content.asFloat); @@ -1690,23 +1748,13 @@ class VariantData { void setNull() { setType(VALUE_IS_NULL); } - void setString(not_null s, storage_policies::store_by_copy) { + void setStringPointer(const char *s, storage_policies::store_by_copy) { setType(VALUE_IS_OWNED_STRING); - _content.asString = s.get(); + _content.asString = s; } - void setString(not_null s, storage_policies::store_by_address) { + void setStringPointer(const char *s, storage_policies::store_by_address) { setType(VALUE_IS_LINKED_STRING); - _content.asString = s.get(); - } - template - bool setString(const char *s, TStoragePolicy storage_policy) { - if (s) { - setString(make_not_null(s), storage_policy); - return true; - } else { - setType(VALUE_IS_NULL); - return false; - } + _content.asString = s; } template bool setString(TAdaptedString value, MemoryPool *pool) { @@ -1723,13 +1771,26 @@ class VariantData { template inline bool setString(TAdaptedString value, MemoryPool *, storage_policies::store_by_address) { - return setString(value.data(), storage_policies::store_by_address()); + if (value.isNull()) + setNull(); + else + setStringPointer(value.data(), storage_policies::store_by_address()); + return true; } template inline bool setString(TAdaptedString value, MemoryPool *pool, storage_policies::store_by_copy) { - return setString(pool->saveString(value), - storage_policies::store_by_copy()); + if (value.isNull()) { + setNull(); + return true; + } + const char *copy = pool->saveString(value); + if (!copy) { + setNull(); + return false; + } + setStringPointer(copy, storage_policies::store_by_copy()); + return true; } CollectionData &toArray() { setType(VALUE_IS_ARRAY); @@ -1795,10 +1856,10 @@ class VariantData { if (_flags & COLLECTION_MASK) _content.asCollection.movePointers(stringDistance, variantDistance); } - private: uint8_t type() const { return _flags & VALUE_MASK; } + private: void setType(uint8_t t) { _flags &= KEY_IS_OWNED; _flags |= t; @@ -1854,6 +1915,10 @@ inline size_t slotSize(const VariantSlot* var) { inline VariantData* slotData(VariantSlot* slot) { return reinterpret_cast(slot); } +template +struct Visitor { + typedef TResult result_type; +}; struct Visitable { }; template @@ -1985,12 +2050,13 @@ inline typename enable_if::value, T>::type variantAs( #define ARDUINOJSON_NO_SANITIZE(check) #endif namespace ARDUINOJSON_NAMESPACE { -template -inline void variantAccept(const VariantData *var, Visitor &visitor) { +template +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) { return var != 0 ? var->asArray() : 0; @@ -2211,14 +2277,16 @@ CompareResult compare(const T1 &lhs, const T2 &rhs); // VariantCompare.cpp template struct VariantOperators { template - friend T operator|(const TVariant &variant, const T &defaultValue) { + friend typename enable_if::value, T>::type operator|( + const TVariant &variant, const T &defaultValue) { if (variant.template is()) return variant.template as(); else return defaultValue; } - friend const char *operator|(const TVariant &variant, - const char *defaultValue) { + template + friend typename enable_if::value, T>::type operator|( + const TVariant &variant, T defaultValue) { const char *value = variant.template as(); return value ? value : defaultValue; } @@ -2536,9 +2604,9 @@ class VariantRef : public VariantRefBase, FORCE_INLINE operator T() const { return variantAs(_data, _pool); } - template - void accept(Visitor &visitor) const { - variantAccept(_data, visitor); + template + typename TVisitor::result_type accept(TVisitor &visitor) const { + return variantAccept(_data, visitor); } template typename enable_if::value, ArrayRef>::type to() const; @@ -2588,9 +2656,9 @@ class VariantConstRef : public VariantRefBase, VariantConstRef() : base_type(0) {} VariantConstRef(const VariantData *data) : base_type(data) {} VariantConstRef(VariantRef var) : base_type(var._data) {} - template - void accept(Visitor &visitor) const { - variantAccept(_data, visitor); + template + typename TVisitor::result_type accept(TVisitor &visitor) const { + return variantAccept(_data, visitor); } template FORCE_INLINE typename VariantConstAs::type as() const { @@ -2727,9 +2795,9 @@ class ArrayRefBase { const void* data = _data; // prevent warning cast-align 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 { return _data == 0; @@ -2830,12 +2898,13 @@ class ArrayRef : public ArrayRefBase, private: MemoryPool* _pool; }; -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) { if (lhs == rhs) @@ -3049,9 +3118,9 @@ class ObjectRefBase { const void* data = _data; // prevent warning cast-align 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 { return _data == 0; @@ -3273,8 +3342,8 @@ class ElementProxy : public VariantOperators >, FORCE_INLINE bool set(TValue* value) const { return getOrAddUpstreamElement().set(value); } - template - void accept(Visitor& visitor) const { + template + typename TVisitor::result_type accept(TVisitor& visitor) const { return getUpstreamElement().accept(visitor); } FORCE_INLINE size_t size() const { @@ -3411,8 +3480,8 @@ class MemberProxy : public VariantOperators >, FORCE_INLINE bool set(TChar *value) { return getOrAddUpstreamMember().set(value); } - template - void accept(Visitor &visitor) const { + template + typename TVisitor::result_type accept(TVisitor &visitor) const { return getUpstreamMember().accept(visitor); } FORCE_INLINE VariantRef addElement() const { @@ -3457,8 +3526,8 @@ class MemberProxy : public VariantOperators >, 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); } template @@ -3483,6 +3552,9 @@ class JsonDocument : public Visitable { size_t memoryUsage() const { return _pool.size(); } + bool overflowed() const { + return _pool.overflowed(); + } size_t nesting() const { return _data.nesting(); } @@ -3888,35 +3960,49 @@ inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) { return copyArray(src, dst.to()); } template -class ArrayCopier1D { +class ArrayCopier1D : public Visitor { public: ArrayCopier1D(T* destination, size_t capacity) - : _destination(destination), _capacity(capacity), _size(0) {} - void visitArray(const CollectionData& array) { + : _destination(destination), _capacity(capacity) {} + 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) {} void visitArray(const CollectionData& array) { @@ -3948,8 +4034,7 @@ 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); } template inline void copyArray(const TSource& src, T (&dst)[N1][N2]) { @@ -4234,18 +4319,34 @@ inline VariantRef variantAs(VariantData* data, MemoryPool* pool) { return VariantRef(pool, data); } 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 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 struct Comparer; @@ -4254,18 +4355,20 @@ struct Comparer::value>::type> : ComparerBase { T rhs; 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; } }; template @@ -4274,22 +4377,22 @@ struct Comparer::value || : ComparerBase { T rhs; 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(lhs)); + CompareResult visitBoolean(bool lhs) { + return visitPositiveInteger(static_cast(lhs)); } }; struct NullComparer : ComparerBase { - void visitNull() { - result = COMPARE_RESULT_EQUAL; + CompareResult visitNull() { + return COMPARE_RESULT_EQUAL; } }; #if ARDUINOJSON_HAS_NULLPTR @@ -4301,33 +4404,37 @@ struct Comparer : NullComparer { struct ArrayComparer : ComparerBase { const CollectionData *_rhs; 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; } }; struct NegativeIntegerComparer : ComparerBase { UInt _rhs; 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; } }; struct ObjectComparer : ComparerBase { const CollectionData *_rhs; 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; } }; struct RawComparer : ComparerBase { @@ -4335,15 +4442,15 @@ struct RawComparer : ComparerBase { size_t _rhsSize; 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; } }; template @@ -4351,64 +4458,60 @@ struct Comparer::value>::type> : ComparerBase { T rhs; 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 comparer(lhs); - accept(comparer); + return accept(comparer); } - void visitString(const char *lhs) { + CompareResult visitString(const char *lhs) { Comparer 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 comparer(lhs); - accept(comparer); + return accept(comparer); } - void visitBoolean(bool lhs) { + CompareResult visitBoolean(bool lhs) { Comparer comparer(lhs); - accept(comparer); + return accept(comparer); } - void visitNull() { + CompareResult visitNull() { NullComparer comparer; - accept(comparer); + return accept(comparer); } private: template - 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; } } }; template CompareResult compare(const T1 &lhs, const T2 &rhs) { Comparer comparer(rhs); - lhs.accept(comparer); - return comparer.result; + return lhs.accept(comparer); } inline int variantCompare(const VariantData *a, const VariantData *b) { return compare(VariantConstRef(a), VariantConstRef(b)); @@ -4419,48 +4522,12 @@ inline bool isdigit(char c) { inline bool issign(char c) { return '-' == c || c == '+'; } -template -struct ParsedNumber { - ParsedNumber() : _type(VALUE_IS_NULL) {} - void setInteger(TUInt value, bool is_negative) { - uintValue = value; - _type = uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER - : VALUE_IS_POSITIVE_INTEGER); - } - void setFloat(TFloat value) { - floatValue = value; - _type = VALUE_IS_FLOAT; - } - template - T as() const { - switch (_type) { - case VALUE_IS_NEGATIVE_INTEGER: - return convertNegativeInteger(uintValue); - case VALUE_IS_POSITIVE_INTEGER: - return convertPositiveInteger(uintValue); - case VALUE_IS_FLOAT: - return convertFloat(floatValue); - default: - return 0; - } - } - uint8_t type() const { - return _type; - } - union { - TUInt uintValue; - TFloat floatValue; - }; - uint8_t _type; -}; // namespace ARDUINOJSON_NAMESPACE template struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {}; -template -inline void parseNumber(const char* s, ParsedNumber& result) { - typedef FloatTraits traits; - typedef typename choose_largest::type - mantissa_t; - typedef typename traits::exponent_type exponent_t; +inline bool parseNumber(const char* s, VariantData& result) { + typedef FloatTraits traits; + typedef choose_largest::type mantissa_t; + typedef traits::exponent_type exponent_t; ARDUINOJSON_ASSERT(s != 0); bool is_negative = false; switch (*s) { @@ -4475,20 +4542,20 @@ inline void parseNumber(const char* s, ParsedNumber& result) { #if ARDUINOJSON_ENABLE_NAN if (*s == 'n' || *s == 'N') { result.setFloat(traits::nan()); - return; + return true; } #endif #if ARDUINOJSON_ENABLE_INFINITY if (*s == 'i' || *s == 'I') { result.setFloat(is_negative ? -traits::inf() : traits::inf()); - return; + return true; } #endif if (!isdigit(*s) && *s != '.') - return; + return false; mantissa_t mantissa = 0; exponent_t exponent_offset = 0; - const mantissa_t maxUint = TUInt(-1); + const mantissa_t maxUint = UInt(-1); while (isdigit(*s)) { uint8_t digit = uint8_t(*s - '0'); if (mantissa > maxUint / 10) @@ -4500,8 +4567,11 @@ inline void parseNumber(const char* s, ParsedNumber& result) { s++; } if (*s == '\0') { - result.setInteger(TUInt(mantissa), is_negative); - return; + if (is_negative) + result.setNegativeInteger(UInt(mantissa)); + else + result.setPositiveInteger(UInt(mantissa)); + return true; } while (mantissa > traits::mantissa_max) { mantissa /= 10; @@ -4538,7 +4608,7 @@ inline void parseNumber(const char* s, ParsedNumber& result) { result.setFloat(is_negative ? -0.0f : 0.0f); else result.setFloat(is_negative ? -traits::inf() : traits::inf()); - return; + return true; } s++; } @@ -4547,25 +4617,18 @@ inline void parseNumber(const char* s, ParsedNumber& result) { } exponent += exponent_offset; if (*s != '\0') - return; - TFloat final_result = - traits::make_float(static_cast(mantissa), exponent); + return false; + Float final_result = + traits::make_float(static_cast(mantissa), exponent); result.setFloat(is_negative ? -final_result : final_result); + return true; } template -inline T parseFloat(const char* s) { - typedef typename choose_largest::type TFloat; - ParsedNumber value; +inline T parseNumber(const char* s) { + VariantData value; + value.init(); // VariantData is a POD, so it has no constructor parseNumber(s, value); - return value.template as(); -} -template -T parseInteger(const char *s) { - typedef typename choose_largest::type>::type - TUInt; - ParsedNumber value; - parseNumber(s, value); - return value.template as(); + return variantAs(&value); } template inline T VariantData::asIntegral() const { @@ -4577,7 +4640,7 @@ inline T VariantData::asIntegral() const { return convertNegativeInteger(_content.asInteger); case VALUE_IS_LINKED_STRING: case VALUE_IS_OWNED_STRING: - return parseInteger(_content.asString); + return parseNumber(_content.asString); case VALUE_IS_FLOAT: return convertFloat(_content.asFloat); default: @@ -4608,7 +4671,7 @@ inline T VariantData::asFloat() const { return -static_cast(_content.asInteger); case VALUE_IS_LINKED_STRING: case VALUE_IS_OWNED_STRING: - return parseFloat(_content.asString); + return parseNumber(_content.asString); case VALUE_IS_FLOAT: return static_cast(_content.asFloat); default: @@ -4675,6 +4738,10 @@ template inline VariantRef VariantRef::getOrAddMember(const TString &key) const { return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool)); } +inline VariantConstRef operator|(VariantConstRef preferedValue, + VariantConstRef defaultValue) { + return preferedValue ? preferedValue : defaultValue; +} } // namespace ARDUINOJSON_NAMESPACE #if ARDUINOJSON_ENABLE_STD_STREAM #include @@ -4686,6 +4753,7 @@ class DeserializationError { public: enum Code { Ok, + EmptyInput, IncompleteInput, InvalidInput, NoMemory, @@ -4733,23 +4801,29 @@ class DeserializationError { return _code; } const char* c_str() const { - switch (_code) { - case Ok: - return "Ok"; - case TooDeep: - return "TooDeep"; - case NoMemory: - return "NoMemory"; - case InvalidInput: - return "InvalidInput"; - case IncompleteInput: - return "IncompleteInput"; - case NotSupported: - return "NotSupported"; - default: - return "???"; - } + static const char* messages[] = { + "Ok", "EmptyInput", "IncompleteInput", "InvalidInput", + "NoMemory", "NotSupported", "TooDeep"}; + ARDUINOJSON_ASSERT(static_cast(_code) < + sizeof(messages) / sizeof(messages[0])); + return messages[_code]; } +#if ARDUINOJSON_ENABLE_PROGMEM + const __FlashStringHelper* f_str() const { + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s0, "Ok"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s1, "EmptyInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s2, "IncompleteInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s3, "InvalidInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s4, "NoMemory"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s5, "NotSupported"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s6, "TooDeep"); + ARDUINOJSON_DEFINE_STATIC_ARRAY( + const char*, messages, + ARDUINOJSON_EXPAND7({s0, s1, s2, s3, s4, s5, s6})); + return ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages, + _code); + } +#endif private: Code _code; }; @@ -4784,7 +4858,7 @@ class Filter { if (_variant == true) // "true" means "allow recursively" return *this; else - return Filter(_variant[key]); + return Filter(_variant[key] | _variant["*"]); } private: VariantConstRef _variant; @@ -4919,7 +4993,6 @@ struct Reader : Reader { }; } // namespace ARDUINOJSON_NAMESPACE #if ARDUINOJSON_ENABLE_ARDUINO_STREAM -#include namespace ARDUINOJSON_NAMESPACE { template struct ReadergetFreeZone(&_ptr, &_capacity); + StringCopier(MemoryPool& pool) : _pool(&pool) {} + void startString() { + _pool->getFreeZone(&_ptr, &_capacity); _size = 0; } - const char* save(MemoryPool* pool) { + const char* save() { ARDUINOJSON_ASSERT(_ptr); - return pool->saveStringFromFreeZone(_size); + return _pool->saveStringFromFreeZone(_size); } void append(const char* s) { while (*s) append(*s++); @@ -5032,6 +5106,7 @@ class StringCopier { return; if (_size >= _capacity) { _ptr = 0; + _pool->markAsOverflowed(); return; } _ptr[_size++] = c; @@ -5044,6 +5119,7 @@ class StringCopier { } typedef storage_policies::store_by_copy storage_policy; private: + MemoryPool* _pool; char* _ptr; size_t _size; size_t _capacity; @@ -5051,10 +5127,10 @@ class StringCopier { class StringMover { public: StringMover(char* ptr) : _writePtr(ptr) {} - void startString(MemoryPool*) { + void startString() { _startPtr = _writePtr; } - const char* save(MemoryPool*) const { + const char* save() const { return _startPtr; } void append(char c) { @@ -5071,28 +5147,15 @@ class StringMover { char* _writePtr; char* _startPtr; }; -template -struct StringStorage { - typedef StringCopier type; - static type create(TInput&) { - return type(); - } -}; -template -struct StringStorage::value>::type> { - typedef StringMover type; - static type create(TChar* input) { - return type(reinterpret_cast(input)); - } -}; template -typename StringStorage::type makeStringStorage(TInput& input) { - return StringStorage::create(input); +StringCopier makeStringStorage(TInput&, MemoryPool& pool) { + return StringCopier(pool); } template -typename StringStorage::type makeStringStorage(TChar* input) { - return StringStorage::create(input); +StringMover makeStringStorage( + TChar* input, MemoryPool&, + typename enable_if::value>::type* = 0) { + return StringMover(reinterpret_cast(input)); } template