From 3a6bbf57ae59d3dccdfded1cf8343cc3efa18ab4 Mon Sep 17 00:00:00 2001 From: proddy Date: Fri, 28 Jun 2024 09:04:30 +0200 Subject: [PATCH] bump ArduinoJson to 7.1.0 --- lib_standalone/ArduinoJson.h | 1380 +++++++++++++++++++++------------- platformio.ini | 2 +- 2 files changed, 858 insertions(+), 524 deletions(-) diff --git a/lib_standalone/ArduinoJson.h b/lib_standalone/ArduinoJson.h index 8d7bd7a11..91dd096f4 100644 --- a/lib_standalone/ArduinoJson.h +++ b/lib_standalone/ArduinoJson.h @@ -77,11 +77,11 @@ #endif #ifndef ARDUINOJSON_SLOT_ID_SIZE #if ARDUINOJSON_SIZEOF_POINTER <= 2 -#define ARDUINOJSON_SLOT_ID_SIZE 1 // up to 255 slots +#define ARDUINOJSON_SLOT_ID_SIZE 1 #elif ARDUINOJSON_SIZEOF_POINTER == 4 -#define ARDUINOJSON_SLOT_ID_SIZE 2 // up to 65535 slots +#define ARDUINOJSON_SLOT_ID_SIZE 2 #else -#define ARDUINOJSON_SLOT_ID_SIZE 4 // up to 4294967295 slots +#define ARDUINOJSON_SLOT_ID_SIZE 4 #endif #endif #ifndef ARDUINOJSON_POOL_CAPACITY @@ -203,7 +203,9 @@ #endif #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_CONCAT3(A, B, C) ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), C) +#define ARDUINOJSON_CONCAT4(A, B, C, D) ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT3(A, B, C), D) +#define ARDUINOJSON_CONCAT5(A, B, C, D, E) ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT4(A, B, C, D), E) #define ARDUINOJSON_BIN2ALPHA_0000() A #define ARDUINOJSON_BIN2ALPHA_0001() B #define ARDUINOJSON_BIN2ALPHA_0010() C @@ -222,17 +224,18 @@ #define ARDUINOJSON_BIN2ALPHA_1111() P #define ARDUINOJSON_BIN2ALPHA_(A, B, C, D) ARDUINOJSON_BIN2ALPHA_##A##B##C##D() #define ARDUINOJSON_BIN2ALPHA(A, B, C, D) ARDUINOJSON_BIN2ALPHA_(A, B, C, D) -#define ARDUINOJSON_VERSION "7.0.4" +#define ARDUINOJSON_VERSION "7.1.0" #define ARDUINOJSON_VERSION_MAJOR 7 -#define ARDUINOJSON_VERSION_MINOR 0 -#define ARDUINOJSON_VERSION_REVISION 4 -#define ARDUINOJSON_VERSION_MACRO V704 +#define ARDUINOJSON_VERSION_MINOR 1 +#define ARDUINOJSON_VERSION_REVISION 0 +#define ARDUINOJSON_VERSION_MACRO V710 #ifndef ARDUINOJSON_VERSION_NAMESPACE #define ARDUINOJSON_VERSION_NAMESPACE \ - ARDUINOJSON_CONCAT4(ARDUINOJSON_VERSION_MACRO, \ + ARDUINOJSON_CONCAT5(ARDUINOJSON_VERSION_MACRO, \ ARDUINOJSON_BIN2ALPHA(ARDUINOJSON_ENABLE_PROGMEM, ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, 1), \ ARDUINOJSON_BIN2ALPHA(ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE), \ - ARDUINOJSON_SLOT_ID_SIZE) + ARDUINOJSON_SLOT_ID_SIZE, \ + ARDUINOJSON_STRING_LENGTH_SIZE) #endif #define ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE \ namespace ArduinoJson { \ @@ -255,8 +258,6 @@ ARDUINOJSON_END_PUBLIC_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template class InvalidConversion; // Error here? See https://arduinojson.org/v7/invalid-conversion/ -template -struct ConverterNeedsWriteableRef; ARDUINOJSON_END_PRIVATE_NAMESPACE #include #include @@ -302,19 +303,21 @@ ARDUINOJSON_END_PUBLIC_NAMESPACE #endif ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template -struct uint_t; +struct uint_; template <> -struct uint_t<8> { +struct uint_<8> { typedef uint8_t type; }; template <> -struct uint_t<16> { +struct uint_<16> { typedef uint16_t type; }; template <> -struct uint_t<32> { +struct uint_<32> { typedef uint32_t type; }; +template +using uint_t = typename uint_::type; template struct conditional { typedef TrueType type; @@ -323,12 +326,29 @@ template struct conditional { typedef FalseType type; }; +template +using conditional_t = typename conditional::type; template struct enable_if {}; template struct enable_if { typedef T type; }; +template +using enable_if_t = typename enable_if::type; +template +struct function_traits; +template +struct function_traits { + using return_type = ReturnType; + using arg1_type = Arg1; +}; +template +struct function_traits { + using return_type = ReturnType; + using arg1_type = Arg1; + using arg2_type = Arg2; +}; template struct integral_constant { static const T value = v; @@ -349,6 +369,8 @@ template struct remove_reference { typedef T type; }; +template +using remove_reference_t = typename remove_reference::type; template class is_base_of { protected: // <- to avoid GCC's "all member functions in class are private" @@ -356,7 +378,7 @@ class is_base_of { static char probe(...); public: - static const bool value = sizeof(probe(reinterpret_cast::type *>(0))) == sizeof(int); + static const bool value = sizeof(probe(reinterpret_cast *>(0))) == sizeof(int); }; template T && declval(); @@ -422,21 +444,22 @@ template struct remove_cv { typedef T type; }; +template +using remove_cv_t = typename remove_cv::type; template struct is_floating_point : integral_constant::type>::value || is_same::type>::value> {}; + is_same>::value || is_same>::value> {}; template struct is_integral - : integral_constant::type, signed char>::value || is_same::type, unsigned char>::value - || is_same::type, signed short>::value || is_same::type, unsigned short>::value - || is_same::type, signed int>::value || is_same::type, unsigned int>::value - || is_same::type, signed long>::value || is_same::type, unsigned long>::value - || is_same::type, signed long long>::value || is_same::type, unsigned long long>::value - || is_same::type, char>::value || is_same::type, bool>::value> {}; + : integral_constant< + bool, + is_same, signed char>::value || is_same, unsigned char>::value || is_same, signed short>::value + || is_same, unsigned short>::value || is_same, signed int>::value || is_same, unsigned int>::value + || is_same, signed long>::value || is_same, unsigned long>::value || is_same, signed long long>::value + || is_same, unsigned long long>::value || is_same, char>::value || is_same, bool>::value> {}; template struct is_enum { - static const bool value = is_convertible::value && !is_class::value && !is_integral::value && !is_floating_point::value; + static const bool value = is_convertible::value && !is_class::value && !is_integral::value && !is_floating_point::value; }; template struct is_pointer : false_type {}; @@ -445,16 +468,15 @@ struct is_pointer : true_type {}; template struct is_signed : integral_constant::type, char>::value || is_same::type, signed char>::value - || is_same::type, signed short>::value || is_same::type, signed int>::value - || is_same::type, signed long>::value || is_same::type, signed long long>::value - || is_same::type, float>::value || is_same::type, double>::value> {}; + is_same, char>::value || is_same, signed char>::value || is_same, signed short>::value + || is_same, signed int>::value || is_same, signed long>::value + || is_same, signed long long>::value || is_same, float>::value || is_same, double>::value> { +}; template -struct is_unsigned - : integral_constant::type, unsigned char>::value || is_same::type, unsigned short>::value - || is_same::type, unsigned int>::value || is_same::type, unsigned long>::value - || is_same::type, unsigned long long>::value || is_same::type, bool>::value> {}; +struct is_unsigned : integral_constant, unsigned char>::value || is_same, unsigned short>::value + || is_same, unsigned int>::value || is_same, unsigned long>::value + || is_same, unsigned long long>::value || is_same, bool>::value> {}; template struct type_identity { typedef T type; @@ -483,10 +505,8 @@ template <> struct make_unsigned : type_identity {}; template <> struct make_unsigned : type_identity {}; -template -struct make_void { - typedef void type; -}; +template +using make_unsigned_t = typename make_unsigned::type; template struct remove_const { typedef T type; @@ -495,6 +515,14 @@ template struct remove_const { typedef T type; }; +template +using remove_const_t = typename remove_const::type; +template +struct make_void { + using type = void; +}; +template +using void_t = typename make_void::type; ARDUINOJSON_END_PRIVATE_NAMESPACE #ifdef _MSC_VER #pragma warning(push) @@ -504,7 +532,7 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template struct numeric_limits; template -struct numeric_limits::value>::type> { +struct numeric_limits::value>> { static constexpr T lowest() { return 0; } @@ -513,7 +541,7 @@ struct numeric_limits::value>::type> { } }; template -struct numeric_limits::value && is_signed::value>::type> { +struct numeric_limits::value && is_signed::value>> { static constexpr T lowest() { return T(T(1) << (sizeof(T) * 8 - 1)); } @@ -527,8 +555,8 @@ ARDUINOJSON_END_PRIVATE_NAMESPACE #endif ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE struct StringNode { - using references_type = uint_t::type; - using length_type = uint_t::type; + using references_type = uint_t; + using length_type = uint_t; struct StringNode * next; references_type references; length_type length; @@ -540,7 +568,10 @@ struct StringNode { static StringNode * create(size_t length, Allocator * allocator) { if (length > maxLength) return nullptr; - auto node = reinterpret_cast(allocator->allocate(sizeForLength(length))); + auto size = sizeForLength(length); + if (size < length) // integer overflow + return nullptr; // (not testable on 64-bit) + auto node = reinterpret_cast(allocator->allocate(size)); if (node) { node->length = length_type(length); node->references = 1; @@ -569,12 +600,12 @@ constexpr size_t sizeofString(size_t n) { } using nullptr_t = decltype(nullptr); template -T && forward(typename remove_reference::type & t) noexcept { +T && forward(remove_reference_t & t) noexcept { return static_cast(t); } template -typename remove_reference::type && move(T && t) { - return static_cast::type &&>(t); +remove_reference_t && move(T && t) { + return static_cast &&>(t); } template void swap_(T & a, T & b) { @@ -668,14 +699,14 @@ class ZeroTerminatedRamString { const char * str_; }; template -struct StringAdapter::value>::type> { +struct StringAdapter::value>> { typedef ZeroTerminatedRamString AdaptedString; static AdaptedString adapt(const TChar * p) { return AdaptedString(reinterpret_cast(p)); } }; template -struct StringAdapter::value>::type> { +struct StringAdapter::value>> { typedef ZeroTerminatedRamString AdaptedString; static AdaptedString adapt(const TChar * p) { return AdaptedString(reinterpret_cast(p)); @@ -727,7 +758,7 @@ class SizedRamString { size_t size_; }; template -struct SizedStringAdapter::value>::type> { +struct SizedStringAdapter::value>> { typedef SizedRamString AdaptedString; static AdaptedString adapt(const TChar * p, size_t n) { return AdaptedString(reinterpret_cast(p), n); @@ -822,19 +853,19 @@ namespace string_traits_impl { template struct has_cstr : false_type {}; template -struct has_cstr().c_str()), const char *>::value>::type> : true_type {}; +struct has_cstr().c_str()), const char *>::value>> : true_type {}; template struct has_data : false_type {}; template -struct has_data().data()), const char *>::value>::type> : true_type {}; +struct has_data().data()), const char *>::value>> : true_type {}; template struct has_length : false_type {}; template -struct has_length().length()), size_t>::value>::type> : true_type {}; +struct has_length().length())>::value>> : true_type {}; template struct has_size : false_type {}; template -struct has_size().size()), size_t>::value>::type> : true_type {}; +struct has_size().size()), size_t>::value>> : true_type {}; } // namespace string_traits_impl template struct string_traits { @@ -846,7 +877,7 @@ struct string_traits { }; }; template -struct StringAdapter::has_cstr || string_traits::has_data) && (string_traits::has_length || string_traits::has_size)>::type> { +struct StringAdapter::has_cstr || string_traits::has_data) && (string_traits::has_length || string_traits::has_size)>> { typedef SizedRamString AdaptedString; static AdaptedString adapt(const T & s) { return AdaptedString(get_data(s), get_size(s)); @@ -854,19 +885,19 @@ struct StringAdapter::has_cstr || string private: template - static typename enable_if::has_size, size_t>::type get_size(const U & s) { + static enable_if_t::has_size, size_t> get_size(const U & s) { return s.size(); } template - static typename enable_if::has_size, size_t>::type get_size(const U & s) { + static enable_if_t::has_size, size_t> get_size(const U & s) { return s.length(); } template - static typename enable_if::has_data, const char *>::type get_data(const U & s) { + static enable_if_t::has_data, const char *> get_data(const U & s) { return s.data(); } template - static typename enable_if::has_data, const char *>::type get_data(const U & s) { + static enable_if_t::has_data, const char *> get_data(const U & s) { return s.c_str(); } }; @@ -1066,7 +1097,7 @@ ARDUINOJSON_END_PRIVATE_NAMESPACE #endif ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template -typename enable_if::type stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) { +enable_if_t stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) { ARDUINOJSON_ASSERT(!s1.isNull()); ARDUINOJSON_ASSERT(!s2.isNull()); size_t size1 = s1.size(); @@ -1083,11 +1114,11 @@ typename enable_if -typename enable_if<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), int>::type stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) { +enable_if_t<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), int> stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) { return -stringCompare(s2, s1); } template -typename enable_if::type stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) { +enable_if_t stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) { ARDUINOJSON_ASSERT(!s1.isNull()); ARDUINOJSON_ASSERT(!s2.isNull()); size_t size1 = s1.size(); @@ -1101,7 +1132,7 @@ typename enable_if -typename enable_if<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), bool>::type stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) { +enable_if_t<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), bool> stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) { return stringEquals(s2, s1); } template @@ -1188,7 +1219,7 @@ class StringPool { StringNode * strings_ = nullptr; }; class VariantSlot; -using SlotId = uint_t::type; +using SlotId = uint_t; using SlotCount = SlotId; const SlotId NULL_SLOT = SlotId(-1); class SlotWithId { @@ -1412,9 +1443,7 @@ class ResourceManager { overflowed_ = true; return p; } - void freeSlot(SlotWithId id) { - variantPools_.freeSlot(id); - } + void freeSlot(SlotWithId slot); VariantSlot * getSlot(SlotId id) const { return variantPools_.getSlot(id); } @@ -1470,7 +1499,7 @@ class ResourceManager { template struct IsString : false_type {}; template -struct IsString::AdaptedString>::type> : true_type {}; +struct IsString::AdaptedString>> : true_type {}; ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE template @@ -1656,11 +1685,11 @@ struct FloatTraits { return forge(0x7FEFFFFFFFFFFFFF); } template // int64_t - static T highest_for(typename enable_if::value && is_signed::value && sizeof(TOut) == 8, signed>::type * = 0) { + static T highest_for(enable_if_t::value && is_signed::value && sizeof(TOut) == 8, signed> * = 0) { return forge(0x43DFFFFFFFFFFFFF); // 9.2233720368547748e+18 } template // uint64_t - static T highest_for(typename enable_if::value && is_unsigned::value && sizeof(TOut) == 8, unsigned>::type * = 0) { + static T highest_for(enable_if_t::value && is_unsigned::value && sizeof(TOut) == 8, unsigned> * = 0) { return forge(0x43EFFFFFFFFFFFFF); // 1.8446744073709549568e+19 } static T lowest() { @@ -1716,19 +1745,19 @@ struct FloatTraits { return forge(0x7f7fffff); } template // int32_t - static T highest_for(typename enable_if::value && is_signed::value && sizeof(TOut) == 4, signed>::type * = 0) { + static T highest_for(enable_if_t::value && is_signed::value && sizeof(TOut) == 4, signed> * = 0) { return forge(0x4EFFFFFF); // 2.14748352E9 } template // uint32_t - static T highest_for(typename enable_if::value && is_unsigned::value && sizeof(TOut) == 4, unsigned>::type * = 0) { + static T highest_for(enable_if_t::value && is_unsigned::value && sizeof(TOut) == 4, unsigned> * = 0) { return forge(0x4F7FFFFF); // 4.29496704E9 } template // int64_t - static T highest_for(typename enable_if::value && is_signed::value && sizeof(TOut) == 8, signed>::type * = 0) { + static T highest_for(enable_if_t::value && is_signed::value && sizeof(TOut) == 8, signed> * = 0) { return forge(0x5EFFFFFF); // 9.22337148709896192E18 } template // uint64_t - static T highest_for(typename enable_if::value && is_unsigned::value && sizeof(TOut) == 8, unsigned>::type * = 0) { + static T highest_for(enable_if_t::value && is_unsigned::value && sizeof(TOut) == 8, unsigned> * = 0) { return forge(0x5F7FFFFF); // 1.844674297419792384E19 } static T lowest() { @@ -1758,48 +1787,47 @@ typedef float JsonFloat; ARDUINOJSON_END_PUBLIC_NAMESPACE ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template -typename enable_if::value && is_unsigned::value && is_integral::value && sizeof(TOut) <= sizeof(TIn), bool>::type -canConvertNumber(TIn value) { +enable_if_t::value && is_unsigned::value && is_integral::value && sizeof(TOut) <= sizeof(TIn), bool> canConvertNumber(TIn value) { return value <= TIn(numeric_limits::highest()); } template -typename enable_if::value && is_unsigned::value && is_integral::value && sizeof(TIn) < sizeof(TOut), bool>::type canConvertNumber(TIn) { +enable_if_t::value && is_unsigned::value && is_integral::value && sizeof(TIn) < sizeof(TOut), bool> canConvertNumber(TIn) { return true; } template -typename enable_if::value && is_floating_point::value, bool>::type canConvertNumber(TIn) { +enable_if_t::value && is_floating_point::value, bool> canConvertNumber(TIn) { return true; } template -typename enable_if::value && is_signed::value && is_integral::value && is_signed::value && sizeof(TOut) < sizeof(TIn), bool>::type +enable_if_t::value && is_signed::value && is_integral::value && is_signed::value && sizeof(TOut) < sizeof(TIn), bool> canConvertNumber(TIn value) { return value >= TIn(numeric_limits::lowest()) && value <= TIn(numeric_limits::highest()); } template -typename enable_if::value && is_signed::value && is_integral::value && is_signed::value && sizeof(TIn) <= sizeof(TOut), bool>::type +enable_if_t::value && is_signed::value && is_integral::value && is_signed::value && sizeof(TIn) <= sizeof(TOut), bool> canConvertNumber(TIn) { return true; } template -typename enable_if::value && is_signed::value && is_integral::value && is_unsigned::value && sizeof(TOut) >= sizeof(TIn), bool>::type +enable_if_t::value && is_signed::value && is_integral::value && is_unsigned::value && sizeof(TOut) >= sizeof(TIn), bool> canConvertNumber(TIn value) { if (value < 0) return false; return TOut(value) <= numeric_limits::highest(); } template -typename enable_if::value && is_signed::value && is_integral::value && is_unsigned::value && sizeof(TOut) < sizeof(TIn), bool>::type +enable_if_t::value && is_signed::value && is_integral::value && is_unsigned::value && sizeof(TOut) < sizeof(TIn), bool> canConvertNumber(TIn value) { if (value < 0) return false; return value <= TIn(numeric_limits::highest()); } template -typename enable_if::value && is_integral::value && sizeof(TOut) < sizeof(TIn), bool>::type canConvertNumber(TIn value) { +enable_if_t::value && is_integral::value && sizeof(TOut) < sizeof(TIn), bool> canConvertNumber(TIn value) { return value >= numeric_limits::lowest() && value <= numeric_limits::highest(); } template -typename enable_if::value && is_integral::value && sizeof(TOut) >= sizeof(TIn), bool>::type canConvertNumber(TIn value) { +enable_if_t::value && is_integral::value && sizeof(TOut) >= sizeof(TIn), bool> canConvertNumber(TIn value) { return value >= numeric_limits::lowest() && value <= FloatTraits::template highest_for(); } template @@ -1891,13 +1919,13 @@ class CollectionData { SlotId head() const { return head_; } + void addSlot(SlotWithId slot, ResourceManager * resources); protected: iterator addSlot(ResourceManager *); private: SlotWithId getPreviousSlot(VariantSlot *, const ResourceManager *) const; - void releaseSlot(SlotWithId, ResourceManager *); }; inline const VariantData * collectionToVariant(const CollectionData * collection) { const void * data = collection; // prevent warning cast-align @@ -1917,6 +1945,14 @@ class ArrayData : public CollectionData { return nullptr; return array->addElement(resources); } + template + bool addValue(T && value, ResourceManager * resources); + template + static bool addValue(ArrayData * array, T && value, ResourceManager * resources) { + if (!array) + return false; + return array->addValue(value, resources); + } VariantData * getOrAddElement(size_t index, ResourceManager * resources); VariantData * getElement(size_t index, const ResourceManager * resources) const; static VariantData * getElement(const ArrayData * array, size_t index, const ResourceManager * resources) { @@ -2144,6 +2180,17 @@ class VariantData { return nullptr; return var->addElement(resources); } + template + bool addValue(T && value, ResourceManager * resources) { + auto array = isNull() ? &toArray() : asArray(); + return detail::ArrayData::addValue(array, detail::forward(value), resources); + } + template + static bool addValue(VariantData * var, T && value, ResourceManager * resources) { + if (!var) + return false; + return var->addValue(value, resources); + } bool asBoolean() const { switch (type()) { case VALUE_IS_BOOLEAN: @@ -2352,12 +2399,12 @@ class VariantData { setFloat(value); } template - typename enable_if::value>::type setInteger(T value) { + enable_if_t::value> setInteger(T value) { setType(VALUE_IS_SIGNED_INTEGER); content_.asSignedInteger = value; } template - typename enable_if::value>::type setInteger(T value) { + enable_if_t::value> setInteger(T value) { setType(VALUE_IS_UNSIGNED_INTEGER); content_.asUnsignedInteger = static_cast(value); } @@ -2532,27 +2579,25 @@ CompareResult arithmeticCompare(const T & lhs, const T & rhs) { return COMPARE_RESULT_EQUAL; } template -CompareResult -arithmeticCompare(const T1 & lhs, const T2 & rhs, typename enable_if::value && is_integral::value && sizeof(T1) < sizeof(T2)>::type * = 0) { +CompareResult arithmeticCompare(const T1 & lhs, const T2 & rhs, enable_if_t::value && is_integral::value && sizeof(T1) < sizeof(T2)> * = 0) { return arithmeticCompare(static_cast(lhs), rhs); } template +CompareResult arithmeticCompare(const T1 & lhs, const T2 & rhs, enable_if_t::value && is_integral::value && sizeof(T2) < sizeof(T1)> * = 0) { + return arithmeticCompare(lhs, static_cast(rhs)); +} +template CompareResult -arithmeticCompare(const T1 & lhs, const T2 & rhs, typename enable_if::value && is_integral::value && sizeof(T2) < sizeof(T1)>::type * = 0) { +arithmeticCompare(const T1 & lhs, + const T2 & rhs, + enable_if_t::value && is_integral::value && is_signed::value == is_signed::value && sizeof(T2) == sizeof(T1)> * = 0) { return arithmeticCompare(lhs, static_cast(rhs)); } template CompareResult arithmeticCompare( const T1 & lhs, const T2 & rhs, - typename enable_if::value && is_integral::value && is_signed::value == is_signed::value && sizeof(T2) == sizeof(T1)>::type * = 0) { - return arithmeticCompare(lhs, static_cast(rhs)); -} -template -CompareResult arithmeticCompare( - const T1 & lhs, - const T2 & rhs, - typename enable_if::value && is_integral::value && is_unsigned::value && is_signed::value && sizeof(T2) == sizeof(T1)>::type * = 0) { + enable_if_t::value && is_integral::value && is_unsigned::value && is_signed::value && sizeof(T2) == sizeof(T1)> * = 0) { if (rhs < 0) return COMPARE_RESULT_GREATER; return arithmeticCompare(lhs, static_cast(rhs)); @@ -2561,31 +2606,31 @@ template CompareResult arithmeticCompare( const T1 & lhs, const T2 & rhs, - typename enable_if::value && is_integral::value && is_signed::value && is_unsigned::value && sizeof(T2) == sizeof(T1)>::type * = 0) { + enable_if_t::value && is_integral::value && is_signed::value && is_unsigned::value && sizeof(T2) == sizeof(T1)> * = 0) { if (lhs < 0) return COMPARE_RESULT_LESS; return arithmeticCompare(static_cast(lhs), rhs); } template -CompareResult arithmeticCompare(const T1 & lhs, const T2 & rhs, typename enable_if::value || is_floating_point::value>::type * = 0) { +CompareResult arithmeticCompare(const T1 & lhs, const T2 & rhs, enable_if_t::value || is_floating_point::value> * = 0) { return arithmeticCompare(static_cast(lhs), static_cast(rhs)); } template -CompareResult arithmeticCompareNegateLeft(JsonUInt, const T2 &, typename enable_if::value>::type * = 0) { +CompareResult arithmeticCompareNegateLeft(JsonUInt, const T2 &, enable_if_t::value> * = 0) { return COMPARE_RESULT_LESS; } template -CompareResult arithmeticCompareNegateLeft(JsonUInt lhs, const T2 & rhs, typename enable_if::value>::type * = 0) { +CompareResult arithmeticCompareNegateLeft(JsonUInt lhs, const T2 & rhs, enable_if_t::value> * = 0) { if (rhs > 0) return COMPARE_RESULT_LESS; return arithmeticCompare(-rhs, static_cast(lhs)); } template -CompareResult arithmeticCompareNegateRight(const T1 &, JsonUInt, typename enable_if::value>::type * = 0) { +CompareResult arithmeticCompareNegateRight(const T1 &, JsonUInt, enable_if_t::value> * = 0) { return COMPARE_RESULT_GREATER; } template -CompareResult arithmeticCompareNegateRight(const T1 & lhs, JsonUInt rhs, typename enable_if::value>::type * = 0) { +CompareResult arithmeticCompareNegateRight(const T1 & lhs, JsonUInt rhs, enable_if_t::value> * = 0) { if (lhs > 0) return COMPARE_RESULT_GREATER; return arithmeticCompare(static_cast(rhs), -lhs); @@ -2605,7 +2650,7 @@ struct VariantOperatorTag {}; template struct VariantOperators : VariantOperatorTag { template - friend typename enable_if::value && !is_array::value, T>::type operator|(const TVariant & variant, const T & defaultValue) { + friend enable_if_t::value && !is_array::value, T> operator|(const TVariant & variant, const T & defaultValue) { if (variant.template is()) return variant.template as(); else @@ -2618,7 +2663,7 @@ struct VariantOperators : VariantOperatorTag { return defaultValue; } template - friend typename enable_if::value, JsonVariantConst>::type operator|(const TVariant & variant, T defaultValue) { + friend enable_if_t::value, JsonVariantConst> operator|(const TVariant & variant, T defaultValue) { if (variant) return variant; else @@ -2637,7 +2682,7 @@ struct VariantOperators : VariantOperatorTag { return compare(lhs, rhs) == COMPARE_RESULT_EQUAL; } template - friend typename enable_if::value, bool>::type operator==(TVariant lhs, const T & rhs) { + friend enable_if_t::value, bool> operator==(TVariant lhs, const T & rhs) { return compare(lhs, rhs) == COMPARE_RESULT_EQUAL; } template @@ -2653,7 +2698,7 @@ struct VariantOperators : VariantOperatorTag { return compare(lhs, rhs) != COMPARE_RESULT_EQUAL; } template - friend typename enable_if::value, bool>::type operator!=(TVariant lhs, const T & rhs) { + friend enable_if_t::value, bool> operator!=(TVariant lhs, const T & rhs) { return compare(lhs, rhs) != COMPARE_RESULT_EQUAL; } template @@ -2669,7 +2714,7 @@ struct VariantOperators : VariantOperatorTag { return compare(lhs, rhs) == COMPARE_RESULT_LESS; } template - friend typename enable_if::value, bool>::type operator<(TVariant lhs, const T & rhs) { + friend enable_if_t::value, bool> operator<(TVariant lhs, const T & rhs) { return compare(lhs, rhs) == COMPARE_RESULT_LESS; } template @@ -2685,7 +2730,7 @@ struct VariantOperators : VariantOperatorTag { return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0; } template - friend typename enable_if::value, bool>::type operator<=(TVariant lhs, const T & rhs) { + friend enable_if_t::value, bool> operator<=(TVariant lhs, const T & rhs) { return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0; } template @@ -2701,7 +2746,7 @@ struct VariantOperators : VariantOperatorTag { return compare(lhs, rhs) == COMPARE_RESULT_GREATER; } template - friend typename enable_if::value, bool>::type operator>(TVariant lhs, const T & rhs) { + friend enable_if_t::value, bool> operator>(TVariant lhs, const T & rhs) { return compare(lhs, rhs) == COMPARE_RESULT_GREATER; } template @@ -2717,7 +2762,7 @@ struct VariantOperators : VariantOperatorTag { return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0; } template - friend typename enable_if::value, bool>::type operator>=(TVariant lhs, const T & rhs) { + friend enable_if_t::value, bool> operator>=(TVariant lhs, const T & rhs) { return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0; } }; @@ -2727,6 +2772,8 @@ class JsonArray; class JsonObject; class JsonVariantConst : public detail::VariantTag, public detail::VariantOperators { friend class detail::VariantAttorney; + template + using ConversionSupported = detail::is_same::fromJson)>::arg1_type, JsonVariantConst>; public: JsonVariantConst() @@ -2749,37 +2796,55 @@ class JsonVariantConst : public detail::VariantTag, public detail::VariantOperat size_t size() const { return detail::VariantData::size(data_, resources_); } - template - typename detail::enable_if::value && !detail::is_same::value, T>::type as() const { + template ::value, bool> = true> + T as() const { return Converter::fromJson(*this); } + template ::value, bool> = true> + detail::InvalidConversion as() const; template - typename detail::enable_if::value && !detail::is_same::value, bool>::type is() const { + detail::enable_if_t::value, bool> is() const { return Converter::checkJson(*this); } template + detail::enable_if_t::value, bool> is() const { + return false; + } + template operator T() const { return as(); } - JsonVariantConst operator[](size_t index) const { - return JsonVariantConst(detail::VariantData::getElement(data_, index, resources_), resources_); + template + detail::enable_if_t::value, JsonVariantConst> operator[](T index) const { + return JsonVariantConst(detail::VariantData::getElement(data_, size_t(index), resources_), resources_); } template - typename detail::enable_if::value, JsonVariantConst>::type operator[](const TString & key) const { + detail::enable_if_t::value, JsonVariantConst> operator[](const TString & key) const { return JsonVariantConst(detail::VariantData::getMember(data_, detail::adaptString(key), resources_), resources_); } template - typename detail::enable_if::value, JsonVariantConst>::type operator[](TChar * key) const { + detail::enable_if_t::value, JsonVariantConst> operator[](TChar * key) const { return JsonVariantConst(detail::VariantData::getMember(data_, detail::adaptString(key), resources_), resources_); } + template + detail::enable_if_t::value, JsonVariantConst> operator[](const TVariant & key) const { + if (key.template is()) + return operator[](key.template as()); + else + return operator[](key.template as()); + } template - typename detail::enable_if::value, bool>::type containsKey(const TString & key) const { + detail::enable_if_t::value, bool> containsKey(const TString & key) const { return detail::VariantData::getMember(getData(), detail::adaptString(key), resources_) != 0; } template - typename detail::enable_if::value, bool>::type containsKey(TChar * key) const { + detail::enable_if_t::value, bool> containsKey(TChar * key) const { return detail::VariantData::getMember(getData(), detail::adaptString(key), resources_) != 0; } + template + detail::enable_if_t::value, bool> containsKey(const TVariant & key) const { + return containsKey(key.template as()); + } ARDUINOJSON_DEPRECATED("always returns zero") size_t memoryUsage() const { return 0; @@ -2819,31 +2884,27 @@ class VariantRefBase : public VariantTag { return !getData(); } template - typename enable_if::value, T>::type as() const { - return Converter::fromJson(getVariantConst()); - } - template - typename enable_if::value, T>::type as() const; - template ::value>::type> + T as() const; + template ::value>> operator T() const { return as(); } template - typename enable_if::value, JsonArray>::type to() const; + enable_if_t::value, JsonArray> to() const; template - typename enable_if::value, JsonObject>::type to() const; + enable_if_t::value, JsonObject> to() const; template - typename enable_if::value, JsonVariant>::type to() const; + enable_if_t::value, JsonVariant> to() const; template - FORCE_INLINE typename enable_if::value, bool>::type is() const; + FORCE_INLINE bool is() const; template - FORCE_INLINE typename enable_if::value, bool>::type is() const { - return Converter::checkJson(getVariantConst()); + bool set(const T & value) const { + return doSet>>(value); } template - bool set(const T & value) const; - template - bool set(T * value) const; + bool set(T * value) const { + return doSet>(value); + } size_t size() const { return VariantData::size(getData(), getResourceManager()); } @@ -2851,39 +2912,55 @@ class VariantRefBase : public VariantTag { return VariantData::nesting(getData(), getResourceManager()); } template - typename enable_if::value, T>::type add() const { + enable_if_t::value, T> add() const { return add().template to(); } template - typename enable_if::value, T>::type add() const; + enable_if_t::value, T> add() const; template bool add(const T & value) const { - return add().set(value); + return detail::VariantData::addValue(getOrCreateData(), value, getResourceManager()); } template bool add(T * value) const { - return add().set(value); + return detail::VariantData::addValue(getOrCreateData(), value, getResourceManager()); } void remove(size_t index) const { VariantData::removeElement(getData(), index, getResourceManager()); } template - typename enable_if::value>::type remove(TChar * key) const { + enable_if_t::value> remove(TChar * key) const { VariantData::removeMember(getData(), adaptString(key), getResourceManager()); } template - typename enable_if::value>::type remove(const TString & key) const { + enable_if_t::value> remove(const TString & key) const { VariantData::removeMember(getData(), adaptString(key), getResourceManager()); } + template + enable_if_t::value> remove(const TVariant & key) const { + if (key.template is()) + remove(key.template as()); + else + remove(key.template as()); + } ElementProxy operator[](size_t index) const; template - typename enable_if::value, bool>::type containsKey(const TString & key) const; + enable_if_t::value, bool> containsKey(const TString & key) const; template - typename enable_if::value, bool>::type containsKey(TChar * key) const; + enable_if_t::value, bool> containsKey(TChar * key) const; + template + enable_if_t::value, bool> containsKey(const TVariant & key) const; template - FORCE_INLINE typename enable_if::value, MemberProxy>::type operator[](const TString & key) const; + FORCE_INLINE enable_if_t::value, MemberProxy> operator[](const TString & key) const; template - FORCE_INLINE typename enable_if::value, MemberProxy>::type operator[](TChar * key) const; + FORCE_INLINE enable_if_t::value, MemberProxy> operator[](TChar * key) const; + template + enable_if_t::value, JsonVariantConst> operator[](const TVariant & key) const { + if (key.template is()) + return operator[](key.template as()); + else + return operator[](key.template as()); + } ARDUINOJSON_DEPRECATED("use add() instead") JsonVariant add() const; ARDUINOJSON_DEPRECATED("use add() instead") @@ -2931,6 +3008,22 @@ class VariantRefBase : public VariantTag { FORCE_INLINE ArduinoJson::JsonVariantConst getVariantConst() const { return ArduinoJson::JsonVariantConst(getData(), getResourceManager()); } + template + FORCE_INLINE enable_if_t::value, T> getVariant() const { + return getVariantConst(); + } + template + FORCE_INLINE enable_if_t::value, T> getVariant() const { + return getVariant(); + } + template + bool doSet(T && value) const { + return doSet(detail::forward(value), is_same::return_type, bool>{}); + } + template + bool doSet(T && value, false_type) const; + template + bool doSet(T && value, true_type) const; ArduinoJson::JsonVariant getOrCreateVariant() const; }; template @@ -3016,14 +3109,10 @@ struct Converter : private detail::VariantAttorney { static JsonVariant fromJson(JsonVariant src) { return src; } - static detail::InvalidConversion fromJson(JsonVariantConst); - static bool checkJson(JsonVariant src) { + static bool checkJson(JsonVariant src) { auto data = getData(src); return !!data; } - static bool checkJson(JsonVariantConst) { - return false; - } }; template <> struct Converter : private detail::VariantAttorney { @@ -3132,14 +3221,23 @@ class JsonArrayConst : public detail::VariantOperators { return iterator(); } JsonArrayConst() - : data_(0) { + : data_(0) + , resources_(0) { } JsonArrayConst(const detail::ArrayData * data, const detail::ResourceManager * resources) : data_(data) , resources_(resources) { } - JsonVariantConst operator[](size_t index) const { - return JsonVariantConst(detail::ArrayData::getElement(data_, index, resources_), resources_); + template + detail::enable_if_t::value, JsonVariantConst> operator[](T index) const { + return JsonVariantConst(detail::ArrayData::getElement(data_, size_t(index), resources_), resources_); + } + template + detail::enable_if_t::value, JsonVariantConst> operator[](const TVariant & variant) const { + if (variant.template is()) + return operator[](variant.template as()); + else + return JsonVariantConst(); } operator JsonVariantConst() const { return JsonVariantConst(getData(), resources_); @@ -3208,20 +3306,20 @@ class JsonArray : public detail::VariantOperators { return JsonArrayConst(data_, resources_); } template - typename detail::enable_if::value, T>::type add() const { + detail::enable_if_t::value, T> add() const { return add().to(); } template - typename detail::enable_if::value, T>::type add() const { + detail::enable_if_t::value, T> add() const { return JsonVariant(detail::ArrayData::addElement(data_, resources_), resources_); } template bool add(const T & value) const { - return add().set(value); + return detail::ArrayData::addValue(data_, value, resources_); } template bool add(T * value) const { - return add().set(value); + return detail::ArrayData::addValue(data_, value, resources_); } iterator begin() const { if (!data_) @@ -3247,11 +3345,24 @@ class JsonArray : public detail::VariantOperators { void remove(size_t index) const { detail::ArrayData::removeElement(data_, index, resources_); } + template + detail::enable_if_t::value> remove(TVariant variant) const { + if (variant.template is()) + remove(variant.template as()); + } void clear() const { detail::ArrayData::clear(data_, resources_); } - detail::ElementProxy operator[](size_t index) const { - return {*this, index}; + template + detail::enable_if_t::value, detail::ElementProxy> operator[](T index) const { + return {*this, size_t(index)}; + } + template + detail::enable_if_t::value, detail::ElementProxy> operator[](const TVariant & variant) const { + if (variant.template is()) + return operator[](variant.template as()); + else + return {*this, size_t(-1)}; } operator JsonVariantConst() const { return JsonVariantConst(collectionToVariant(data_), resources_); @@ -3405,7 +3516,8 @@ class JsonObjectConst : public detail::VariantOperators { public: typedef JsonObjectConstIterator iterator; JsonObjectConst() - : data_(0) { + : data_(0) + , resources_(0) { } JsonObjectConst(const detail::ObjectData * data, const detail::ResourceManager * resources) : data_(data) @@ -3435,21 +3547,32 @@ class JsonObjectConst : public detail::VariantOperators { return iterator(); } template - bool containsKey(const TString & key) const { + detail::enable_if_t::value, bool> containsKey(const TString & key) const { return detail::ObjectData::getMember(data_, detail::adaptString(key), resources_) != 0; } template bool containsKey(TChar * key) const { return detail::ObjectData::getMember(data_, detail::adaptString(key), resources_) != 0; } + template + detail::enable_if_t::value, bool> containsKey(const TVariant & key) const { + return containsKey(key.template as()); + } template - typename detail::enable_if::value, JsonVariantConst>::type operator[](const TString & key) const { + detail::enable_if_t::value, JsonVariantConst> operator[](const TString & key) const { return JsonVariantConst(detail::ObjectData::getMember(data_, detail::adaptString(key), resources_), resources_); } template - typename detail::enable_if::value, JsonVariantConst>::type operator[](TChar * key) const { + detail::enable_if_t::value, JsonVariantConst> operator[](TChar * key) const { return JsonVariantConst(detail::ObjectData::getMember(data_, detail::adaptString(key), resources_), resources_); } + template + detail::enable_if_t::value, JsonVariantConst> operator[](const TVariant & key) const { + if (key.template is()) + return operator[](key.template as()); + else + return JsonVariantConst(); + } ARDUINOJSON_DEPRECATED("always returns zero") size_t memoryUsage() const { return 0; @@ -3586,32 +3709,48 @@ class JsonObject : public detail::VariantOperators { return true; } template - typename detail::enable_if::value, detail::MemberProxy>::type operator[](const TString & key) const { + detail::enable_if_t::value, detail::MemberProxy> operator[](const TString & key) const { return {*this, key}; } template - typename detail::enable_if::value, detail::MemberProxy>::type operator[](TChar * key) const { + detail::enable_if_t::value, detail::MemberProxy> operator[](TChar * key) const { return {*this, key}; } + template + detail::enable_if_t::value, detail::MemberProxy> operator[](const TVariant & key) const { + if (key.template is()) + return {*this, key.template as()}; + else + return {*this, nullptr}; + } FORCE_INLINE void remove(iterator it) const { detail::ObjectData::remove(data_, it.iterator_, resources_); } template - FORCE_INLINE void remove(const TString & key) const { + detail::enable_if_t::value> remove(const TString & key) const { detail::ObjectData::removeMember(data_, detail::adaptString(key), resources_); } + template + detail::enable_if_t::value> remove(const TVariant & key) const { + if (key.template is()) + remove(key.template as()); + } template FORCE_INLINE void remove(TChar * key) const { detail::ObjectData::removeMember(data_, detail::adaptString(key), resources_); } template - typename detail::enable_if::value, bool>::type containsKey(const TString & key) const { + detail::enable_if_t::value, bool> containsKey(const TString & key) const { return detail::ObjectData::getMember(data_, detail::adaptString(key), resources_) != 0; } template - typename detail::enable_if::value, bool>::type containsKey(TChar * key) const { + detail::enable_if_t::value, bool> containsKey(TChar * key) const { return detail::ObjectData::getMember(data_, detail::adaptString(key), resources_) != 0; } + template + detail::enable_if_t::value, bool> containsKey(const TVariant & key) const { + return containsKey(key.template as()); + } template ARDUINOJSON_DEPRECATED("use obj[key].to() instead") JsonArray createNestedArray(TChar * key) const { @@ -3668,9 +3807,8 @@ class JsonDocument : public detail::VariantOperators { template JsonDocument(const T & src, Allocator * alloc = detail::DefaultAllocator::instance(), - typename detail::enable_if::value || detail::is_same::value - || detail::is_same::value || detail::is_same::value - || detail::is_same::value || detail::is_same::value>::type * = 0) + detail::enable_if_t::value || detail::is_same::value || detail::is_same::value + || detail::is_same::value || detail::is_same::value> * = 0) : JsonDocument(alloc) { set(src); } @@ -3725,7 +3863,7 @@ class JsonDocument : public detail::VariantOperators { return to().set(src.as()); } template - typename detail::enable_if::value, bool>::type set(const T & src) { + detail::enable_if_t::value, bool> set(const T & src) { return to().set(src); } template @@ -3738,58 +3876,79 @@ class JsonDocument : public detail::VariantOperators { return data_.getMember(detail::adaptString(key), &resources_) != 0; } template - bool containsKey(const TString & key) const { + detail::enable_if_t::value, bool> containsKey(const TString & key) const { return data_.getMember(detail::adaptString(key), &resources_) != 0; } + template + detail::enable_if_t::value, bool> containsKey(const TVariant & key) const { + return containsKey(key.template as()); + } template - typename detail::enable_if::value, detail::MemberProxy>::type operator[](const TString & key) { + detail::enable_if_t::value, detail::MemberProxy> operator[](const TString & key) { return {*this, key}; } template - typename detail::enable_if::value, detail::MemberProxy>::type operator[](TChar * key) { + detail::enable_if_t::value, detail::MemberProxy> operator[](TChar * key) { return {*this, key}; } template - typename detail::enable_if::value, JsonVariantConst>::type operator[](const TString & key) const { + detail::enable_if_t::value, JsonVariantConst> operator[](const TString & key) const { return JsonVariantConst(data_.getMember(detail::adaptString(key), &resources_), &resources_); } template - typename detail::enable_if::value, JsonVariantConst>::type operator[](TChar * key) const { + detail::enable_if_t::value, JsonVariantConst> operator[](TChar * key) const { return JsonVariantConst(data_.getMember(detail::adaptString(key), &resources_), &resources_); } - detail::ElementProxy operator[](size_t index) { - return {*this, index}; + template + detail::enable_if_t::value, detail::ElementProxy> operator[](T index) { + return {*this, size_t(index)}; } JsonVariantConst operator[](size_t index) const { return JsonVariantConst(data_.getElement(index, &resources_), &resources_); } + template + detail::enable_if_t::value, JsonVariantConst> operator[](const TVariant & key) const { + if (key.template is()) + return operator[](key.template as()); + if (key.template is()) + return operator[](key.template as()); + return {}; + } template - typename detail::enable_if::value, T>::type add() { + detail::enable_if_t::value, T> add() { return add().to(); } template - typename detail::enable_if::value, T>::type add() { + detail::enable_if_t::value, T> add() { return JsonVariant(data_.addElement(&resources_), &resources_); } template bool add(const TValue & value) { - return add().set(value); + return data_.addValue(value, &resources_); } template bool add(TChar * value) { - return add().set(value); + return data_.addValue(value, &resources_); } - void remove(size_t index) { - detail::VariantData::removeElement(getData(), index, getResourceManager()); + template + detail::enable_if_t::value> remove(T index) { + detail::VariantData::removeElement(getData(), size_t(index), getResourceManager()); } template - typename detail::enable_if::value>::type remove(TChar * key) { + detail::enable_if_t::value> remove(TChar * key) { detail::VariantData::removeMember(getData(), detail::adaptString(key), getResourceManager()); } template - typename detail::enable_if::value>::type remove(const TString & key) { + detail::enable_if_t::value> remove(const TString & key) { detail::VariantData::removeMember(getData(), detail::adaptString(key), getResourceManager()); } + template + detail::enable_if_t::value> remove(const TVariant & key) { + if (key.template is()) + remove(key.template as()); + if (key.template is()) + remove(key.template as()); + } operator JsonVariant() { return getVariant(); } @@ -3916,8 +4075,8 @@ struct ComparerBase : JsonVariantVisitor {}; template struct Comparer; template -struct Comparer::value>::type> : ComparerBase { - T rhs; +struct Comparer::value>> : ComparerBase { + T rhs; // TODO: store adapted string? explicit Comparer(T value) : rhs(value) { } @@ -3939,7 +4098,7 @@ struct Comparer::value>::type> : ComparerBase using ComparerBase::visit; }; template -struct Comparer::value || is_floating_point::value>::type> : ComparerBase { +struct Comparer::value || is_floating_point::value>> : ComparerBase { T rhs; explicit Comparer(T value) : rhs(value) { @@ -4070,7 +4229,7 @@ struct VariantComparer : ComparerBase { } }; template -struct Comparer::value>::type> : VariantComparer { +struct Comparer::value>> : VariantComparer { explicit Comparer(const T & value) : VariantComparer(static_cast(value)) { } @@ -4111,19 +4270,32 @@ inline VariantData * ArrayData::getElement(size_t index, const ResourceManager * inline void ArrayData::removeElement(size_t index, ResourceManager * resources) { remove(at(index, resources), resources); } +template +inline bool ArrayData::addValue(T && value, ResourceManager * resources) { + ARDUINOJSON_ASSERT(resources != nullptr); + auto slot = resources->allocSlot(); + if (!slot) + return false; + JsonVariant variant(slot->data(), resources); + if (!variant.set(detail::forward(value))) { + resources->freeSlot(slot); + return false; + } + addSlot(slot, resources); + return true; +} ARDUINOJSON_END_PRIVATE_NAMESPACE ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE template -inline typename detail::enable_if::value, bool>::type copyArray(const T & src, JsonVariant dst) { +inline detail::enable_if_t::value, bool> copyArray(const T & src, JsonVariant dst) { return dst.set(src); } template -inline typename detail::enable_if::value, bool>::type copyArray(T (&src)[N], const TDestination & dst) { +inline detail::enable_if_t::value, bool> copyArray(T (&src)[N], const TDestination & dst) { return copyArray(src, N, dst); } template -inline typename detail::enable_if::value, bool>::type -copyArray(const T * src, size_t len, const TDestination & dst) { +inline detail::enable_if_t::value, bool> copyArray(const T * src, size_t len, const TDestination & dst) { bool ok = true; for (size_t i = 0; i < len; i++) { ok &= copyArray(src[i], dst.template add()); @@ -4143,7 +4315,7 @@ inline bool copyArray(const T * src, size_t len, JsonDocument & dst) { return copyArray(src, len, dst.to()); } template -inline typename detail::enable_if::value, size_t>::type copyArray(JsonVariantConst src, T & dst) { +inline detail::enable_if_t::value, size_t> copyArray(JsonVariantConst src, T & dst) { dst = src.as(); return 1; } @@ -4169,8 +4341,7 @@ inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) { return 1; } template -inline typename detail::enable_if::value && detail::is_base_of::value, size_t>::type copyArray(const TSource & src, - T & dst) { +inline detail::enable_if_t::value && detail::is_base_of::value, size_t> copyArray(const TSource & src, T & dst) { return copyArray(src.template as(), dst); } ARDUINOJSON_END_PUBLIC_NAMESPACE @@ -4255,13 +4426,23 @@ inline CollectionData::iterator CollectionData::addSlot(ResourceManager * resour } return iterator(slot, slot.id()); } +inline void CollectionData::addSlot(SlotWithId slot, ResourceManager * resources) { + if (tail_ != NULL_SLOT) { + auto tail = resources->getSlot(tail_); + tail->setNext(slot.id()); + tail_ = slot.id(); + } else { + head_ = slot.id(); + tail_ = slot.id(); + } +} inline void CollectionData::clear(ResourceManager * resources) { auto next = head_; while (next != NULL_SLOT) { auto currId = next; auto slot = resources->getSlot(next); next = slot->next(); - releaseSlot(SlotWithId(slot, currId), resources); + resources->freeSlot(SlotWithId(slot, currId)); } head_ = NULL_SLOT; tail_ = NULL_SLOT; @@ -4290,7 +4471,7 @@ inline void CollectionData::remove(iterator it, ResourceManager * resources) { head_ = next; if (next == NULL_SLOT) tail_ = prev.id(); - releaseSlot({it.slot_, it.currentId_}, resources); + resources->freeSlot({it.slot_, it.currentId_}); } inline size_t CollectionData::nesting(const ResourceManager * resources) const { size_t maxChildNesting = 0; @@ -4307,11 +4488,11 @@ inline size_t CollectionData::size(const ResourceManager * resources) const { count++; return count; } -inline void CollectionData::releaseSlot(SlotWithId slot, ResourceManager * resources) { +inline void ResourceManager::freeSlot(SlotWithId slot) { if (slot->ownsKey()) - resources->dereferenceString(slot->key()); - slot->data()->setNull(resources); - resources->freeSlot(slot); + dereferenceString(slot->key()); + slot->data()->setNull(this); + variantPools_.freeSlot(slot); } inline void VariantPool::create(SlotCount cap, Allocator * allocator) { ARDUINOJSON_ASSERT(cap > 0); @@ -4568,9 +4749,9 @@ class TextFormatter { } } template - typename enable_if::value>::type writeInteger(T value) { - typedef typename make_unsigned::type unsigned_type; - unsigned_type unsigned_value; + enable_if_t::value> writeInteger(T value) { + typedef make_unsigned_t unsigned_type; + unsigned_type unsigned_value; if (value < 0) { writeRaw('-'); unsigned_value = unsigned_type(unsigned_type(~value) + 1); @@ -4580,7 +4761,7 @@ class TextFormatter { writeInteger(unsigned_value); } template - typename enable_if::value>::type writeInteger(T value) { + enable_if_t::value> writeInteger(T value) { char buffer[22]; char * end = buffer + sizeof(buffer); char * begin = end; @@ -4683,10 +4864,9 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template struct is_std_string : false_type {}; template -struct is_std_string::value && is_same::value>::type> - : true_type {}; +struct is_std_string::value && is_same::value>> : true_type {}; template -class Writer::value>::type> { +class Writer::value>> { public: Writer(TDestination & str) : str_(&str) { @@ -4752,7 +4932,7 @@ ARDUINOJSON_END_PRIVATE_NAMESPACE #if ARDUINOJSON_ENABLE_STD_STREAM ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template -class Writer::value>::type> { +class Writer::value>> { public: explicit Writer(std::ostream & os) : os_(&os) { @@ -4774,7 +4954,7 @@ ARDUINOJSON_END_PRIVATE_NAMESPACE #if ARDUINOJSON_ENABLE_ARDUINO_PRINT ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template -class Writer::value>::type> { +class Writer::value>> { public: explicit Writer(::Print & print) : print_(&print) { @@ -4803,12 +4983,12 @@ size_t serialize(ArduinoJson::JsonVariantConst source, TDestination & destinatio return doSerialize(source, writer); } template