diff --git a/wled00/src/dependencies/json/ArduinoJson-v5.h b/wled00/src/dependencies/json/ArduinoJson-v5.h deleted file mode 100644 index 1728af0c..00000000 --- a/wled00/src/dependencies/json/ArduinoJson-v5.h +++ /dev/null @@ -1,3429 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2019 -// MIT License - -#pragma once - -#ifdef __cplusplus - -#define ARDUINOJSON_VERSION "5.13.5" -#define ARDUINOJSON_VERSION_MAJOR 5 -#define ARDUINOJSON_VERSION_MINOR 13 -#define ARDUINOJSON_VERSION_REVISION 5 -#include // for size_t -#include // for uint8_t -#include -namespace ArduinoJson { -namespace Internals { -class NonCopyable { - protected: - NonCopyable() {} - private: - NonCopyable(const NonCopyable&); - NonCopyable& operator=(const NonCopyable&); -}; -} // namespace Internals -} // namespace ArduinoJson -#ifndef ARDUINOJSON_EMBEDDED_MODE -#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \ - defined(__ARMCC_VERSION) -#define ARDUINOJSON_EMBEDDED_MODE 1 -#else -#define ARDUINOJSON_EMBEDDED_MODE 0 -#endif -#endif -#if ARDUINOJSON_EMBEDDED_MODE -#ifndef ARDUINOJSON_USE_DOUBLE -#define ARDUINOJSON_USE_DOUBLE 0 -#endif -#ifndef ARDUINOJSON_USE_LONG_LONG -#define ARDUINOJSON_USE_LONG_LONG 0 -#endif -#ifndef ARDUINOJSON_USE_INT64 -#define ARDUINOJSON_USE_INT64 0 -#endif -#ifndef ARDUINOJSON_ENABLE_STD_STRING -#define ARDUINOJSON_ENABLE_STD_STRING 0 -#endif -#ifndef ARDUINOJSON_ENABLE_STD_STREAM -#define ARDUINOJSON_ENABLE_STD_STREAM 0 -#endif -#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT -#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 -#endif -#else // ARDUINOJSON_EMBEDDED_MODE -#ifndef ARDUINOJSON_USE_DOUBLE -#define ARDUINOJSON_USE_DOUBLE 1 -#endif -#ifndef ARDUINOJSON_USE_LONG_LONG -#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) -#define ARDUINOJSON_USE_LONG_LONG 1 -#else -#define ARDUINOJSON_USE_LONG_LONG 0 -#endif -#endif -#ifndef ARDUINOJSON_USE_INT64 -#if defined(_MSC_VER) && _MSC_VER <= 1700 -#define ARDUINOJSON_USE_INT64 1 -#else -#define ARDUINOJSON_USE_INT64 0 -#endif -#endif -#ifndef ARDUINOJSON_ENABLE_STD_STRING -#define ARDUINOJSON_ENABLE_STD_STRING 1 -#endif -#ifndef ARDUINOJSON_ENABLE_STD_STREAM -#define ARDUINOJSON_ENABLE_STD_STREAM 1 -#endif -#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT -#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50 -#endif -#endif // ARDUINOJSON_EMBEDDED_MODE -#ifdef ARDUINO -#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING -#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 -#endif -#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM -#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 -#endif -#else // ARDUINO -#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING -#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 -#endif -#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM -#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0 -#endif -#endif // ARDUINO -#ifndef ARDUINOJSON_ENABLE_PROGMEM -#ifdef PROGMEM -#define ARDUINOJSON_ENABLE_PROGMEM 1 -#else -#define ARDUINOJSON_ENABLE_PROGMEM 0 -#endif -#endif -#ifndef ARDUINOJSON_ENABLE_ALIGNMENT -#ifdef ARDUINO_ARCH_AVR -#define ARDUINOJSON_ENABLE_ALIGNMENT 0 -#else -#define ARDUINOJSON_ENABLE_ALIGNMENT 1 -#endif -#endif -#ifndef ARDUINOJSON_ENABLE_DEPRECATED -#define ARDUINOJSON_ENABLE_DEPRECATED 1 -#endif -#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD -#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 -#endif -#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD -#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5 -#endif -#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64 -#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together -#endif -namespace ArduinoJson { -namespace Internals { -#if ARDUINOJSON_USE_DOUBLE -typedef double JsonFloat; -#else -typedef float JsonFloat; -#endif -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -#if ARDUINOJSON_USE_LONG_LONG -typedef long long JsonInteger; -typedef unsigned long long JsonUInt; -#elif ARDUINOJSON_USE_INT64 -typedef __int64 JsonInteger; -typedef unsigned _int64 JsonUInt; -#else -typedef long JsonInteger; -typedef unsigned long JsonUInt; -#endif -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -class JsonArray; -class JsonObject; -namespace Internals { -union JsonVariantContent { - JsonFloat asFloat; // used for double and float - JsonUInt asInteger; // used for bool, char, short, int and longs - const char* asString; // asString can be null - JsonArray* asArray; // asArray cannot be null - JsonObject* asObject; // asObject cannot be null -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct JsonVariantDefault { - static T get() { - return T(); - } -}; -template -struct JsonVariantDefault : JsonVariantDefault {}; -template -struct JsonVariantDefault : JsonVariantDefault {}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -class JsonArray; -class JsonObject; -namespace Internals { -enum JsonVariantType { - JSON_UNDEFINED, // JsonVariant has not been initialized - JSON_UNPARSED, // JsonVariant contains an unparsed string - JSON_STRING, // JsonVariant stores a const char* - JSON_BOOLEAN, // JsonVariant stores a bool - JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt - JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated - JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray - JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject - JSON_FLOAT // JsonVariant stores a JsonFloat -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct JsonVariantAs { - typedef T type; -}; -template <> -struct JsonVariantAs { - typedef const char* type; -}; -template <> -struct JsonVariantAs { - typedef JsonArray& type; -}; -template <> -struct JsonVariantAs { - typedef const JsonArray& type; -}; -template <> -struct JsonVariantAs { - typedef JsonObject& type; -}; -template <> -struct JsonVariantAs { - typedef const JsonObject& type; -}; -} // namespace Internals -} // namespace ArduinoJson -#ifdef _MSC_VER // Visual Studio -#define FORCE_INLINE // __forceinline causes C4714 when returning std::string -#define NO_INLINE __declspec(noinline) -#define DEPRECATED(msg) __declspec(deprecated(msg)) -#elif defined(__GNUC__) // GCC or Clang -#define FORCE_INLINE __attribute__((always_inline)) -#define NO_INLINE __attribute__((noinline)) -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) -#define DEPRECATED(msg) __attribute__((deprecated(msg))) -#else -#define DEPRECATED(msg) __attribute__((deprecated)) -#endif -#else // Other compilers -#define FORCE_INLINE -#define NO_INLINE -#define DEPRECATED(msg) -#endif -namespace ArduinoJson { -namespace Internals { -template -class JsonVariantCasts { - public: -#if ARDUINOJSON_ENABLE_DEPRECATED - DEPRECATED("use as() instead") - FORCE_INLINE JsonArray &asArray() const { - return impl()->template as(); - } - DEPRECATED("use as() instead") - FORCE_INLINE JsonObject &asObject() const { - return impl()->template as(); - } - DEPRECATED("use as() instead") - FORCE_INLINE const char *asString() const { - return impl()->template as(); - } -#endif - FORCE_INLINE operator JsonArray &() const { - return impl()->template as(); - } - FORCE_INLINE operator JsonObject &() const { - return impl()->template as(); - } - template - FORCE_INLINE operator T() const { - return impl()->template as(); - } - private: - const TImpl *impl() const { - return static_cast(this); - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct EnableIf {}; -template -struct EnableIf { - typedef T type; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class IsBaseOf { - protected: // <- to avoid GCC's "all member functions in class are private" - typedef char Yes[1]; - typedef char No[2]; - static Yes &probe(const TBase *); - static No &probe(...); - public: - enum { - value = sizeof(probe(reinterpret_cast(0))) == sizeof(Yes) - }; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct IsSame { - static const bool value = false; -}; -template -struct IsSame { - static const bool value = true; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct IsChar { - static const bool value = IsSame::value || - IsSame::value || - IsSame::value; -}; -template -struct IsChar : IsChar {}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct IsConst { - static const bool value = false; -}; -template -struct IsConst { - static const bool value = true; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct RemoveReference { - typedef T type; -}; -template -struct RemoveReference { - typedef T type; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct StringTraits { - static const bool has_append = false; - static const bool has_equals = false; -}; -template -struct StringTraits : StringTraits {}; -template -struct StringTraits : StringTraits {}; -} // namespace Internals -} // namespace ArduinoJson -#if ARDUINOJSON_ENABLE_ARDUINO_STREAM -#include -namespace ArduinoJson { -namespace Internals { -struct ArduinoStreamTraits { - class Reader { - Stream& _stream; - char _current, _next; - public: - Reader(Stream& stream) : _stream(stream), _current(0), _next(0) {} - void move() { - _current = _next; - _next = 0; - } - char current() { - if (!_current) _current = read(); - return _current; - } - char next() { - if (!_next) _next = read(); - return _next; - } - private: - char read() { - char c = 0; - _stream.readBytes(&c, 1); - return c; - } - }; - static const bool has_append = false; - static const bool has_equals = false; -}; -template -struct StringTraits< - TStream, - typename EnableIf< - IsBaseOf::type>::value>::type> - : ArduinoStreamTraits {}; -} // namespace Internals -} // namespace ArduinoJson -#endif -namespace ArduinoJson { -namespace Internals { -template -struct CharPointerTraits { - class Reader { - const TChar* _ptr; - public: - Reader(const TChar* ptr) - : _ptr(ptr ? ptr : reinterpret_cast("")) {} - void move() { - ++_ptr; - } - char current() const { - return char(_ptr[0]); - } - char next() const { - return char(_ptr[1]); - } - }; - static bool equals(const TChar* str, const char* expected) { - const char* actual = reinterpret_cast(str); - if (!actual || !expected) return actual == expected; - return strcmp(actual, expected) == 0; - } - static bool is_null(const TChar* str) { - return !str; - } - typedef const char* duplicate_t; - template - static duplicate_t duplicate(const TChar* str, Buffer* buffer) { - if (!str) return NULL; - size_t size = strlen(reinterpret_cast(str)) + 1; - void* dup = buffer->alloc(size); - if (dup != NULL) memcpy(dup, str, size); - return static_cast(dup); - } - static const bool has_append = false; - static const bool has_equals = true; - static const bool should_duplicate = !IsConst::value; -}; -template -struct StringTraits::value>::type> - : CharPointerTraits {}; -} // namespace Internals -} // namespace ArduinoJson -#if ARDUINOJSON_ENABLE_PROGMEM -namespace ArduinoJson { -namespace Internals { -template <> -struct StringTraits { - class Reader { - const char* _ptr; - public: - Reader(const __FlashStringHelper* ptr) - : _ptr(reinterpret_cast(ptr)) {} - void move() { - _ptr++; - } - char current() const { - return pgm_read_byte_near(_ptr); - } - char next() const { - return pgm_read_byte_near(_ptr + 1); - } - }; - static bool equals(const __FlashStringHelper* str, const char* expected) { - const char* actual = reinterpret_cast(str); - if (!actual || !expected) return actual == expected; - return strcmp_P(expected, actual) == 0; - } - static bool is_null(const __FlashStringHelper* str) { - return !str; - } - typedef const char* duplicate_t; - template - static duplicate_t duplicate(const __FlashStringHelper* str, Buffer* buffer) { - if (!str) return NULL; - size_t size = strlen_P((const char*)str) + 1; - void* dup = buffer->alloc(size); - if (dup != NULL) memcpy_P(dup, (const char*)str, size); - return static_cast(dup); - } - static const bool has_append = false; - static const bool has_equals = true; - static const bool should_duplicate = true; -}; -} // namespace Internals -} // namespace ArduinoJson -#endif -#if ARDUINOJSON_ENABLE_STD_STREAM -#include -namespace ArduinoJson { -namespace Internals { -struct StdStreamTraits { - class Reader { - std::istream& _stream; - char _current, _next; - public: - Reader(std::istream& stream) : _stream(stream), _current(0), _next(0) {} - void move() { - _current = _next; - _next = 0; - } - char current() { - if (!_current) _current = read(); - return _current; - } - char next() { - if (!_next) _next = read(); - return _next; - } - private: - Reader& operator=(const Reader&); // Visual Studio C4512 - char read() { - return _stream.eof() ? '\0' : static_cast(_stream.get()); - } - }; - static const bool has_append = false; - static const bool has_equals = false; -}; -template -struct StringTraits< - TStream, - typename EnableIf::type>::value>::type> - : StdStreamTraits {}; -} // namespace Internals -} // namespace ArduinoJson -#endif -#if ARDUINOJSON_ENABLE_STD_STRING || ARDUINOJSON_ENABLE_ARDUINO_STRING -#if ARDUINOJSON_ENABLE_ARDUINO_STRING -#include -#endif -#if ARDUINOJSON_ENABLE_STD_STRING -#include -#endif -namespace ArduinoJson { -namespace Internals { -template -struct StdStringTraits { - typedef const char* duplicate_t; - template - static duplicate_t duplicate(const TString& str, Buffer* buffer) { - if (!str.c_str()) return NULL; // <- Arduino string can return NULL - size_t size = str.length() + 1; - void* dup = buffer->alloc(size); - if (dup != NULL) memcpy(dup, str.c_str(), size); - return static_cast(dup); - } - static bool is_null(const TString& str) { - return !str.c_str(); - } - struct Reader : CharPointerTraits::Reader { - Reader(const TString& str) : CharPointerTraits::Reader(str.c_str()) {} - }; - static bool equals(const TString& str, const char* expected) { - const char* actual = str.c_str(); - if (!actual || !expected) return actual == expected; - return 0 == strcmp(actual, expected); - } - static void append(TString& str, char c) { - str += c; - } - static void append(TString& str, const char* s) { - str += s; - } - static const bool has_append = true; - static const bool has_equals = true; - static const bool should_duplicate = true; -}; -#if ARDUINOJSON_ENABLE_ARDUINO_STRING -template <> -struct StringTraits : StdStringTraits {}; -template <> -struct StringTraits : StdStringTraits { -}; -#endif -#if ARDUINOJSON_ENABLE_STD_STRING -template <> -struct StringTraits : StdStringTraits {}; -#endif -} // namespace Internals -} // namespace ArduinoJson -#endif -namespace ArduinoJson { -namespace Internals { -class JsonVariantTag {}; -template -struct IsVariant : IsBaseOf {}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class JsonVariantComparisons { - public: - template - friend bool operator==(const JsonVariantComparisons &variant, - TComparand comparand) { - return variant.equals(comparand); - } - template - friend typename EnableIf::value, bool>::type - operator==(TComparand comparand, const JsonVariantComparisons &variant) { - return variant.equals(comparand); - } - template - friend bool operator!=(const JsonVariantComparisons &variant, - TComparand comparand) { - return !variant.equals(comparand); - } - template - friend typename EnableIf::value, bool>::type - operator!=(TComparand comparand, const JsonVariantComparisons &variant) { - return !variant.equals(comparand); - } - template - friend bool operator<=(const JsonVariantComparisons &left, TComparand right) { - return left.as() <= right; - } - template - friend bool operator<=(TComparand comparand, - const JsonVariantComparisons &variant) { - return comparand <= variant.as(); - } - template - friend bool operator>=(const JsonVariantComparisons &variant, - TComparand comparand) { - return variant.as() >= comparand; - } - template - friend bool operator>=(TComparand comparand, - const JsonVariantComparisons &variant) { - return comparand >= variant.as(); - } - template - friend bool operator<(const JsonVariantComparisons &varian, - TComparand comparand) { - return varian.as() < comparand; - } - template - friend bool operator<(TComparand comparand, - const JsonVariantComparisons &variant) { - return comparand < variant.as(); - } - template - friend bool operator>(const JsonVariantComparisons &variant, - TComparand comparand) { - return variant.as() > comparand; - } - template - friend bool operator>(TComparand comparand, - const JsonVariantComparisons &variant) { - return comparand > variant.as(); - } - private: - const TImpl *impl() const { - return static_cast(this); - } - template - const typename JsonVariantAs::type as() const { - return impl()->template as(); - } - template - bool is() const { - return impl()->template is(); - } - template - typename EnableIf::has_equals, bool>::type equals( - const TString &comparand) const { - const char *value = as(); - return StringTraits::equals(comparand, value); - } - template - typename EnableIf::value && - !StringTraits::has_equals, - bool>::type - equals(const TComparand &comparand) const { - return as() == comparand; - } - template - bool equals(const JsonVariantComparisons &right) const { - using namespace Internals; - if (is() && right.template is()) - return as() == right.template as(); - if (is() && right.template is()) - return as() == right.template as(); - if (is() && right.template is()) - return as() == right.template as(); - if (is() && right.template is()) - return as() == right.template as(); - if (is() && right.template is()) - return as() == right.template as(); - if (is() && right.template is()) - return StringTraits::equals(as(), - right.template as()); - return false; - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct IsSignedIntegral { - static const bool value = - IsSame::value || IsSame::value || - IsSame::value || IsSame::value || -#if ARDUINOJSON_USE_LONG_LONG - IsSame::value || -#endif -#if ARDUINOJSON_USE_INT64 - IsSame::value || -#endif - false; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct IsUnsignedIntegral { - static const bool value = - IsSame::value || IsSame::value || - IsSame::value || IsSame::value || -#if ARDUINOJSON_USE_LONG_LONG - IsSame::value || -#endif -#if ARDUINOJSON_USE_INT64 - IsSame::value || -#endif - false; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct IsIntegral { - static const bool value = IsSignedIntegral::value || - IsUnsignedIntegral::value || - IsSame::value; -}; -template -struct IsIntegral : IsIntegral {}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class JsonVariantOr { - public: - template - typename EnableIf::value, T>::type operator|( - const T &defaultValue) const { - if (impl()->template is()) - return impl()->template as(); - else - return defaultValue; - } - const char *operator|(const char *defaultValue) const { - const char *value = impl()->template as(); - return value ? value : defaultValue; - } - template - typename EnableIf::value, Integer>::type operator|( - const Integer &defaultValue) const { - if (impl()->template is()) - return impl()->template as(); - else - return defaultValue; - } - private: - const TImpl *impl() const { - return static_cast(this); - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -class JsonArraySubscript; -template -class JsonObjectSubscript; -template -class JsonVariantSubscripts { - public: - size_t size() const { - return impl()->template as().size() + - impl()->template as().size(); - } - FORCE_INLINE const JsonArraySubscript operator[](size_t index) const; - FORCE_INLINE JsonArraySubscript operator[](size_t index); - template - FORCE_INLINE - typename EnableIf::has_equals, - const JsonObjectSubscript >::type - operator[](const TString &key) const { - return impl()->template as()[key]; - } - template - FORCE_INLINE typename EnableIf::has_equals, - JsonObjectSubscript >::type - operator[](const TString &key) { - return impl()->template as()[key]; - } - template - FORCE_INLINE typename EnableIf::has_equals, - JsonObjectSubscript >::type - operator[](const TString *key) { - return impl()->template as()[key]; - } - template - FORCE_INLINE - typename EnableIf::has_equals, - const JsonObjectSubscript >::type - operator[](const TString *key) const { - return impl()->template as()[key]; - } - private: - const TImpl *impl() const { - return static_cast(this); - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -class DummyPrint { - public: - size_t print(char) { - return 1; - } - size_t print(const char* s) { - return strlen(s); - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class DynamicStringBuilder { - public: - DynamicStringBuilder(TString &str) : _str(str) {} - size_t print(char c) { - StringTraits::append(_str, c); - return 1; - } - size_t print(const char *s) { - size_t initialLen = _str.length(); - StringTraits::append(_str, s); - return _str.length() - initialLen; - } - private: - DynamicStringBuilder &operator=(const DynamicStringBuilder &); - TString &_str; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class IndentedPrint { - public: - explicit IndentedPrint(Print &p) : sink(&p) { - level = 0; - tabSize = 2; - isNewLine = true; - } - size_t print(char c) { - size_t n = 0; - if (isNewLine) n += writeTabs(); - n += sink->print(c); - isNewLine = c == '\n'; - return n; - } - size_t print(const char *s) { - size_t n = 0; - while (*s) n += print(*s++); - return n; - } - void indent() { - if (level < MAX_LEVEL) level++; - } - void unindent() { - if (level > 0) level--; - } - void setTabSize(uint8_t n) { - if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE; - } - private: - Print *sink; - uint8_t level : 4; - uint8_t tabSize : 3; - bool isNewLine : 1; - size_t writeTabs() { - size_t n = 0; - for (int i = 0; i < level * tabSize; i++) n += sink->print(' '); - return n; - } - static const int MAX_LEVEL = 15; // because it's only 4 bits - static const int MAX_TAB_SIZE = 7; // because it's only 3 bits -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -class Encoding { - public: - static char escapeChar(char c) { - const char *p = escapeTable(false); - while (p[0] && p[1] != c) { - p += 2; - } - return p[0]; - } - static char unescapeChar(char c) { - const char *p = escapeTable(true); - for (;;) { - if (p[0] == '\0') return c; - if (p[0] == c) return p[1]; - p += 2; - } - } - private: - static const char *escapeTable(bool excludeIdenticals) { - return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0]; - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -bool isNaN(T x) { - return x != x; -} -template -bool isInfinity(T x) { - return x != 0.0 && x * 2 == x; -} -} // namespace Internals -} // namespace ArduinoJson -#include // for size_t -namespace ArduinoJson { -namespace Internals { -template -struct alias_cast_t { - union { - F raw; - T data; - }; -}; -template -T alias_cast(F raw_data) { - alias_cast_t ac; - ac.raw = raw_data; - return ac.data; -} -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct FloatTraits {}; -template -struct FloatTraits { - typedef int64_t mantissa_type; - static const short mantissa_bits = 52; - static const mantissa_type mantissa_max = - (static_cast(1) << mantissa_bits) - 1; - typedef int16_t exponent_type; - static const exponent_type exponent_max = 308; - template - static T make_float(T m, TExponent e) { - if (e > 0) { - for (uint8_t index = 0; e != 0; index++) { - if (e & 1) m *= positiveBinaryPowerOfTen(index); - e >>= 1; - } - } else { - e = TExponent(-e); - for (uint8_t index = 0; e != 0; index++) { - if (e & 1) m *= negativeBinaryPowerOfTen(index); - e >>= 1; - } - } - 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]; - } - 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]; - } - 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]; - } - static T nan() { - return forge(0x7ff80000, 0x00000000); - } - static T inf() { - return forge(0x7ff00000, 0x00000000); - } - static T forge(uint32_t msb, uint32_t lsb) { - return alias_cast((uint64_t(msb) << 32) | lsb); - } -}; -template -struct FloatTraits { - typedef int32_t mantissa_type; - static const short mantissa_bits = 23; - static const mantissa_type mantissa_max = - (static_cast(1) << mantissa_bits) - 1; - typedef int8_t exponent_type; - static const exponent_type exponent_max = 38; - template - static T make_float(T m, TExponent e) { - if (e > 0) { - for (uint8_t index = 0; e != 0; index++) { - if (e & 1) m *= positiveBinaryPowerOfTen(index); - e >>= 1; - } - } else { - e = -e; - for (uint8_t index = 0; e != 0; index++) { - if (e & 1) m *= negativeBinaryPowerOfTen(index); - e >>= 1; - } - } - return m; - } - static T positiveBinaryPowerOfTen(int index) { - static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}; - return 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]; - } - static T negativeBinaryPowerOfTenPlusOne(int index) { - static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}; - return factors[index]; - } - static T forge(uint32_t bits) { - return alias_cast(bits); - } - static T nan() { - return forge(0x7fc00000); - } - static T inf() { - return forge(0x7f800000); - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct FloatParts { - uint32_t integral; - uint32_t decimal; - int16_t exponent; - int8_t decimalPlaces; - FloatParts(TFloat value) { - uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000; - decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6; - exponent = normalize(value); - integral = uint32_t(value); - for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) { - maxDecimalPart /= 10; - decimalPlaces--; - } - TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart); - decimal = uint32_t(remainder); - remainder = remainder - TFloat(decimal); - decimal += uint32_t(remainder * 2); - if (decimal >= maxDecimalPart) { - decimal = 0; - integral++; - if (exponent && integral >= 10) { - exponent++; - integral = 1; - } - } - while (decimal % 10 == 0 && decimalPlaces > 0) { - decimal /= 10; - decimalPlaces--; - } - } - static int16_t normalize(TFloat& value) { - typedef FloatTraits traits; - int16_t powersOf10 = 0; - int8_t index = sizeof(TFloat) == 8 ? 8 : 5; - int bit = 1 << index; - if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) { - for (; index >= 0; index--) { - if (value >= traits::positiveBinaryPowerOfTen(index)) { - value *= traits::negativeBinaryPowerOfTen(index); - powersOf10 = int16_t(powersOf10 + bit); - } - bit >>= 1; - } - } - if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) { - for (; index >= 0; index--) { - if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) { - value *= traits::positiveBinaryPowerOfTen(index); - powersOf10 = int16_t(powersOf10 - bit); - } - bit >>= 1; - } - } - return powersOf10; - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class JsonWriter { - public: - explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {} - size_t bytesWritten() const { - return _length; - } - void beginArray() { - writeRaw('['); - } - void endArray() { - writeRaw(']'); - } - void beginObject() { - writeRaw('{'); - } - void endObject() { - writeRaw('}'); - } - void writeColon() { - writeRaw(':'); - } - void writeComma() { - writeRaw(','); - } - void writeBoolean(bool value) { - writeRaw(value ? "true" : "false"); - } - void writeString(const char *value) { - if (!value) { - writeRaw("null"); - } else { - writeRaw('\"'); - while (*value) writeChar(*value++); - writeRaw('\"'); - } - } - void writeChar(char c) { - char specialChar = Encoding::escapeChar(c); - if (specialChar) { - writeRaw('\\'); - writeRaw(specialChar); - } else { - writeRaw(c); - } - } - template - void writeFloat(TFloat value) { - if (isNaN(value)) return writeRaw("NaN"); - if (value < 0.0) { - writeRaw('-'); - value = -value; - } - if (isInfinity(value)) return writeRaw("Infinity"); - FloatParts parts(value); - writeInteger(parts.integral); - if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces); - if (parts.exponent < 0) { - writeRaw("e-"); - writeInteger(-parts.exponent); - } - if (parts.exponent > 0) { - writeRaw('e'); - writeInteger(parts.exponent); - } - } - template - void writeInteger(UInt value) { - char buffer[22]; - char *end = buffer + sizeof(buffer) - 1; - char *ptr = end; - *ptr = 0; - do { - *--ptr = char(value % 10 + '0'); - value = UInt(value / 10); - } while (value); - writeRaw(ptr); - } - void writeDecimals(uint32_t value, int8_t width) { - char buffer[16]; - char *ptr = buffer + sizeof(buffer) - 1; - *ptr = 0; - while (width--) { - *--ptr = char(value % 10 + '0'); - value /= 10; - } - *--ptr = '.'; - writeRaw(ptr); - } - void writeRaw(const char *s) { - _length += _sink.print(s); - } - void writeRaw(char c) { - _length += _sink.print(c); - } - protected: - Print &_sink; - size_t _length; - private: - JsonWriter &operator=(const JsonWriter &); // cannot be assigned -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -class JsonArray; -class JsonObject; -class JsonVariant; -namespace Internals { -class JsonArraySubscript; -template -class JsonObjectSubscript; -template -class JsonSerializer { - public: - static void serialize(const JsonArray &, Writer &); - static void serialize(const JsonArraySubscript &, Writer &); - static void serialize(const JsonObject &, Writer &); - template - static void serialize(const JsonObjectSubscript &, Writer &); - static void serialize(const JsonVariant &, Writer &); -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class Prettyfier { - public: - explicit Prettyfier(IndentedPrint& p) : _sink(p) { - _previousChar = 0; - _inString = false; - } - size_t print(char c) { - size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c); - _previousChar = c; - return n; - } - size_t print(const char* s) { - size_t n = 0; - while (*s) n += print(*s++); - return n; - } - private: - Prettyfier& operator=(const Prettyfier&); // cannot be assigned - bool inEmptyBlock() { - return _previousChar == '{' || _previousChar == '['; - } - size_t handleStringChar(char c) { - bool isQuote = c == '"' && _previousChar != '\\'; - if (isQuote) _inString = false; - return _sink.print(c); - } - size_t handleMarkupChar(char c) { - switch (c) { - case '{': - case '[': - return writeBlockOpen(c); - case '}': - case ']': - return writeBlockClose(c); - case ':': - return writeColon(); - case ',': - return writeComma(); - case '"': - return writeQuoteOpen(); - default: - return writeNormalChar(c); - } - } - size_t writeBlockClose(char c) { - size_t n = 0; - n += unindentIfNeeded(); - n += _sink.print(c); - return n; - } - size_t writeBlockOpen(char c) { - size_t n = 0; - n += indentIfNeeded(); - n += _sink.print(c); - return n; - } - size_t writeColon() { - size_t n = 0; - n += _sink.print(": "); - return n; - } - size_t writeComma() { - size_t n = 0; - n += _sink.print(",\r\n"); - return n; - } - size_t writeQuoteOpen() { - _inString = true; - size_t n = 0; - n += indentIfNeeded(); - n += _sink.print('"'); - return n; - } - size_t writeNormalChar(char c) { - size_t n = 0; - n += indentIfNeeded(); - n += _sink.print(c); - return n; - } - size_t indentIfNeeded() { - if (!inEmptyBlock()) return 0; - _sink.indent(); - return _sink.print("\r\n"); - } - size_t unindentIfNeeded() { - if (inEmptyBlock()) return 0; - _sink.unindent(); - return _sink.print("\r\n"); - } - char _previousChar; - IndentedPrint& _sink; - bool _inString; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -class StaticStringBuilder { - public: - StaticStringBuilder(char *buf, size_t size) : end(buf + size - 1), p(buf) { - *p = '\0'; - } - size_t print(char c) { - if (p >= end) return 0; - *p++ = c; - *p = '\0'; - return 1; - } - size_t print(const char *s) { - char *begin = p; - while (p < end && *s) *p++ = *s++; - *p = '\0'; - return size_t(p - begin); - } - private: - char *end; - char *p; -}; -} // namespace Internals -} // namespace ArduinoJson -#if ARDUINOJSON_ENABLE_STD_STREAM -#if ARDUINOJSON_ENABLE_STD_STREAM -#include -namespace ArduinoJson { -namespace Internals { -class StreamPrintAdapter { - public: - explicit StreamPrintAdapter(std::ostream& os) : _os(os) {} - size_t print(char c) { - _os << c; - return 1; - } - size_t print(const char* s) { - _os << s; - return strlen(s); - } - private: - StreamPrintAdapter& operator=(const StreamPrintAdapter&); - std::ostream& _os; -}; -} // namespace Internals -} // namespace ArduinoJson -#endif // ARDUINOJSON_ENABLE_STD_STREAM -#endif -namespace ArduinoJson { -namespace Internals { -template -class JsonPrintable { - public: - template - typename EnableIf::has_append, size_t>::type printTo( - Print &print) const { - JsonWriter writer(print); - JsonSerializer >::serialize(downcast(), writer); - return writer.bytesWritten(); - } -#if ARDUINOJSON_ENABLE_STD_STREAM - std::ostream &printTo(std::ostream &os) const { - StreamPrintAdapter adapter(os); - printTo(adapter); - return os; - } -#endif - size_t printTo(char *buffer, size_t bufferSize) const { - StaticStringBuilder sb(buffer, bufferSize); - return printTo(sb); - } - template - size_t printTo(char (&buffer)[N]) const { - return printTo(buffer, N); - } - template - typename EnableIf::has_append, size_t>::type printTo( - TString &str) const { - DynamicStringBuilder sb(str); - return printTo(sb); - } - template - size_t prettyPrintTo(IndentedPrint &print) const { - Prettyfier p(print); - return printTo(p); - } - size_t prettyPrintTo(char *buffer, size_t bufferSize) const { - StaticStringBuilder sb(buffer, bufferSize); - return prettyPrintTo(sb); - } - template - size_t prettyPrintTo(char (&buffer)[N]) const { - return prettyPrintTo(buffer, N); - } - template - typename EnableIf::has_append, size_t>::type - prettyPrintTo(Print &print) const { - IndentedPrint indentedPrint(print); - return prettyPrintTo(indentedPrint); - } - template - typename EnableIf::has_append, size_t>::type - prettyPrintTo(TString &str) const { - DynamicStringBuilder sb(str); - return prettyPrintTo(sb); - } - size_t measureLength() const { - DummyPrint dp; - return printTo(dp); - } - size_t measurePrettyLength() const { - DummyPrint dp; - return prettyPrintTo(dp); - } - private: - const T &downcast() const { - return *static_cast(this); - } -}; -#if ARDUINOJSON_ENABLE_STD_STREAM -template -inline std::ostream &operator<<(std::ostream &os, const JsonPrintable &v) { - return v.printTo(os); -} -#endif -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class JsonVariantBase : public JsonPrintable, - public JsonVariantCasts, - public JsonVariantComparisons, - public JsonVariantOr, - public JsonVariantSubscripts, - public JsonVariantTag {}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class RawJsonString { - public: - explicit RawJsonString(T str) : _str(str) {} - operator T() const { - return _str; - } - private: - T _str; -}; -template -struct StringTraits, void> { - static bool is_null(RawJsonString source) { - return StringTraits::is_null(static_cast(source)); - } - typedef RawJsonString duplicate_t; - template - static duplicate_t duplicate(RawJsonString source, Buffer* buffer) { - return duplicate_t(StringTraits::duplicate(source, buffer)); - } - static const bool has_append = false; - static const bool has_equals = false; - static const bool should_duplicate = StringTraits::should_duplicate; -}; -} // namespace Internals -template -inline Internals::RawJsonString RawJson(T str) { - return Internals::RawJsonString(str); -} -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct IsFloatingPoint { - static const bool value = IsSame::value || IsSame::value; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct RemoveConst { - typedef T type; -}; -template -struct RemoveConst { - typedef T type; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -class JsonArray; -class JsonObject; -class JsonVariant : public Internals::JsonVariantBase { - template - friend class Internals::JsonSerializer; - public: - JsonVariant() : _type(Internals::JSON_UNDEFINED) {} - JsonVariant(bool value) { - using namespace Internals; - _type = JSON_BOOLEAN; - _content.asInteger = static_cast(value); - } - template - JsonVariant(T value, typename Internals::EnableIf< - Internals::IsFloatingPoint::value>::type * = 0) { - using namespace Internals; - _type = JSON_FLOAT; - _content.asFloat = static_cast(value); - } - template - DEPRECATED("Second argument is not supported anymore") - JsonVariant(T value, uint8_t, - typename Internals::EnableIf< - Internals::IsFloatingPoint::value>::type * = 0) { - using namespace Internals; - _type = JSON_FLOAT; - _content.asFloat = static_cast(value); - } - template - JsonVariant( - T value, - typename Internals::EnableIf::value || - Internals::IsSame::value>::type * = - 0) { - using namespace Internals; - if (value >= 0) { - _type = JSON_POSITIVE_INTEGER; - _content.asInteger = static_cast(value); - } else { - _type = JSON_NEGATIVE_INTEGER; - _content.asInteger = static_cast(-value); - } - } - template - JsonVariant(T value, - typename Internals::EnableIf< - Internals::IsUnsignedIntegral::value>::type * = 0) { - using namespace Internals; - _type = JSON_POSITIVE_INTEGER; - _content.asInteger = static_cast(value); - } - template - JsonVariant( - const TChar *value, - typename Internals::EnableIf::value>::type * = - 0) { - _type = Internals::JSON_STRING; - _content.asString = reinterpret_cast(value); - } - JsonVariant(Internals::RawJsonString value) { - _type = Internals::JSON_UNPARSED; - _content.asString = value; - } - JsonVariant(const JsonArray &array); - JsonVariant(const JsonObject &object); - template - const typename Internals::EnableIf::value, T>::type - as() const { - return variantAsInteger(); - } - template - const typename Internals::EnableIf::value, T>::type - as() const { - return variantAsInteger() != 0; - } - template - const typename Internals::EnableIf::value, - T>::type - as() const { - return variantAsFloat(); - } - template - typename Internals::EnableIf::value || - Internals::IsSame::value, - const char *>::type - as() const { - return variantAsString(); - } - template - typename Internals::EnableIf::has_append, T>::type - as() const { - const char *cstr = variantAsString(); - if (cstr) return T(cstr); - T s; - printTo(s); - return s; - } - template - typename Internals::EnableIf< - Internals::IsSame::type, - JsonArray>::value, - JsonArray &>::type - as() const { - return variantAsArray(); - } - template - typename Internals::EnableIf< - Internals::IsSame::type, - const JsonArray>::value, - const JsonArray &>::type - as() const { - return variantAsArray(); - } - template - typename Internals::EnableIf< - Internals::IsSame::type, - JsonObject>::value, - JsonObject &>::type - as() const { - return variantAsObject(); - } - template - typename Internals::EnableIf< - Internals::IsSame::type, - const JsonObject>::value, - const JsonObject &>::type - as() const { - return variantAsObject(); - } - template - typename Internals::EnableIf::value, - T>::type - as() const { - return *this; - } - template - typename Internals::EnableIf::value, bool>::type is() - const { - return variantIsInteger(); - } - template - typename Internals::EnableIf::value, bool>::type - is() const { - return variantIsFloat(); - } - template - typename Internals::EnableIf::value, bool>::type - is() const { - return variantIsBoolean(); - } - template - typename Internals::EnableIf::value || - Internals::IsSame::value || - Internals::StringTraits::has_append, - bool>::type - is() const { - return variantIsString(); - } - template - typename Internals::EnableIf< - Internals::IsSame::type>::type, - JsonArray>::value, - bool>::type - is() const { - return variantIsArray(); - } - template - typename Internals::EnableIf< - Internals::IsSame::type>::type, - JsonObject>::value, - bool>::type - is() const { - return variantIsObject(); - } - bool success() const { - return _type != Internals::JSON_UNDEFINED; - } - private: - JsonArray &variantAsArray() const; - JsonObject &variantAsObject() const; - const char *variantAsString() const; - template - T variantAsFloat() const; - template - T variantAsInteger() const; - bool variantIsBoolean() const; - bool variantIsFloat() const; - bool variantIsInteger() const; - bool variantIsArray() const { - return _type == Internals::JSON_ARRAY; - } - bool variantIsObject() const { - return _type == Internals::JSON_OBJECT; - } - bool variantIsString() const { - return _type == Internals::JSON_STRING || - (_type == Internals::JSON_UNPARSED && _content.asString && - !strcmp("null", _content.asString)); - } - Internals::JsonVariantType _type; - Internals::JsonVariantContent _content; -}; -DEPRECATED("Decimal places are ignored, use the float value instead") -inline JsonVariant float_with_n_digits(float value, uint8_t) { - return JsonVariant(value); -} -DEPRECATED("Decimal places are ignored, use the double value instead") -inline JsonVariant double_with_n_digits(double value, uint8_t) { - return JsonVariant(value); -} -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct IsArray { - static const bool value = false; -}; -template -struct IsArray { - static const bool value = true; -}; -template -struct IsArray { - static const bool value = true; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -class JsonArray; -class JsonObject; -class JsonBuffer : Internals::NonCopyable { - public: - JsonArray &createArray(); - JsonObject &createObject(); - template - DEPRECATED("char* are duplicated, you don't need strdup() anymore") - typename Internals::EnableIf::value, - const char *>::type strdup(const TString &src) { - return Internals::StringTraits::duplicate(src, this); - } - template - DEPRECATED("char* are duplicated, you don't need strdup() anymore") - const char *strdup(TString *src) { - return Internals::StringTraits::duplicate(src, this); - } - virtual void *alloc(size_t size) = 0; - protected: - ~JsonBuffer() {} - static FORCE_INLINE size_t round_size_up(size_t bytes) { -#if ARDUINOJSON_ENABLE_ALIGNMENT - const size_t x = sizeof(void *) - 1; - return (bytes + x) & ~x; -#else - return bytes; -#endif - } -}; -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class StringWriter { - public: - class String { - public: - String(TChar** ptr) : _writePtr(ptr), _startPtr(*ptr) {} - void append(char c) { - *(*_writePtr)++ = TChar(c); - } - const char* c_str() const { - *(*_writePtr)++ = 0; - return reinterpret_cast(_startPtr); - } - private: - TChar** _writePtr; - TChar* _startPtr; - }; - StringWriter(TChar* buffer) : _ptr(buffer) {} - String startString() { - return String(&_ptr); - } - private: - TChar* _ptr; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class JsonParser { - public: - JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer, - uint8_t nestingLimit) - : _buffer(buffer), - _reader(reader), - _writer(writer), - _nestingLimit(nestingLimit) {} - JsonArray &parseArray(); - JsonObject &parseObject(); - JsonVariant parseVariant() { - JsonVariant result; - parseAnythingTo(&result); - return result; - } - private: - JsonParser &operator=(const JsonParser &); // non-copiable - static bool eat(TReader &, char charToSkip); - FORCE_INLINE bool eat(char charToSkip) { - return eat(_reader, charToSkip); - } - const char *parseString(); - bool parseAnythingTo(JsonVariant *destination); - inline bool parseArrayTo(JsonVariant *destination); - inline bool parseObjectTo(JsonVariant *destination); - inline bool parseStringTo(JsonVariant *destination); - static inline bool isBetween(char c, char min, char max) { - return min <= c && c <= max; - } - static inline bool canBeInNonQuotedString(char c) { - return isBetween(c, '0', '9') || isBetween(c, '_', 'z') || - isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.'; - } - static inline bool isQuote(char c) { - return c == '\'' || c == '\"'; - } - JsonBuffer *_buffer; - TReader _reader; - TWriter _writer; - uint8_t _nestingLimit; -}; -template -struct JsonParserBuilder { - typedef typename StringTraits::Reader InputReader; - typedef JsonParser TParser; - static TParser makeParser(TJsonBuffer *buffer, TString &json, - uint8_t nestingLimit) { - return TParser(buffer, InputReader(json), *buffer, nestingLimit); - } -}; -template -struct JsonParserBuilder::value>::type> { - typedef typename StringTraits::Reader TReader; - typedef StringWriter TWriter; - typedef JsonParser TParser; - static TParser makeParser(TJsonBuffer *buffer, TChar *json, - uint8_t nestingLimit) { - return TParser(buffer, TReader(json), TWriter(json), nestingLimit); - } -}; -template -inline typename JsonParserBuilder::TParser makeParser( - TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) { - return JsonParserBuilder::makeParser(buffer, json, - nestingLimit); -} -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class JsonBufferBase : public JsonBuffer { - public: - template - typename Internals::EnableIf::value, - JsonArray &>::type - parseArray(const TString &json, - uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { - return Internals::makeParser(that(), json, nestingLimit).parseArray(); - } - template - JsonArray &parseArray( - TString *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { - return Internals::makeParser(that(), json, nestingLimit).parseArray(); - } - template - JsonArray &parseArray( - TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { - return Internals::makeParser(that(), json, nestingLimit).parseArray(); - } - template - typename Internals::EnableIf::value, - JsonObject &>::type - parseObject(const TString &json, - uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { - return Internals::makeParser(that(), json, nestingLimit).parseObject(); - } - template - JsonObject &parseObject( - TString *json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { - return Internals::makeParser(that(), json, nestingLimit).parseObject(); - } - template - JsonObject &parseObject( - TString &json, uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { - return Internals::makeParser(that(), json, nestingLimit).parseObject(); - } - template - typename Internals::EnableIf::value, - JsonVariant>::type - parse(const TString &json, - uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { - return Internals::makeParser(that(), json, nestingLimit).parseVariant(); - } - template - JsonVariant parse(TString *json, - uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { - return Internals::makeParser(that(), json, nestingLimit).parseVariant(); - } - template - JsonVariant parse(TString &json, - uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { - return Internals::makeParser(that(), json, nestingLimit).parseVariant(); - } - protected: - ~JsonBufferBase() {} - private: - TDerived *that() { - return static_cast(this); - } -}; -} // namespace Internals -} // namespace ArduinoJson -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnon-virtual-dtor" -#elif defined(__GNUC__) -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#pragma GCC diagnostic push -#endif -#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" -#endif -namespace ArduinoJson { -namespace Internals { -class DefaultAllocator { - public: - void* allocate(size_t size) { - return malloc(size); - } - void deallocate(void* pointer) { - free(pointer); - } -}; -template -class DynamicJsonBufferBase - : public JsonBufferBase > { - struct Block; - struct EmptyBlock { - Block* next; - size_t capacity; - size_t size; - }; - struct Block : EmptyBlock { - uint8_t data[1]; - }; - public: - enum { EmptyBlockSize = sizeof(EmptyBlock) }; - DynamicJsonBufferBase(size_t initialSize = 256) - : _head(NULL), _nextBlockCapacity(initialSize) {} - ~DynamicJsonBufferBase() { - clear(); - } - size_t size() const { - size_t total = 0; - for (const Block* b = _head; b; b = b->next) total += b->size; - return total; - } - virtual void* alloc(size_t bytes) { - alignNextAlloc(); - return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes); - } - void clear() { - Block* currentBlock = _head; - while (currentBlock != NULL) { - _nextBlockCapacity = currentBlock->capacity; - Block* nextBlock = currentBlock->next; - _allocator.deallocate(currentBlock); - currentBlock = nextBlock; - } - _head = 0; - } - class String { - public: - String(DynamicJsonBufferBase* parent) - : _parent(parent), _start(NULL), _length(0) {} - void append(char c) { - if (_parent->canAllocInHead(1)) { - char* end = static_cast(_parent->allocInHead(1)); - *end = c; - if (_length == 0) _start = end; - } else { - char* newStart = - static_cast(_parent->allocInNewBlock(_length + 1)); - if (_start && newStart) memcpy(newStart, _start, _length); - if (newStart) newStart[_length] = c; - _start = newStart; - } - _length++; - } - const char* c_str() { - append(0); - return _start; - } - private: - DynamicJsonBufferBase* _parent; - char* _start; - size_t _length; - }; - String startString() { - return String(this); - } - private: - void alignNextAlloc() { - if (_head) _head->size = this->round_size_up(_head->size); - } - bool canAllocInHead(size_t bytes) const { - return _head != NULL && _head->size + bytes <= _head->capacity; - } - void* allocInHead(size_t bytes) { - void* p = _head->data + _head->size; - _head->size += bytes; - return p; - } - void* allocInNewBlock(size_t bytes) { - size_t capacity = _nextBlockCapacity; - if (bytes > capacity) capacity = bytes; - if (!addNewBlock(capacity)) return NULL; - _nextBlockCapacity *= 2; - return allocInHead(bytes); - } - bool addNewBlock(size_t capacity) { - size_t bytes = EmptyBlockSize + capacity; - Block* block = static_cast(_allocator.allocate(bytes)); - if (block == NULL) return false; - block->capacity = capacity; - block->size = 0; - block->next = _head; - _head = block; - return true; - } - TAllocator _allocator; - Block* _head; - size_t _nextBlockCapacity; -}; -} // namespace Internals -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#pragma GCC diagnostic pop -#endif -#endif -typedef Internals::DynamicJsonBufferBase - DynamicJsonBuffer; -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -class JsonBufferAllocated { - public: - void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() { - if (!jsonBuffer) return NULL; - return jsonBuffer->alloc(n); - } - void operator delete(void *, JsonBuffer *)throw(); -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct ListNode : public Internals::JsonBufferAllocated { - ListNode() throw() : next(NULL) {} - ListNode *next; - T content; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class ListConstIterator { - public: - explicit ListConstIterator(const ListNode *node = NULL) : _node(node) {} - const T &operator*() const { - return _node->content; - } - const T *operator->() { - return &_node->content; - } - bool operator==(const ListConstIterator &other) const { - return _node == other._node; - } - bool operator!=(const ListConstIterator &other) const { - return _node != other._node; - } - ListConstIterator &operator++() { - if (_node) _node = _node->next; - return *this; - } - ListConstIterator &operator+=(size_t distance) { - while (_node && distance) { - _node = _node->next; - --distance; - } - return *this; - } - private: - const ListNode *_node; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class List; -template -class ListIterator { - friend class List; - public: - explicit ListIterator(ListNode *node = NULL) : _node(node) {} - T &operator*() const { - return _node->content; - } - T *operator->() { - return &_node->content; - } - bool operator==(const ListIterator &other) const { - return _node == other._node; - } - bool operator!=(const ListIterator &other) const { - return _node != other._node; - } - ListIterator &operator++() { - if (_node) _node = _node->next; - return *this; - } - ListIterator &operator+=(size_t distance) { - while (_node && distance) { - _node = _node->next; - --distance; - } - return *this; - } - operator ListConstIterator() const { - return ListConstIterator(_node); - } - private: - ListNode *_node; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -class List { - public: - typedef T value_type; - typedef ListNode node_type; - typedef ListIterator iterator; - typedef ListConstIterator const_iterator; - explicit List(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {} - bool success() const { - return _buffer != NULL; - } - size_t size() const { - size_t nodeCount = 0; - for (node_type *node = _firstNode; node; node = node->next) nodeCount++; - return nodeCount; - } - iterator add() { - node_type *newNode = new (_buffer) node_type(); - if (_firstNode) { - node_type *lastNode = _firstNode; - while (lastNode->next) lastNode = lastNode->next; - lastNode->next = newNode; - } else { - _firstNode = newNode; - } - return iterator(newNode); - } - iterator begin() { - return iterator(_firstNode); - } - iterator end() { - return iterator(NULL); - } - const_iterator begin() const { - return const_iterator(_firstNode); - } - const_iterator end() const { - return const_iterator(NULL); - } - void remove(iterator it) { - node_type *nodeToRemove = it._node; - if (!nodeToRemove) return; - if (nodeToRemove == _firstNode) { - _firstNode = nodeToRemove->next; - } else { - for (node_type *node = _firstNode; node; node = node->next) - if (node->next == nodeToRemove) node->next = nodeToRemove->next; - } - } - protected: - JsonBuffer *_buffer; - private: - node_type *_firstNode; -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -class ReferenceType { - public: - bool operator==(const ReferenceType& other) const { - return this == &other; - } - bool operator!=(const ReferenceType& other) const { - return this != &other; - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -struct ValueSaver { - template - static bool save(JsonBuffer*, Destination& destination, Source source) { - destination = source; - return true; - } -}; -template -struct ValueSaver< - Source, typename EnableIf::should_duplicate>::type> { - template - static bool save(JsonBuffer* buffer, Destination& dest, Source source) { - if (!StringTraits::is_null(source)) { - typename StringTraits::duplicate_t dup = - StringTraits::duplicate(source, buffer); - if (!dup) return false; - dest = dup; - } else { - dest = reinterpret_cast(0); - } - return true; - } -}; -template -struct ValueSaver< - Char*, typename EnableIf::should_duplicate>::type> { - template - static bool save(JsonBuffer*, Destination& dest, Char* source) { - dest = reinterpret_cast(source); - return true; - } -}; -} // namespace Internals -} // namespace ArduinoJson -#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \ - (sizeof(JsonArray) + (NUMBER_OF_ELEMENTS) * sizeof(JsonArray::node_type)) -namespace ArduinoJson { -class JsonObject; -class JsonBuffer; -namespace Internals { -class JsonArraySubscript; -} -class JsonArray : public Internals::JsonPrintable, - public Internals::ReferenceType, - public Internals::NonCopyable, - public Internals::List, - public Internals::JsonBufferAllocated { - public: - explicit JsonArray(JsonBuffer *buffer) throw() - : Internals::List(buffer) {} - const Internals::JsonArraySubscript operator[](size_t index) const; - Internals::JsonArraySubscript operator[](size_t index); - template - bool add(const T &value) { - return add_impl(value); - } - template - bool add(T *value) { - return add_impl(value); - } - template - DEPRECATED("Second argument is not supported anymore") - bool add(T value, uint8_t) { - return add_impl(JsonVariant(value)); - } - template - bool set(size_t index, const T &value) { - return set_impl(index, value); - } - template - bool set(size_t index, T *value) { - return set_impl(index, value); - } - template - typename Internals::EnableIf::value, bool>::type - set(size_t index, T value, uint8_t decimals) { - return set_impl(index, JsonVariant(value, decimals)); - } - template - typename Internals::JsonVariantAs::type get(size_t index) const { - const_iterator it = begin() += index; - return it != end() ? it->as() : Internals::JsonVariantDefault::get(); - } - template - bool is(size_t index) const { - const_iterator it = begin() += index; - return it != end() ? it->is() : false; - } - JsonArray &createNestedArray(); - JsonObject &createNestedObject(); - void remove(size_t index) { - remove(begin() += index); - } - using Internals::List::remove; - static JsonArray &invalid() { - static JsonArray instance(NULL); - return instance; - } - template - bool copyFrom(T (&array)[N]) { - return copyFrom(array, N); - } - template - bool copyFrom(T *array, size_t len) { - bool ok = true; - for (size_t i = 0; i < len; i++) { - ok &= add(array[i]); - } - return ok; - } - template - bool copyFrom(T (&array)[N1][N2]) { - bool ok = true; - for (size_t i = 0; i < N1; i++) { - JsonArray &nestedArray = createNestedArray(); - for (size_t j = 0; j < N2; j++) { - ok &= nestedArray.add(array[i][j]); - } - } - return ok; - } - template - size_t copyTo(T (&array)[N]) const { - return copyTo(array, N); - } - template - size_t copyTo(T *array, size_t len) const { - size_t i = 0; - for (const_iterator it = begin(); it != end() && i < len; ++it) - array[i++] = *it; - return i; - } - template - void copyTo(T (&array)[N1][N2]) const { - size_t i = 0; - for (const_iterator it = begin(); it != end() && i < N1; ++it) { - it->as().copyTo(array[i++]); - } - } -#if ARDUINOJSON_ENABLE_DEPRECATED - DEPRECATED("use remove() instead") - FORCE_INLINE void removeAt(size_t index) { - return remove(index); - } -#endif - private: - template - bool set_impl(size_t index, TValueRef value) { - iterator it = begin() += index; - if (it == end()) return false; - return Internals::ValueSaver::save(_buffer, *it, value); - } - template - bool add_impl(TValueRef value) { - iterator it = Internals::List::add(); - if (it == end()) return false; - return Internals::ValueSaver::save(_buffer, *it, value); - } -}; -namespace Internals { -template <> -struct JsonVariantDefault { - static JsonArray &get() { - return JsonArray::invalid(); - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -struct JsonPair { - const char* key; - JsonVariant value; -}; -} // namespace ArduinoJson -#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \ - (sizeof(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type)) -namespace ArduinoJson { -class JsonArray; -class JsonBuffer; -namespace Internals { -template -class JsonObjectSubscript; -} -class JsonObject : public Internals::JsonPrintable, - public Internals::ReferenceType, - public Internals::NonCopyable, - public Internals::List, - public Internals::JsonBufferAllocated { - public: - explicit JsonObject(JsonBuffer* buffer) throw() - : Internals::List(buffer) {} - template - Internals::JsonObjectSubscript operator[]( - const TString& key) { - return Internals::JsonObjectSubscript(*this, key); - } - template - Internals::JsonObjectSubscript operator[](TString* key) { - return Internals::JsonObjectSubscript(*this, key); - } - template - const Internals::JsonObjectSubscript operator[]( - const TString& key) const { - return Internals::JsonObjectSubscript( - *const_cast(this), key); - } - template - const Internals::JsonObjectSubscript operator[]( - TString* key) const { - return Internals::JsonObjectSubscript( - *const_cast(this), key); - } - template - bool set(const TString& key, const TValue& value) { - return set_impl(key, value); - } - template - bool set(const TString& key, TValue* value) { - return set_impl(key, value); - } - template - bool set(TString* key, const TValue& value) { - return set_impl(key, value); - } - template - bool set(TString* key, TValue* value) { - return set_impl(key, value); - } - template - DEPRECATED("Second argument is not supported anymore") - typename Internals::EnableIf::value, - bool>::type - set(const TString& key, TValue value, uint8_t) { - return set_impl(key, - JsonVariant(value)); - } - template - DEPRECATED("Second argument is not supported anymore") - typename Internals::EnableIf::value, - bool>::type - set(TString* key, TValue value, uint8_t) { - return set_impl(key, JsonVariant(value)); - } - template - typename Internals::JsonVariantAs::type get( - const TString& key) const { - return get_impl(key); - } - template - typename Internals::JsonVariantAs::type get(TString* key) const { - return get_impl(key); - } - template - bool is(const TString& key) const { - return is_impl(key); - } - template - bool is(TString* key) const { - return is_impl(key); - } - template - JsonArray& createNestedArray(const TString& key) { - return createNestedArray_impl(key); - } - template - JsonArray& createNestedArray(TString* key) { - return createNestedArray_impl(key); - } - template - JsonObject& createNestedObject(const TString& key) { - return createNestedObject_impl(key); - } - template - JsonObject& createNestedObject(TString* key) { - return createNestedObject_impl(key); - } - template - bool containsKey(const TString& key) const { - return findKey(key) != end(); - } - template - bool containsKey(TString* key) const { - return findKey(key) != end(); - } - template - void remove(const TString& key) { - remove(findKey(key)); - } - template - void remove(TString* key) { - remove(findKey(key)); - } - using Internals::List::remove; - static JsonObject& invalid() { - static JsonObject instance(NULL); - return instance; - } - private: - template - iterator findKey(TStringRef key) { - iterator it; - for (it = begin(); it != end(); ++it) { - if (Internals::StringTraits::equals(key, it->key)) break; - } - return it; - } - template - const_iterator findKey(TStringRef key) const { - return const_cast(this)->findKey(key); - } - template - typename Internals::JsonVariantAs::type get_impl( - TStringRef key) const { - const_iterator it = findKey(key); - return it != end() ? it->value.as() - : Internals::JsonVariantDefault::get(); - } - template - bool set_impl(TStringRef key, TValueRef value) { - if (Internals::StringTraits::is_null(key)) return false; - iterator it = findKey(key); - if (it == end()) { - it = Internals::List::add(); - if (it == end()) return false; - bool key_ok = - Internals::ValueSaver::save(_buffer, it->key, key); - if (!key_ok) return false; - } - return Internals::ValueSaver::save(_buffer, it->value, value); - } - template - bool is_impl(TStringRef key) const { - const_iterator it = findKey(key); - return it != end() ? it->value.is() : false; - } - template - JsonArray& createNestedArray_impl(TStringRef key); - template - JsonObject& createNestedObject_impl(TStringRef key); -}; -namespace Internals { -template <> -struct JsonVariantDefault { - static JsonObject& get() { - return JsonObject::invalid(); - } -}; -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -class StaticJsonBufferBase : public JsonBufferBase { - public: - class String { - public: - String(StaticJsonBufferBase* parent) : _parent(parent) { - _start = parent->_buffer + parent->_size; - } - void append(char c) { - if (_parent->canAlloc(1)) { - char* last = static_cast(_parent->doAlloc(1)); - *last = c; - } - } - const char* c_str() const { - if (_parent->canAlloc(1)) { - char* last = static_cast(_parent->doAlloc(1)); - *last = '\0'; - return _start; - } else { - return NULL; - } - } - private: - StaticJsonBufferBase* _parent; - char* _start; - }; - StaticJsonBufferBase(char* buffer, size_t capa) - : _buffer(buffer), _capacity(capa), _size(0) {} - size_t capacity() const { - return _capacity; - } - size_t size() const { - return _size; - } - virtual void* alloc(size_t bytes) { - alignNextAlloc(); - if (!canAlloc(bytes)) return NULL; - return doAlloc(bytes); - } - void clear() { - _size = 0; - } - String startString() { - return String(this); - } - protected: - ~StaticJsonBufferBase() {} - private: - void alignNextAlloc() { - _size = round_size_up(_size); - } - bool canAlloc(size_t bytes) const { - return _size + bytes <= _capacity; - } - void* doAlloc(size_t bytes) { - void* p = &_buffer[_size]; - _size += bytes; - return p; - } - char* _buffer; - size_t _capacity; - size_t _size; -}; -} // namespace Internals -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnon-virtual-dtor" -#elif defined(__GNUC__) -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#pragma GCC diagnostic push -#endif -#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" -#endif -template -class StaticJsonBuffer : public Internals::StaticJsonBufferBase { - public: - explicit StaticJsonBuffer() - : Internals::StaticJsonBufferBase(_buffer, CAPACITY) {} - private: - char _buffer[CAPACITY]; -}; -} // namespace ArduinoJson -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#pragma GCC diagnostic pop -#endif -#endif -namespace ArduinoJson { -namespace Internals { -template -void skipSpacesAndComments(TInput& input) { - for (;;) { - switch (input.current()) { - case ' ': - case '\t': - case '\r': - case '\n': - input.move(); - continue; - case '/': - switch (input.next()) { - case '*': - input.move(); // skip '/' - for (;;) { - input.move(); - if (input.current() == '\0') return; - if (input.current() == '*' && input.next() == '/') { - input.move(); // skip '*' - input.move(); // skip '/' - break; - } - } - break; - case '/': - for (;;) { - input.move(); - if (input.current() == '\0') return; - if (input.current() == '\n') break; - } - break; - default: - return; - } - break; - default: - return; - } - } -} -} // namespace Internals -} // namespace ArduinoJson -template -inline bool ArduinoJson::Internals::JsonParser::eat( - TReader &reader, char charToSkip) { - skipSpacesAndComments(reader); - if (reader.current() != charToSkip) return false; - reader.move(); - return true; -} -template -inline bool -ArduinoJson::Internals::JsonParser::parseAnythingTo( - JsonVariant *destination) { - skipSpacesAndComments(_reader); - switch (_reader.current()) { - case '[': - return parseArrayTo(destination); - case '{': - return parseObjectTo(destination); - default: - return parseStringTo(destination); - } -} -template -inline ArduinoJson::JsonArray & -ArduinoJson::Internals::JsonParser::parseArray() { - if (_nestingLimit == 0) return JsonArray::invalid(); - _nestingLimit--; - JsonArray &array = _buffer->createArray(); - if (!eat('[')) goto ERROR_MISSING_BRACKET; - if (eat(']')) goto SUCCESS_EMPTY_ARRAY; - for (;;) { - JsonVariant value; - if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE; - if (!array.add(value)) goto ERROR_NO_MEMORY; - if (eat(']')) goto SUCCES_NON_EMPTY_ARRAY; - if (!eat(',')) goto ERROR_MISSING_COMMA; - } -SUCCESS_EMPTY_ARRAY: -SUCCES_NON_EMPTY_ARRAY: - _nestingLimit++; - return array; -ERROR_INVALID_VALUE: -ERROR_MISSING_BRACKET: -ERROR_MISSING_COMMA: -ERROR_NO_MEMORY: - return JsonArray::invalid(); -} -template -inline bool ArduinoJson::Internals::JsonParser::parseArrayTo( - JsonVariant *destination) { - JsonArray &array = parseArray(); - if (!array.success()) return false; - *destination = array; - return true; -} -template -inline ArduinoJson::JsonObject & -ArduinoJson::Internals::JsonParser::parseObject() { - if (_nestingLimit == 0) return JsonObject::invalid(); - _nestingLimit--; - JsonObject &object = _buffer->createObject(); - if (!eat('{')) goto ERROR_MISSING_BRACE; - if (eat('}')) goto SUCCESS_EMPTY_OBJECT; - for (;;) { - const char *key = parseString(); - if (!key) goto ERROR_INVALID_KEY; - if (!eat(':')) goto ERROR_MISSING_COLON; - JsonVariant value; - if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE; - if (!object.set(key, value)) goto ERROR_NO_MEMORY; - if (eat('}')) goto SUCCESS_NON_EMPTY_OBJECT; - if (!eat(',')) goto ERROR_MISSING_COMMA; - } -SUCCESS_EMPTY_OBJECT: -SUCCESS_NON_EMPTY_OBJECT: - _nestingLimit++; - return object; -ERROR_INVALID_KEY: -ERROR_INVALID_VALUE: -ERROR_MISSING_BRACE: -ERROR_MISSING_COLON: -ERROR_MISSING_COMMA: -ERROR_NO_MEMORY: - return JsonObject::invalid(); -} -template -inline bool ArduinoJson::Internals::JsonParser::parseObjectTo( - JsonVariant *destination) { - JsonObject &object = parseObject(); - if (!object.success()) return false; - *destination = object; - return true; -} -template -inline const char * -ArduinoJson::Internals::JsonParser::parseString() { - typename RemoveReference::type::String str = _writer.startString(); - skipSpacesAndComments(_reader); - char c = _reader.current(); - if (isQuote(c)) { // quotes - _reader.move(); - char stopChar = c; - for (;;) { - c = _reader.current(); - if (c == '\0') break; - _reader.move(); - if (c == stopChar) break; - if (c == '\\') { - c = Encoding::unescapeChar(_reader.current()); - if (c == '\0') break; - _reader.move(); - } - str.append(c); - } - } else { // no quotes - for (;;) { - if (!canBeInNonQuotedString(c)) break; - _reader.move(); - str.append(c); - c = _reader.current(); - } - } - return str.c_str(); -} -template -inline bool ArduinoJson::Internals::JsonParser::parseStringTo( - JsonVariant *destination) { - bool hasQuotes = isQuote(_reader.current()); - const char *value = parseString(); - if (value == NULL) return false; - if (hasQuotes) { - *destination = value; - } else { - *destination = RawJson(value); - } - return true; -} -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4522) -#endif -namespace ArduinoJson { -namespace Internals { -class JsonArraySubscript : public JsonVariantBase { - public: - FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index) - : _array(array), _index(index) {} - FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) { - _array.set(_index, src); - return *this; - } - template - FORCE_INLINE JsonArraySubscript& operator=(const T& src) { - _array.set(_index, src); - return *this; - } - template - FORCE_INLINE JsonArraySubscript& operator=(T* src) { - _array.set(_index, src); - return *this; - } - FORCE_INLINE bool success() const { - return _index < _array.size(); - } - template - FORCE_INLINE typename JsonVariantAs::type as() const { - return _array.get(_index); - } - template - FORCE_INLINE bool is() const { - return _array.is(_index); - } - template - FORCE_INLINE bool set(const TValue& value) { - return _array.set(_index, value); - } - template - FORCE_INLINE bool set(TValue* value) { - return _array.set(_index, value); - } - template - DEPRECATED("Second argument is not supported anymore") - FORCE_INLINE bool set(const TValue& value, uint8_t) { - return _array.set(_index, value); - } - private: - JsonArray& _array; - const size_t _index; -}; -template -inline JsonArraySubscript JsonVariantSubscripts::operator[]( - size_t index) { - return impl()->template as()[index]; -} -template -inline const JsonArraySubscript JsonVariantSubscripts::operator[]( - size_t index) const { - return impl()->template as()[index]; -} -#if ARDUINOJSON_ENABLE_STD_STREAM -inline std::ostream& operator<<(std::ostream& os, - const JsonArraySubscript& source) { - return source.printTo(os); -} -#endif -} // namespace Internals -inline Internals::JsonArraySubscript JsonArray::operator[](size_t index) { - return Internals::JsonArraySubscript(*this, index); -} -inline const Internals::JsonArraySubscript JsonArray::operator[]( - size_t index) const { - return Internals::JsonArraySubscript(*const_cast(this), index); -} -} // namespace ArduinoJson -#ifdef _MSC_VER -#pragma warning(pop) -#endif -namespace ArduinoJson { -inline JsonArray &JsonArray::createNestedArray() { - if (!_buffer) return JsonArray::invalid(); - JsonArray &array = _buffer->createArray(); - add(array); - return array; -} -inline JsonObject &JsonArray::createNestedObject() { - if (!_buffer) return JsonObject::invalid(); - JsonObject &object = _buffer->createObject(); - add(object); - return object; -} -} // namespace ArduinoJson -inline ArduinoJson::JsonArray &ArduinoJson::JsonBuffer::createArray() { - JsonArray *ptr = new (this) JsonArray(this); - return ptr ? *ptr : JsonArray::invalid(); -} -inline ArduinoJson::JsonObject &ArduinoJson::JsonBuffer::createObject() { - JsonObject *ptr = new (this) JsonObject(this); - return ptr ? *ptr : JsonObject::invalid(); -} -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4522) -#endif -namespace ArduinoJson { -namespace Internals { -template -class JsonObjectSubscript - : public JsonVariantBase > { - typedef JsonObjectSubscript this_type; - public: - FORCE_INLINE JsonObjectSubscript(JsonObject& object, TStringRef key) - : _object(object), _key(key) {} - FORCE_INLINE this_type& operator=(const this_type& src) { - _object.set(_key, src); - return *this; - } - template - FORCE_INLINE typename EnableIf::value, this_type&>::type - operator=(const TValue& src) { - _object.set(_key, src); - return *this; - } - template - FORCE_INLINE this_type& operator=(TValue* src) { - _object.set(_key, src); - return *this; - } - FORCE_INLINE bool success() const { - return _object.containsKey(_key); - } - template - FORCE_INLINE typename JsonVariantAs::type as() const { - return _object.get(_key); - } - template - FORCE_INLINE bool is() const { - return _object.is(_key); - } - template - FORCE_INLINE typename EnableIf::value, bool>::type set( - const TValue& value) { - return _object.set(_key, value); - } - template - FORCE_INLINE bool set(const TValue* value) { - return _object.set(_key, value); - } - template - DEPRECATED("Second argument is not supported anymore") - FORCE_INLINE bool set(const TValue& value, uint8_t) { - return _object.set(_key, value); - } - private: - JsonObject& _object; - TStringRef _key; -}; -#if ARDUINOJSON_ENABLE_STD_STREAM -template -inline std::ostream& operator<<(std::ostream& os, - const JsonObjectSubscript& source) { - return source.printTo(os); -} -#endif -} // namespace Internals -} // namespace ArduinoJson -#ifdef _MSC_VER -#pragma warning(pop) -#endif -namespace ArduinoJson { -template -inline JsonArray &JsonObject::createNestedArray_impl(TStringRef key) { - if (!_buffer) return JsonArray::invalid(); - JsonArray &array = _buffer->createArray(); - set(key, array); - return array; -} -template -inline JsonObject &JsonObject::createNestedObject_impl(TStringRef key) { - if (!_buffer) return JsonObject::invalid(); - JsonObject &object = _buffer->createObject(); - set(key, object); - return object; -} -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -inline bool isdigit(char c) { - return '0' <= c && c <= '9'; -} -inline bool issign(char c) { - return '-' == c || c == '+'; -} -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -inline bool isFloat(const char* s) { - if (!s) return false; - if (!strcmp(s, "NaN")) return true; - if (issign(*s)) s++; - if (!strcmp(s, "Infinity")) return true; - if (*s == '\0') return false; - while (isdigit(*s)) s++; - if (*s == '.') { - s++; - while (isdigit(*s)) s++; - } - if (*s == 'e' || *s == 'E') { - s++; - if (issign(*s)) s++; - if (!isdigit(*s)) return false; - while (isdigit(*s)) s++; - } - return *s == '\0'; -} -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -inline bool isInteger(const char* s) { - if (!s || !*s) return false; - if (issign(*s)) s++; - while (isdigit(*s)) s++; - return *s == '\0'; -} -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -inline T parseFloat(const char* s) { - typedef FloatTraits traits; - typedef typename traits::mantissa_type mantissa_t; - typedef typename traits::exponent_type exponent_t; - if (!s) return 0; // NULL - bool negative_result = false; - switch (*s) { - case '-': - negative_result = true; - s++; - break; - case '+': - s++; - break; - } - if (*s == 't') return 1; // true - if (*s == 'n' || *s == 'N') return traits::nan(); - if (*s == 'i' || *s == 'I') - return negative_result ? -traits::inf() : traits::inf(); - mantissa_t mantissa = 0; - exponent_t exponent_offset = 0; - while (isdigit(*s)) { - if (mantissa < traits::mantissa_max / 10) - mantissa = mantissa * 10 + (*s - '0'); - else - exponent_offset++; - s++; - } - if (*s == '.') { - s++; - while (isdigit(*s)) { - if (mantissa < traits::mantissa_max / 10) { - mantissa = mantissa * 10 + (*s - '0'); - exponent_offset--; - } - s++; - } - } - int exponent = 0; - if (*s == 'e' || *s == 'E') { - s++; - bool negative_exponent = false; - if (*s == '-') { - negative_exponent = true; - s++; - } else if (*s == '+') { - s++; - } - while (isdigit(*s)) { - exponent = exponent * 10 + (*s - '0'); - if (exponent + exponent_offset > traits::exponent_max) { - if (negative_exponent) - return negative_result ? -0.0f : 0.0f; - else - return negative_result ? -traits::inf() : traits::inf(); - } - s++; - } - if (negative_exponent) exponent = -exponent; - } - exponent += exponent_offset; - T result = traits::make_float(static_cast(mantissa), exponent); - return negative_result ? -result : result; -} -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -namespace Internals { -template -T parseInteger(const char *s) { - if (!s) return 0; // NULL - if (*s == 't') return 1; // "true" - T result = 0; - bool negative_result = false; - switch (*s) { - case '-': - negative_result = true; - s++; - break; - case '+': - s++; - break; - } - while (isdigit(*s)) { - result = T(result * 10 + T(*s - '0')); - s++; - } - return negative_result ? T(~result + 1) : result; -} -} // namespace Internals -} // namespace ArduinoJson -namespace ArduinoJson { -inline JsonVariant::JsonVariant(const JsonArray &array) { - if (array.success()) { - _type = Internals::JSON_ARRAY; - _content.asArray = const_cast(&array); - } else { - _type = Internals::JSON_UNDEFINED; - _content.asArray = 0; // <- prevent warning 'maybe-uninitialized' - } -} -inline JsonVariant::JsonVariant(const JsonObject &object) { - if (object.success()) { - _type = Internals::JSON_OBJECT; - _content.asObject = const_cast(&object); - } else { - _type = Internals::JSON_UNDEFINED; - _content.asObject = 0; // <- prevent warning 'maybe-uninitialized' - } -} -inline JsonArray &JsonVariant::variantAsArray() const { - if (_type == Internals::JSON_ARRAY) return *_content.asArray; - return JsonArray::invalid(); -} -inline JsonObject &JsonVariant::variantAsObject() const { - if (_type == Internals::JSON_OBJECT) return *_content.asObject; - return JsonObject::invalid(); -} -template -inline T JsonVariant::variantAsInteger() const { - using namespace Internals; - switch (_type) { - case JSON_UNDEFINED: - return 0; - case JSON_POSITIVE_INTEGER: - case JSON_BOOLEAN: - return T(_content.asInteger); - case JSON_NEGATIVE_INTEGER: - return T(~_content.asInteger + 1); - case JSON_STRING: - case JSON_UNPARSED: - return parseInteger(_content.asString); - default: - return T(_content.asFloat); - } -} -inline const char *JsonVariant::variantAsString() const { - using namespace Internals; - if (_type == JSON_UNPARSED && _content.asString && - !strcmp("null", _content.asString)) - return NULL; - if (_type == JSON_STRING || _type == JSON_UNPARSED) return _content.asString; - return NULL; -} -template -inline T JsonVariant::variantAsFloat() const { - using namespace Internals; - switch (_type) { - case JSON_UNDEFINED: - return 0; - case JSON_POSITIVE_INTEGER: - case JSON_BOOLEAN: - return static_cast(_content.asInteger); - case JSON_NEGATIVE_INTEGER: - return -static_cast(_content.asInteger); - case JSON_STRING: - case JSON_UNPARSED: - return parseFloat(_content.asString); - default: - return static_cast(_content.asFloat); - } -} -inline bool JsonVariant::variantIsBoolean() const { - using namespace Internals; - if (_type == JSON_BOOLEAN) return true; - if (_type != JSON_UNPARSED || _content.asString == NULL) return false; - return !strcmp(_content.asString, "true") || - !strcmp(_content.asString, "false"); -} -inline bool JsonVariant::variantIsInteger() const { - using namespace Internals; - return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER || - (_type == JSON_UNPARSED && isInteger(_content.asString)); -} -inline bool JsonVariant::variantIsFloat() const { - using namespace Internals; - return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER || - _type == JSON_NEGATIVE_INTEGER || - (_type == JSON_UNPARSED && isFloat(_content.asString)); -} -#if ARDUINOJSON_ENABLE_STD_STREAM -inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) { - return source.printTo(os); -} -#endif -} // namespace ArduinoJson -template -inline void ArduinoJson::Internals::JsonSerializer::serialize( - const JsonArray& array, Writer& writer) { - writer.beginArray(); - JsonArray::const_iterator it = array.begin(); - while (it != array.end()) { - serialize(*it, writer); - ++it; - if (it == array.end()) break; - writer.writeComma(); - } - writer.endArray(); -} -template -inline void ArduinoJson::Internals::JsonSerializer::serialize( - const JsonArraySubscript& arraySubscript, Writer& writer) { - serialize(arraySubscript.as(), writer); -} -template -inline void ArduinoJson::Internals::JsonSerializer::serialize( - const JsonObject& object, Writer& writer) { - writer.beginObject(); - JsonObject::const_iterator it = object.begin(); - while (it != object.end()) { - writer.writeString(it->key); - writer.writeColon(); - serialize(it->value, writer); - ++it; - if (it == object.end()) break; - writer.writeComma(); - } - writer.endObject(); -} -template -template -inline void ArduinoJson::Internals::JsonSerializer::serialize( - const JsonObjectSubscript& objectSubscript, Writer& writer) { - serialize(objectSubscript.template as(), writer); -} -template -inline void ArduinoJson::Internals::JsonSerializer::serialize( - const JsonVariant& variant, Writer& writer) { - switch (variant._type) { - case JSON_FLOAT: - writer.writeFloat(variant._content.asFloat); - return; - case JSON_ARRAY: - serialize(*variant._content.asArray, writer); - return; - case JSON_OBJECT: - serialize(*variant._content.asObject, writer); - return; - case JSON_STRING: - writer.writeString(variant._content.asString); - return; - case JSON_UNPARSED: - writer.writeRaw(variant._content.asString); - return; - case JSON_NEGATIVE_INTEGER: - writer.writeRaw('-'); // Falls through. - case JSON_POSITIVE_INTEGER: - writer.writeInteger(variant._content.asInteger); - return; - case JSON_BOOLEAN: - writer.writeBoolean(variant._content.asInteger != 0); - return; - default: // JSON_UNDEFINED - return; - } -} -#ifdef __GNUC__ -#define ARDUINOJSON_PRAGMA(x) _Pragma(#x) -#define ARDUINOJSON_COMPILE_ERROR(msg) ARDUINOJSON_PRAGMA(GCC error msg) -#define ARDUINOJSON_STRINGIFY(S) #S -#define ARDUINOJSON_DEPRECATION_ERROR(X, Y) \ - ARDUINOJSON_COMPILE_ERROR(ARDUINOJSON_STRINGIFY(X is a Y from ArduinoJson 6 but version 5 is installed. Visit arduinojson.org to get more information.)) -#define StaticJsonDocument ARDUINOJSON_DEPRECATION_ERROR(StaticJsonDocument, class) -#define DynamicJsonDocument ARDUINOJSON_DEPRECATION_ERROR(DynamicJsonDocument, class) -#define JsonDocument ARDUINOJSON_DEPRECATION_ERROR(JsonDocument, class) -#define DeserializationError ARDUINOJSON_DEPRECATION_ERROR(DeserializationError, class) -#define deserializeJson ARDUINOJSON_DEPRECATION_ERROR(deserializeJson, function) -#define deserializeMsgPack ARDUINOJSON_DEPRECATION_ERROR(deserializeMsgPack, function) -#define serializeJson ARDUINOJSON_DEPRECATION_ERROR(serializeJson, function) -#define serializeMsgPack ARDUINOJSON_DEPRECATION_ERROR(serializeMsgPack, function) -#define serializeJsonPretty ARDUINOJSON_DEPRECATION_ERROR(serializeJsonPretty, function) -#define measureMsgPack ARDUINOJSON_DEPRECATION_ERROR(measureMsgPack, function) -#define measureJson ARDUINOJSON_DEPRECATION_ERROR(measureJson, function) -#define measureJsonPretty ARDUINOJSON_DEPRECATION_ERROR(measureJsonPretty, function) -#endif - -using namespace ArduinoJson; - -#else - -#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp - -#endif diff --git a/wled00/src/dependencies/json/ArduinoJson-v6.h b/wled00/src/dependencies/json/ArduinoJson-v6.h new file mode 100644 index 00000000..1cd94f60 --- /dev/null +++ b/wled00/src/dependencies/json/ArduinoJson-v6.h @@ -0,0 +1,5663 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2019 +// MIT License + +#pragma once + +#ifdef __cplusplus + +#ifndef ARDUINOJSON_DEBUG +#ifdef __clang__ +#pragma clang system_header +#elif defined __GNUC__ +#pragma GCC system_header +#endif +#endif +#define ARDUINOJSON_VERSION "6.11.0" +#define ARDUINOJSON_VERSION_MAJOR 6 +#define ARDUINOJSON_VERSION_MINOR 11 +#define ARDUINOJSON_VERSION_REVISION 0 +#if defined(_MSC_VER) +#define ARDUINOJSON_HAS_INT64 1 +#else +#define ARDUINOJSON_HAS_INT64 0 +#endif +#if __cplusplus >= 201103L +#define ARDUINOJSON_HAS_LONG_LONG 1 +#define ARDUINOJSON_HAS_NULLPTR 1 +#else +#define ARDUINOJSON_HAS_LONG_LONG 0 +#define ARDUINOJSON_HAS_NULLPTR 0 +#endif +#ifndef ARDUINOJSON_EMBEDDED_MODE +#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \ + defined(__ARMCC_VERSION) +#define ARDUINOJSON_EMBEDDED_MODE 1 +#else +#define ARDUINOJSON_EMBEDDED_MODE 0 +#endif +#endif +#if ARDUINOJSON_EMBEDDED_MODE +#ifndef ARDUINOJSON_USE_DOUBLE +#define ARDUINOJSON_USE_DOUBLE 0 +#endif +#ifndef ARDUINOJSON_USE_LONG_LONG +#define ARDUINOJSON_USE_LONG_LONG 0 +#endif +#ifndef ARDUINOJSON_ENABLE_STD_STRING +#define ARDUINOJSON_ENABLE_STD_STRING 0 +#endif +#ifndef ARDUINOJSON_ENABLE_STD_STREAM +#define ARDUINOJSON_ENABLE_STD_STREAM 0 +#endif +#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT +#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 +#endif +#else // ARDUINOJSON_EMBEDDED_MODE +#ifndef ARDUINOJSON_USE_DOUBLE +#define ARDUINOJSON_USE_DOUBLE 1 +#endif +#ifndef ARDUINOJSON_USE_LONG_LONG +#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64 +#define ARDUINOJSON_USE_LONG_LONG 1 +#else +#define ARDUINOJSON_USE_LONG_LONG 0 +#endif +#endif +#ifndef ARDUINOJSON_ENABLE_STD_STRING +#define ARDUINOJSON_ENABLE_STD_STRING 1 +#endif +#ifndef ARDUINOJSON_ENABLE_STD_STREAM +#define ARDUINOJSON_ENABLE_STD_STREAM 1 +#endif +#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT +#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50 +#endif +#endif // ARDUINOJSON_EMBEDDED_MODE +#ifdef ARDUINO +#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING +#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 +#endif +#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM +#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 +#endif +#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT +#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1 +#endif +#else // ARDUINO +#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING +#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 +#endif +#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM +#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0 +#endif +#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT +#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0 +#endif +#endif // ARDUINO +#ifndef ARDUINOJSON_ENABLE_PROGMEM +#ifdef PROGMEM +#define ARDUINOJSON_ENABLE_PROGMEM 1 +#else +#define ARDUINOJSON_ENABLE_PROGMEM 0 +#endif +#endif +#ifndef ARDUINOJSON_DECODE_UNICODE +#define ARDUINOJSON_DECODE_UNICODE 0 +#endif +#ifndef ARDUINOJSON_ENABLE_NAN +#define ARDUINOJSON_ENABLE_NAN 0 +#endif +#ifndef ARDUINOJSON_ENABLE_INFINITY +#define ARDUINOJSON_ENABLE_INFINITY 0 +#endif +#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD +#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 +#endif +#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD +#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5 +#endif +#ifndef ARDUINOJSON_LITTLE_ENDIAN +#if defined(_MSC_VER) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ + defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64) +#define ARDUINOJSON_LITTLE_ENDIAN 1 +#else +#define ARDUINOJSON_LITTLE_ENDIAN 0 +#endif +#endif +#ifndef ARDUINOJSON_TAB +#define ARDUINOJSON_TAB " " +#endif +#define ARDUINOJSON_DO_CONCAT(A, B) A##B +#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_DO_CONCAT(A, B) +#define ARDUINOJSON_CONCAT3(A, B, C) \ + ARDUINOJSON_CONCAT2(A, ARDUINOJSON_CONCAT2(B, C)) +#define ARDUINOJSON_CONCAT4(A, B, C, D) \ + ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D)) +#define ARDUINOJSON_CONCAT8(A, B, C, D, E, F, G, H) \ + ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT4(A, B, C, D), \ + ARDUINOJSON_CONCAT4(E, F, G, H)) +#define ARDUINOJSON_CONCAT10(A, B, C, D, E, F, G, H, I, J) \ + ARDUINOJSON_CONCAT8(A, B, C, D, E, F, G, ARDUINOJSON_CONCAT3(H, I, J)) +#define ARDUINOJSON_NAMESPACE \ + ARDUINOJSON_CONCAT10( \ + ArduinoJson, ARDUINOJSON_VERSION_MAJOR, ARDUINOJSON_VERSION_MINOR, \ + ARDUINOJSON_VERSION_REVISION, _, ARDUINOJSON_USE_LONG_LONG, \ + ARDUINOJSON_USE_DOUBLE, ARDUINOJSON_DECODE_UNICODE, \ + ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY) +#ifdef ARDUINOJSON_DEBUG +#include +#define ARDUINOJSON_ASSERT(X) assert(X) +#else +#define ARDUINOJSON_ASSERT(X) ((void)0) +#endif +#include // for size_t +namespace ARDUINOJSON_NAMESPACE { +template Y)> +struct Max {}; +template +struct Max { + static const size_t value = X; +}; +template +struct Max { + static const size_t value = Y; +}; +} // namespace ARDUINOJSON_NAMESPACE +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); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct conditional { + typedef TrueType type; +}; +template +struct conditional { + typedef FalseType type; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct enable_if {}; +template +struct enable_if { + typedef T type; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct integral_constant { + static const T value = v; +}; +typedef integral_constant true_type; +typedef integral_constant false_type; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct is_array : false_type {}; +template +struct is_array : true_type {}; +template +struct is_array : true_type {}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +class is_base_of { + protected: // <- to avoid GCC's "all member functions in class are private" + typedef char Yes[1]; + typedef char No[2]; + static Yes &probe(const TBase *); + static No &probe(...); + public: + static const bool value = + sizeof(probe(reinterpret_cast(0))) == sizeof(Yes); +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct is_const : false_type {}; +template +struct is_const : true_type {}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct is_floating_point : false_type {}; +template <> +struct is_floating_point : true_type {}; +template <> +struct is_floating_point : true_type {}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct is_same : false_type {}; +template +struct is_same : true_type {}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct is_integral { + static const bool value = + is_same::value || is_same::value || + is_same::value || is_same::value || + is_same::value || is_same::value || + is_same::value || is_same::value || +#if ARDUINOJSON_HAS_LONG_LONG + is_same::value || + is_same::value || +#endif +#if ARDUINOJSON_HAS_INT64 + is_same::value || + is_same::value || +#endif + is_same::value; +}; +template +struct is_integral : is_integral {}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct is_signed : false_type {}; +template <> +struct is_signed : true_type {}; +template <> +struct is_signed : true_type {}; +template <> +struct is_signed : true_type {}; +template <> +struct is_signed : true_type {}; +template <> +struct is_signed : true_type {}; +template <> +struct is_signed : true_type {}; +template <> +struct is_signed : true_type {}; +#if ARDUINOJSON_HAS_LONG_LONG +template <> +struct is_signed : true_type {}; +#endif +#if ARDUINOJSON_HAS_INT64 +template <> +struct is_signed : true_type {}; +#endif +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct is_unsigned : false_type {}; +template <> +struct is_unsigned : true_type {}; +template <> +struct is_unsigned : true_type {}; +template <> +struct is_unsigned : true_type {}; +template <> +struct is_unsigned : true_type {}; +template <> +struct is_unsigned : true_type {}; +#if ARDUINOJSON_HAS_INT64 +template <> +struct is_unsigned : true_type {}; +#endif +#if ARDUINOJSON_HAS_LONG_LONG +template <> +struct is_unsigned : true_type {}; +#endif +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct type_identity { + typedef T type; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct make_unsigned; +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +#if ARDUINOJSON_HAS_LONG_LONG +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +#endif +#if ARDUINOJSON_HAS_INT64 +template <> +struct make_unsigned : type_identity {}; +template <> +struct make_unsigned : type_identity {}; +#endif +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct remove_const { + typedef T type; +}; +template +struct remove_const { + typedef T type; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct remove_reference { + typedef T type; +}; +template +struct remove_reference { + typedef T type; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class MemoryPool; +class VariantData; +class VariantSlot; +class CollectionData { + VariantSlot *_head; + VariantSlot *_tail; + public: + VariantSlot *addSlot(MemoryPool *); + VariantData *add(MemoryPool *pool); + template + VariantData *add(TAdaptedString key, MemoryPool *pool); + void clear(); + template + bool containsKey(const TAdaptedString &key) const; + bool copyFrom(const CollectionData &src, MemoryPool *pool); + bool equalsArray(const CollectionData &other) const; + bool equalsObject(const CollectionData &other) const; + VariantData *get(size_t index) const; + template + VariantData *get(TAdaptedString key) const; + VariantSlot *head() const { + return _head; + } + void remove(size_t index); + template + void remove(TAdaptedString key) { + remove(getSlot(key)); + } + void remove(VariantSlot *slot); + size_t memoryUsage() const; + size_t nesting() const; + size_t size() const; + private: + VariantSlot *getSlot(size_t index) const; + template + VariantSlot *getSlot(TAdaptedString key) const; + VariantSlot *getPreviousSlot(VariantSlot *) const; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +#if ARDUINOJSON_USE_DOUBLE +typedef double Float; +#else +typedef float Float; +#endif +} // namespace ARDUINOJSON_NAMESPACE +#include // int64_t +namespace ARDUINOJSON_NAMESPACE { +#if ARDUINOJSON_USE_LONG_LONG +typedef int64_t Integer; +typedef uint64_t UInt; +#else +typedef long Integer; +typedef unsigned long UInt; +#endif +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +enum { + VALUE_MASK = 0x7F, + VALUE_IS_NULL = 0, + VALUE_IS_LINKED_RAW = 0x01, + VALUE_IS_OWNED_RAW = 0x02, + VALUE_IS_LINKED_STRING = 0x03, + VALUE_IS_OWNED_STRING = 0x04, + VALUE_IS_BOOLEAN = 0x05, + VALUE_IS_POSITIVE_INTEGER = 0x06, + VALUE_IS_NEGATIVE_INTEGER = 0x07, + VALUE_IS_FLOAT = 0x08, + COLLECTION_MASK = 0x60, + VALUE_IS_OBJECT = 0x20, + VALUE_IS_ARRAY = 0x40, + KEY_IS_OWNED = 0x80 +}; +struct RawData { + const char *data; + size_t size; +}; +union VariantContent { + Float asFloat; + UInt asInteger; + CollectionData asCollection; + const char *asString; + struct { + const char *data; + size_t size; + } asRaw; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +typedef conditional::type VariantSlotDiff; +class VariantSlot { + VariantContent _content; + uint8_t _flags; + VariantSlotDiff _next; + const char* _key; + public: + VariantData* data() { + return reinterpret_cast(&_content); + } + const VariantData* data() const { + return reinterpret_cast(&_content); + } + VariantSlot* next() { + return _next ? this + _next : 0; + } + const VariantSlot* next() const { + return const_cast(this)->next(); + } + VariantSlot* next(size_t distance) { + VariantSlot* slot = this; + while (distance--) { + if (!slot->_next) return 0; + slot += slot->_next; + } + return slot; + } + const VariantSlot* next(size_t distance) const { + return const_cast(this)->next(distance); + } + void setNext(VariantSlot* slot) { + _next = VariantSlotDiff(slot ? slot - this : 0); + } + void setNextNotNull(VariantSlot* slot) { + ARDUINOJSON_ASSERT(slot != 0); + _next = VariantSlotDiff(slot - this); + } + void setOwnedKey(not_null k) { + _flags |= KEY_IS_OWNED; + _key = k.get(); + } + void setLinkedKey(not_null k) { + _flags &= VALUE_MASK; + _key = k.get(); + } + const char* key() const { + return _key; + } + bool ownsKey() const { + return (_flags & KEY_IS_OWNED) != 0; + } + void clear() { + _next = 0; + _flags = 0; + _key = 0; + } +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +inline bool isAligned(void *ptr) { + const size_t mask = sizeof(void *) - 1; + size_t addr = reinterpret_cast(ptr); + return (addr & mask) == 0; +} +inline size_t addPadding(size_t bytes) { + const size_t mask = sizeof(void *) - 1; + return (bytes + mask) & ~mask; +} +template +struct AddPadding { + static const size_t mask = sizeof(void *) - 1; + static const size_t value = (bytes + mask) & ~mask; +}; +} // namespace ARDUINOJSON_NAMESPACE +#define JSON_STRING_SIZE(SIZE) (SIZE) +namespace ARDUINOJSON_NAMESPACE { +struct StringSlot { + char *value; + size_t size; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class MemoryPool { + public: + MemoryPool(char* buf, size_t capa) + : _begin(buf), + _left(buf), + _right(buf ? buf + capa : 0), + _end(buf ? buf + capa : 0) { + ARDUINOJSON_ASSERT(isAligned(_begin)); + ARDUINOJSON_ASSERT(isAligned(_right)); + ARDUINOJSON_ASSERT(isAligned(_end)); + } + void* buffer() { + return _begin; + } + size_t capacity() const { + return size_t(_end - _begin); + } + size_t size() const { + return size_t(_left - _begin + _end - _right); + } + VariantSlot* allocVariant() { + return allocRight(); + } + char* allocFrozenString(size_t n) { + if (!canAlloc(n)) return 0; + char* s = _left; + _left += n; + checkInvariants(); + return s; + } + StringSlot allocExpandableString() { + StringSlot s; + s.value = _left; + s.size = size_t(_right - _left); + _left = _right; + checkInvariants(); + return s; + } + void freezeString(StringSlot& s, size_t newSize) { + _left -= (s.size - newSize); + s.size = newSize; + checkInvariants(); + } + void clear() { + _left = _begin; + _right = _end; + } + bool canAlloc(size_t bytes) const { + return _left + bytes <= _right; + } + bool owns(void* p) const { + return _begin <= p && p < _end; + } + template + T* allocRight() { + return reinterpret_cast(allocRight(sizeof(T))); + } + void* allocRight(size_t bytes) { + if (!canAlloc(bytes)) return 0; + _right -= bytes; + return _right; + } + void* operator new(size_t, void* p) { + return p; + } + private: + StringSlot* allocStringSlot() { + return allocRight(); + } + void checkInvariants() { + ARDUINOJSON_ASSERT(_begin <= _left); + ARDUINOJSON_ASSERT(_left <= _right); + ARDUINOJSON_ASSERT(_right <= _end); + ARDUINOJSON_ASSERT(isAligned(_right)); + } + char *_begin, *_left, *_right, *_end; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct IsString : false_type {}; +template +struct IsString : IsString {}; +template +struct IsString : IsString {}; +} // namespace ARDUINOJSON_NAMESPACE +#include // strcmp +namespace ARDUINOJSON_NAMESPACE { +inline int8_t safe_strcmp(const char* a, const char* b) { + if (a == b) return 0; + if (!a) return -1; + if (!b) return 1; + return static_cast(strcmp(a, b)); +} +inline int8_t safe_strncmp(const char* a, const char* b, size_t n) { + if (a == b) return 0; + if (!a) return -1; + if (!b) return 1; + return static_cast(strncmp(a, b, n)); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class ConstRamStringAdapter { + public: + ConstRamStringAdapter(const char* str = 0) : _str(str) {} + int8_t compare(const char* other) const { + return safe_strcmp(_str, other); + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + bool isNull() const { + return !_str; + } + template + char* save(TMemoryPool*) const { + return 0; + } + size_t size() const { + if (!_str) return 0; + return strlen(_str); + } + const char* data() const { + return _str; + } + bool isStatic() const { + return true; + } + protected: + const char* _str; +}; +inline ConstRamStringAdapter adaptString(const char* str) { + return ConstRamStringAdapter(str); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class RamStringAdapter : public ConstRamStringAdapter { + public: + RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {} + char* save(MemoryPool* pool) const { + if (!_str) return NULL; + size_t n = size() + 1; + char* dup = pool->allocFrozenString(n); + if (dup) memcpy(dup, _str, n); + return dup; + } + bool isStatic() const { + return false; + } +}; +template +inline RamStringAdapter adaptString(const TChar* str) { + return RamStringAdapter(reinterpret_cast(str)); +} +inline RamStringAdapter adaptString(char* str) { + return RamStringAdapter(str); +} +template +struct IsString { + static const bool value = sizeof(TChar) == 1; +}; +template <> +struct IsString { + static const bool value = false; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class SizedRamStringAdapter { + public: + SizedRamStringAdapter(const char* str, size_t n) : _str(str), _size(n) {} + int8_t compare(const char* other) const { + return safe_strncmp(_str, other, _size) == 0; + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + bool isNull() const { + return !_str; + } + char* save(MemoryPool* pool) const { + if (!_str) return NULL; + char* dup = pool->allocFrozenString(_size); + if (dup) memcpy(dup, _str, _size); + return dup; + } + size_t size() const { + return _size; + } + bool isStatic() const { + return false; + } + private: + const char* _str; + size_t _size; +}; +template +inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) { + return SizedRamStringAdapter(reinterpret_cast(str), size); +} +} // namespace ARDUINOJSON_NAMESPACE +#if ARDUINOJSON_ENABLE_STD_STRING +#include +namespace ARDUINOJSON_NAMESPACE { +class StlStringAdapter { + public: + StlStringAdapter(const std::string& str) : _str(&str) {} + char* save(MemoryPool* pool) const { + size_t n = _str->length() + 1; + char* dup = pool->allocFrozenString(n); + if (dup) memcpy(dup, _str->c_str(), n); + return dup; + } + bool isNull() const { + return false; + } + int8_t compare(const char* other) const { + if (!other) return 1; + return static_cast(_str->compare(other)); + } + bool equals(const char* expected) const { + if (!expected) return false; + return *_str == expected; + } + const char* data() const { + return _str->data(); + } + size_t size() const { + return _str->size(); + } + bool isStatic() const { + return false; + } + private: + const std::string* _str; +}; +template <> +struct IsString : true_type {}; +inline StlStringAdapter adaptString(const std::string& str) { + return StlStringAdapter(str); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +#if ARDUINOJSON_ENABLE_ARDUINO_STRING +#include +namespace ARDUINOJSON_NAMESPACE { +class ArduinoStringAdapter { + public: + ArduinoStringAdapter(const ::String& str) : _str(&str) {} + char* save(MemoryPool* pool) const { + if (isNull()) return NULL; + size_t n = _str->length() + 1; + char* dup = pool->allocFrozenString(n); + if (dup) memcpy(dup, _str->c_str(), n); + return dup; + } + bool isNull() const { + return !_str->c_str(); + } + int8_t compare(const char* other) const { + const char* me = _str->c_str(); + return safe_strcmp(me, other); + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + const char* data() const { + return _str->c_str(); + } + size_t size() const { + return _str->length(); + } + bool isStatic() const { + return false; + } + private: + const ::String* _str; +}; +template <> +struct IsString< ::String> : true_type {}; +template <> +struct IsString< ::StringSumHelper> : true_type {}; +inline ArduinoStringAdapter adaptString(const ::String& str) { + return ArduinoStringAdapter(str); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +#if ARDUINOJSON_ENABLE_PROGMEM +namespace ARDUINOJSON_NAMESPACE { +class FlashStringAdapter { + public: + FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {} + int8_t compare(const char* other) const { + if (!other && !_str) return 0; + if (!_str) return -1; + if (!other) return 1; + return -strcmp_P(other, reinterpret_cast(_str)); + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + bool isNull() const { + return !_str; + } + char* save(MemoryPool* pool) const { + if (!_str) return NULL; + size_t n = size() + 1; // copy the terminator + char* dup = pool->allocFrozenString(n); + if (dup) memcpy_P(dup, reinterpret_cast(_str), n); + return dup; + } + const char* data() const { + return 0; + } + size_t size() const { + if (!_str) return 0; + return strlen_P(reinterpret_cast(_str)); + } + bool isStatic() const { + return false; + } + private: + const __FlashStringHelper* _str; +}; +inline FlashStringAdapter adaptString(const __FlashStringHelper* str) { + return FlashStringAdapter(str); +} +template <> +struct IsString : true_type {}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class SizedFlashStringAdapter { + public: + SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz) + : _str(str), _size(sz) {} + int8_t compare(const char* other) const { + if (!other && !_str) return 0; + if (!_str) return -1; + if (!other) return 1; + return -strncmp_P(other, reinterpret_cast(_str), _size); + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + bool isNull() const { + return !_str; + } + char* save(MemoryPool* pool) const { + if (!_str) return NULL; + char* dup = pool->allocFrozenString(_size); + if (dup) memcpy_P(dup, (const char*)_str, _size); + return dup; + } + size_t size() const { + return _size; + } + bool isStatic() const { + return false; + } + private: + const __FlashStringHelper* _str; + size_t _size; +}; +inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str, + size_t sz) { + return SizedFlashStringAdapter(str, sz); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +namespace ARDUINOJSON_NAMESPACE { +template +class SerializedValue { + public: + explicit SerializedValue(T str) : _str(str) {} + operator T() const { + return _str; + } + const char* data() const { + return _str.c_str(); + } + size_t size() const { + return _str.length(); + } + private: + T _str; +}; +template +class SerializedValue { + public: + explicit SerializedValue(TChar* p, size_t n) : _data(p), _size(n) {} + operator TChar*() const { + return _data; + } + TChar* data() const { + return _data; + } + size_t size() const { + return _size; + } + private: + TChar* _data; + size_t _size; +}; +template +inline SerializedValue serialized(T str) { + return SerializedValue(str); +} +template +inline SerializedValue serialized(TChar* p) { + return SerializedValue(p, adaptString(p).size()); +} +template +inline SerializedValue serialized(TChar* p, size_t n) { + return SerializedValue(p, n); +} +} // namespace ARDUINOJSON_NAMESPACE +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" +#elif defined(__GNUC__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#pragma GCC diagnostic push +#endif +#pragma GCC diagnostic ignored "-Wconversion" +#endif +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4310) +#endif +namespace ARDUINOJSON_NAMESPACE { +template +struct numeric_limits; +template +struct numeric_limits::value>::type> { + static T lowest() { + return 0; + } + static T highest() { + return T(-1); + } +}; +template +struct numeric_limits< + T, typename enable_if::value && is_signed::value>::type> { + static T lowest() { + return T(T(1) << (sizeof(T) * 8 - 1)); + } + static T highest() { + return T(~lowest()); + } +}; +} // namespace ARDUINOJSON_NAMESPACE +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#include // for size_t +namespace ARDUINOJSON_NAMESPACE { +#ifndef isnan +template +bool isnan(T x) { + return x != x; +} +#endif +#ifndef isinf +template +bool isinf(T x) { + return x != 0.0 && x * 2 == x; +} +#endif +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct alias_cast_t { + union { + F raw; + T data; + }; +}; +template +T alias_cast(F raw_data) { + alias_cast_t ac; + ac.raw = raw_data; + return ac.data; +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct FloatTraits {}; +template +struct FloatTraits { + typedef uint64_t mantissa_type; + static const short mantissa_bits = 52; + static const mantissa_type mantissa_max = + (mantissa_type(1) << mantissa_bits) - 1; + typedef int16_t exponent_type; + static const exponent_type exponent_max = 308; + template + static T make_float(T m, TExponent e) { + if (e > 0) { + for (uint8_t index = 0; e != 0; index++) { + if (e & 1) m *= positiveBinaryPowerOfTen(index); + e >>= 1; + } + } else { + e = TExponent(-e); + for (uint8_t index = 0; e != 0; index++) { + if (e & 1) m *= negativeBinaryPowerOfTen(index); + e >>= 1; + } + } + 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]; + } + 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]; + } + 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]; + } + static T nan() { + return forge(0x7ff80000, 0x00000000); + } + static T inf() { + return forge(0x7ff00000, 0x00000000); + } + static T highest() { + return forge(0x7FEFFFFF, 0xFFFFFFFF); + } + static T lowest() { + return forge(0xFFEFFFFF, 0xFFFFFFFF); + } + static T forge(uint32_t msb, uint32_t lsb) { + return alias_cast((uint64_t(msb) << 32) | lsb); + } +}; +template +struct FloatTraits { + typedef uint32_t mantissa_type; + static const short mantissa_bits = 23; + static const mantissa_type mantissa_max = + (mantissa_type(1) << mantissa_bits) - 1; + typedef int8_t exponent_type; + static const exponent_type exponent_max = 38; + template + static T make_float(T m, TExponent e) { + if (e > 0) { + for (uint8_t index = 0; e != 0; index++) { + if (e & 1) m *= positiveBinaryPowerOfTen(index); + e >>= 1; + } + } else { + e = -e; + for (uint8_t index = 0; e != 0; index++) { + if (e & 1) m *= negativeBinaryPowerOfTen(index); + e >>= 1; + } + } + return m; + } + static T positiveBinaryPowerOfTen(int index) { + static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}; + return 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]; + } + static T negativeBinaryPowerOfTenPlusOne(int index) { + static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}; + return factors[index]; + } + static T forge(uint32_t bits) { + return alias_cast(bits); + } + static T nan() { + return forge(0x7fc00000); + } + static T inf() { + return forge(0x7f800000); + } + static T highest() { + return forge(0x7f7fffff); + } + static T lowest() { + return forge(0xFf7fffff); + } +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +typename enable_if::value && sizeof(TOut) <= sizeof(TIn), + bool>::type +canStorePositiveInteger(TIn value) { + return value <= TIn(numeric_limits::highest()); +} +template +typename enable_if::value && sizeof(TIn) < sizeof(TOut), + bool>::type +canStorePositiveInteger(TIn) { + return true; +} +template +typename enable_if::value, bool>::type +canStorePositiveInteger(TIn) { + return true; +} +template +typename enable_if::value, bool>::type +canStoreNegativeInteger(TIn) { + return true; +} +template +typename enable_if::value && is_signed::value && + sizeof(TOut) <= sizeof(TIn), + bool>::type +canStoreNegativeInteger(TIn value) { + return value <= TIn(numeric_limits::highest()) + 1; +} +template +typename enable_if::value && is_signed::value && + sizeof(TIn) < sizeof(TOut), + bool>::type +canStoreNegativeInteger(TIn) { + return true; +} +template +typename enable_if::value && is_unsigned::value, + bool>::type +canStoreNegativeInteger(TIn) { + return false; +} +template +TOut convertPositiveInteger(TIn value) { + return canStorePositiveInteger(value) ? TOut(value) : 0; +} +template +TOut convertNegativeInteger(TIn value) { + return canStoreNegativeInteger(value) ? TOut(~value + 1) : 0; +} +template +typename enable_if::value, TOut>::type convertFloat( + TIn value) { + return TOut(value); +} +template +typename enable_if::value, TOut>::type convertFloat( + TIn value) { + return value >= numeric_limits::lowest() && + value <= numeric_limits::highest() + ? TOut(value) + : 0; +} +} // namespace ARDUINOJSON_NAMESPACE +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#pragma GCC diagnostic pop +#endif +#endif +namespace ARDUINOJSON_NAMESPACE { +class VariantData { + VariantContent _content; // must be first to allow cast from array to variant + uint8_t _flags; + public: + template + void accept(Visitor &visitor) const { + switch (type()) { + case VALUE_IS_FLOAT: + return visitor.visitFloat(_content.asFloat); + case VALUE_IS_ARRAY: + return visitor.visitArray(_content.asCollection); + case VALUE_IS_OBJECT: + return visitor.visitObject(_content.asCollection); + case VALUE_IS_LINKED_STRING: + case VALUE_IS_OWNED_STRING: + return visitor.visitString(_content.asString); + case VALUE_IS_OWNED_RAW: + case VALUE_IS_LINKED_RAW: + return visitor.visitRawJson(_content.asRaw.data, _content.asRaw.size); + case VALUE_IS_NEGATIVE_INTEGER: + return visitor.visitNegativeInteger(_content.asInteger); + case VALUE_IS_POSITIVE_INTEGER: + return visitor.visitPositiveInteger(_content.asInteger); + case VALUE_IS_BOOLEAN: + return visitor.visitBoolean(_content.asInteger != 0); + default: + return visitor.visitNull(); + } + } + template + T asIntegral() const; + template + T asFloat() const; + const char *asString() const; + bool asBoolean() const; + CollectionData *asArray() { + return isArray() ? &_content.asCollection : 0; + } + const CollectionData *asArray() const { + return const_cast(this)->asArray(); + } + CollectionData *asObject() { + return isObject() ? &_content.asCollection : 0; + } + const CollectionData *asObject() const { + return const_cast(this)->asObject(); + } + bool copyFrom(const VariantData &src, MemoryPool *pool) { + switch (src.type()) { + case VALUE_IS_ARRAY: + return toArray().copyFrom(src._content.asCollection, pool); + case VALUE_IS_OBJECT: + return toObject().copyFrom(src._content.asCollection, pool); + case VALUE_IS_OWNED_STRING: + return setOwnedString(RamStringAdapter(src._content.asString), pool); + case VALUE_IS_OWNED_RAW: + return setOwnedRaw( + serialized(src._content.asRaw.data, src._content.asRaw.size), pool); + default: + setType(src.type()); + _content = src._content; + return true; + } + } + bool equals(const VariantData &other) const { + if (type() != other.type()) return false; + switch (type()) { + case VALUE_IS_LINKED_STRING: + case VALUE_IS_OWNED_STRING: + return !strcmp(_content.asString, other._content.asString); + case VALUE_IS_LINKED_RAW: + case VALUE_IS_OWNED_RAW: + return _content.asRaw.size == other._content.asRaw.size && + !memcmp(_content.asRaw.data, other._content.asRaw.data, + _content.asRaw.size); + case VALUE_IS_BOOLEAN: + case VALUE_IS_POSITIVE_INTEGER: + case VALUE_IS_NEGATIVE_INTEGER: + return _content.asInteger == other._content.asInteger; + case VALUE_IS_ARRAY: + return _content.asCollection.equalsArray(other._content.asCollection); + case VALUE_IS_OBJECT: + return _content.asCollection.equalsObject(other._content.asCollection); + case VALUE_IS_FLOAT: + return _content.asFloat == other._content.asFloat; + case VALUE_IS_NULL: + default: + return true; + } + } + bool isArray() const { + return (_flags & VALUE_IS_ARRAY) != 0; + } + bool isBoolean() const { + return type() == VALUE_IS_BOOLEAN; + } + bool isCollection() const { + return (_flags & COLLECTION_MASK) != 0; + } + template + bool isInteger() const { + switch (type()) { + case VALUE_IS_POSITIVE_INTEGER: + return canStorePositiveInteger(_content.asInteger); + case VALUE_IS_NEGATIVE_INTEGER: + return canStoreNegativeInteger(_content.asInteger); + default: + return false; + } + } + bool isFloat() const { + return type() == VALUE_IS_FLOAT || type() == VALUE_IS_POSITIVE_INTEGER || + type() == VALUE_IS_NEGATIVE_INTEGER; + } + bool isString() const { + return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING; + } + bool isObject() const { + return (_flags & VALUE_IS_OBJECT) != 0; + } + bool isNull() const { + return type() == VALUE_IS_NULL; + } + bool isEnclosed() const { + return isCollection() || isString(); + } + void remove(size_t index) { + if (isArray()) _content.asCollection.remove(index); + } + template + void remove(TAdaptedString key) { + if (isObject()) _content.asCollection.remove(key); + } + void setBoolean(bool value) { + setType(VALUE_IS_BOOLEAN); + _content.asInteger = static_cast(value); + } + void setFloat(Float value) { + setType(VALUE_IS_FLOAT); + _content.asFloat = value; + } + void setLinkedRaw(SerializedValue value) { + if (value.data()) { + setType(VALUE_IS_LINKED_RAW); + _content.asRaw.data = value.data(); + _content.asRaw.size = value.size(); + } else { + setType(VALUE_IS_NULL); + } + } + template + bool setOwnedRaw(SerializedValue value, MemoryPool *pool) { + char *dup = adaptString(value.data(), value.size()).save(pool); + if (dup) { + setType(VALUE_IS_OWNED_RAW); + _content.asRaw.data = dup; + _content.asRaw.size = value.size(); + return true; + } else { + setType(VALUE_IS_NULL); + return false; + } + } + template + typename enable_if::value>::type setInteger(T value) { + setUnsignedInteger(value); + } + template + typename enable_if::value>::type setInteger(T value) { + setSignedInteger(value); + } + template + void setSignedInteger(T value) { + if (value >= 0) { + setPositiveInteger(static_cast(value)); + } else { + setNegativeInteger(~static_cast(value) + 1); + } + } + void setPositiveInteger(UInt value) { + setType(VALUE_IS_POSITIVE_INTEGER); + _content.asInteger = value; + } + void setNegativeInteger(UInt value) { + setType(VALUE_IS_NEGATIVE_INTEGER); + _content.asInteger = value; + } + void setLinkedString(const char *value) { + if (value) { + setType(VALUE_IS_LINKED_STRING); + _content.asString = value; + } else { + setType(VALUE_IS_NULL); + } + } + void setNull() { + setType(VALUE_IS_NULL); + } + void setOwnedString(not_null s) { + setType(VALUE_IS_OWNED_STRING); + _content.asString = s.get(); + } + bool setOwnedString(const char *s) { + if (s) { + setOwnedString(make_not_null(s)); + return true; + } else { + setType(VALUE_IS_NULL); + return false; + } + } + template + bool setOwnedString(T value, MemoryPool *pool) { + return setOwnedString(value.save(pool)); + } + void setUnsignedInteger(UInt value) { + setType(VALUE_IS_POSITIVE_INTEGER); + _content.asInteger = static_cast(value); + } + CollectionData &toArray() { + setType(VALUE_IS_ARRAY); + _content.asCollection.clear(); + return _content.asCollection; + } + CollectionData &toObject() { + setType(VALUE_IS_OBJECT); + _content.asCollection.clear(); + return _content.asCollection; + } + size_t memoryUsage() const { + switch (type()) { + case VALUE_IS_OWNED_STRING: + return strlen(_content.asString) + 1; + case VALUE_IS_OWNED_RAW: + return _content.asRaw.size; + case VALUE_IS_OBJECT: + case VALUE_IS_ARRAY: + return _content.asCollection.memoryUsage(); + default: + return 0; + } + } + size_t nesting() const { + return isCollection() ? _content.asCollection.nesting() : 0; + } + size_t size() const { + return isCollection() ? _content.asCollection.size() : 0; + } + VariantData *addElement(MemoryPool *pool) { + if (isNull()) toArray(); + if (!isArray()) return 0; + return _content.asCollection.add(pool); + } + VariantData *getElement(size_t index) const { + return isArray() ? _content.asCollection.get(index) : 0; + } + template + VariantData *getMember(TAdaptedString key) const { + return isObject() ? _content.asCollection.get(key) : 0; + } + template + VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) { + if (isNull()) toObject(); + if (!isObject()) return 0; + VariantData *var = _content.asCollection.get(key); + if (var) return var; + return _content.asCollection.add(key, pool); + } + private: + uint8_t type() const { + return _flags & VALUE_MASK; + } + void setType(uint8_t t) { + _flags &= KEY_IS_OWNED; + _flags |= t; + } +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) { + return arr ? arr->add(pool) : 0; +} +template +inline void arrayAccept(const CollectionData *arr, Visitor &visitor) { + if (arr) + visitor.visitArray(*arr); + else + visitor.visitNull(); +} +inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) { + if (lhs == rhs) return true; + if (!lhs || !rhs) return false; + return lhs->equalsArray(*rhs); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) { + if (!var) return false; + if (key.isStatic()) { + var->setLinkedKey(make_not_null(key.data())); + } else { + const char* dup = key.save(pool); + if (!dup) return false; + var->setOwnedKey(make_not_null(dup)); + } + return true; +} +inline size_t slotSize(const VariantSlot* var) { + size_t n = 0; + while (var) { + n++; + var = var->next(); + } + return n; +} +inline VariantData* slotData(VariantSlot* slot) { + return reinterpret_cast(slot); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +struct Visitable { +}; +template +struct IsVisitable : is_base_of {}; +template +struct IsVisitable : IsVisitable {}; +} // namespace ARDUINOJSON_NAMESPACE +#ifdef _MSC_VER // Visual Studio +#define FORCE_INLINE // __forceinline causes C4714 when returning std::string +#define NO_INLINE __declspec(noinline) +#define DEPRECATED(msg) __declspec(deprecated(msg)) +#elif defined(__GNUC__) // GCC or Clang +#define FORCE_INLINE __attribute__((always_inline)) +#define NO_INLINE __attribute__((noinline)) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#define DEPRECATED(msg) __attribute__((deprecated(msg))) +#else +#define DEPRECATED(msg) __attribute__((deprecated)) +#endif +#else // Other compilers +#define FORCE_INLINE +#define NO_INLINE +#define DEPRECATED(msg) +#endif +#if __cplusplus >= 201103L +#define NOEXCEPT noexcept +#else +#define NOEXCEPT throw() +#endif +#if defined(__has_attribute) +#if __has_attribute(no_sanitize) +#define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check))) +#else +#define ARDUINOJSON_NO_SANITIZE(check) +#endif +#else +#define ARDUINOJSON_NO_SANITIZE(check) +#endif +namespace ARDUINOJSON_NAMESPACE { +template +class VariantCasts { + public: + template + FORCE_INLINE operator T() const { + return impl()->template as(); + } + private: + const TImpl *impl() const { + return static_cast(this); + } +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct Comparer; +template +struct Comparer::value>::type> { + T rhs; + int result; + explicit Comparer(T value) : rhs(value), result(1) {} + void visitArray(const CollectionData &) {} + void visitObject(const CollectionData &) {} + void visitFloat(Float) {} + void visitString(const char *lhs) { + result = -adaptString(rhs).compare(lhs); + } + void visitRawJson(const char *, size_t) {} + void visitNegativeInteger(UInt) {} + void visitPositiveInteger(UInt) {} + void visitBoolean(bool) {} + void visitNull() { + result = adaptString(rhs).compare(NULL); + } +}; +template +typename enable_if::value, int>::type sign(const T &value) { + return value < 0 ? -1 : value > 0 ? 1 : 0; +} +template +typename enable_if::value, int>::type sign(const T &value) { + return value > 0 ? 1 : 0; +} +template +struct Comparer::value || + is_floating_point::value>::type> { + T rhs; + int result; + explicit Comparer(T value) : rhs(value), result(1) {} + void visitArray(const CollectionData &) {} + void visitObject(const CollectionData &) {} + void visitFloat(Float lhs) { + result = sign(lhs - static_cast(rhs)); + } + void visitString(const char *) {} + void visitRawJson(const char *, size_t) {} + void visitNegativeInteger(UInt lhs) { + result = -sign(static_cast(lhs) + rhs); + } + void visitPositiveInteger(UInt lhs) { + result = static_cast(lhs) < rhs ? -1 : static_cast(lhs) > rhs ? 1 : 0; + } + void visitBoolean(bool) {} + void visitNull() {} +}; +template <> +struct Comparer { + bool rhs; + int result; + explicit Comparer(bool value) : rhs(value), result(1) {} + void visitArray(const CollectionData &) {} + 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 lhs) { + result = static_cast(lhs - rhs); + } + void visitNull() {} +}; +#if ARDUINOJSON_HAS_NULLPTR +template <> +struct Comparer { + int result; + explicit Comparer(decltype(nullptr)) : result(1) {} + void visitArray(const CollectionData &) {} + 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() { + result = 0; + } +}; +#endif +template +class VariantComparisons { + private: + template + static int compare(TVariant lhs, const T &rhs) { + Comparer comparer(rhs); + lhs.accept(comparer); + return comparer.result; + } + public: + template + friend bool operator==(T *lhs, TVariant rhs) { + return compare(rhs, lhs) == 0; + } + template + friend bool operator==(const T &lhs, TVariant rhs) { + return compare(rhs, lhs) == 0; + } + template + friend bool operator==(TVariant lhs, T *rhs) { + return compare(lhs, rhs) == 0; + } + template + friend bool operator==(TVariant lhs, const T &rhs) { + return compare(lhs, rhs) == 0; + } + template + friend bool operator!=(T *lhs, TVariant rhs) { + return compare(rhs, lhs) != 0; + } + template + friend bool operator!=(const T &lhs, TVariant rhs) { + return compare(rhs, lhs) != 0; + } + template + friend bool operator!=(TVariant lhs, T *rhs) { + return compare(lhs, rhs) != 0; + } + template + friend bool operator!=(TVariant lhs, const T &rhs) { + return compare(lhs, rhs) != 0; + } + template + friend bool operator<(T *lhs, TVariant rhs) { + return compare(rhs, lhs) > 0; + } + template + friend bool operator<(const T &lhs, TVariant rhs) { + return compare(rhs, lhs) > 0; + } + template + friend bool operator<(TVariant lhs, T *rhs) { + return compare(lhs, rhs) < 0; + } + template + friend bool operator<(TVariant lhs, const T &rhs) { + return compare(lhs, rhs) < 0; + } + template + friend bool operator<=(T *lhs, TVariant rhs) { + return compare(rhs, lhs) >= 0; + } + template + friend bool operator<=(const T &lhs, TVariant rhs) { + return compare(rhs, lhs) >= 0; + } + template + friend bool operator<=(TVariant lhs, T *rhs) { + return compare(lhs, rhs) <= 0; + } + template + friend bool operator<=(TVariant lhs, const T &rhs) { + return compare(lhs, rhs) <= 0; + } + template + friend bool operator>(T *lhs, TVariant rhs) { + return compare(rhs, lhs) < 0; + } + template + friend bool operator>(const T &lhs, TVariant rhs) { + return compare(rhs, lhs) < 0; + } + template + friend bool operator>(TVariant lhs, T *rhs) { + return compare(lhs, rhs) > 0; + } + template + friend bool operator>(TVariant lhs, const T &rhs) { + return compare(lhs, rhs) > 0; + } + template + friend bool operator>=(T *lhs, TVariant rhs) { + return compare(rhs, lhs) <= 0; + } + template + friend bool operator>=(const T &lhs, TVariant rhs) { + return compare(rhs, lhs) <= 0; + } + template + friend bool operator>=(TVariant lhs, T *rhs) { + return compare(lhs, rhs) >= 0; + } + template + friend bool operator>=(TVariant lhs, const T &rhs) { + return compare(lhs, rhs) >= 0; + } +}; +} // namespace ARDUINOJSON_NAMESPACE +#if ARDUINOJSON_ENABLE_ARDUINO_STRING +#endif +#if ARDUINOJSON_ENABLE_STD_STRING +#endif +namespace ARDUINOJSON_NAMESPACE { +template +struct IsWriteableString : false_type {}; +template +class DynamicStringWriter {}; +#if ARDUINOJSON_ENABLE_ARDUINO_STRING +template <> +struct IsWriteableString : true_type {}; +template <> +class DynamicStringWriter { + public: + DynamicStringWriter(String &str) : _str(&str) {} + size_t write(uint8_t c) { + _str->operator+=(static_cast(c)); + return 1; + } + size_t write(const uint8_t *s, size_t n) { + _str->reserve(_str->length() + n); + while (n > 0) { + _str->operator+=(static_cast(*s++)); + n--; + } + return n; + } + private: + String *_str; +}; +#endif +#if ARDUINOJSON_ENABLE_STD_STRING +template <> +struct IsWriteableString : true_type {}; +template <> +class DynamicStringWriter { + public: + DynamicStringWriter(std::string &str) : _str(&str) {} + size_t write(uint8_t c) { + _str->operator+=(static_cast(c)); + return 1; + } + size_t write(const uint8_t *s, size_t n) { + _str->append(reinterpret_cast(s), n); + return n; + } + private: + std::string *_str; +}; +#endif +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class ArrayRef; +class ArrayConstRef; +class ObjectRef; +class ObjectConstRef; +class VariantRef; +class VariantConstRef; +template +struct VariantAs { + typedef T type; +}; +template <> +struct VariantAs { + typedef const char* type; +}; +template +struct VariantConstAs { + typedef typename VariantAs::type type; +}; +template <> +struct VariantConstAs { + typedef VariantConstRef type; +}; +template <> +struct VariantConstAs { + typedef ObjectConstRef type; +}; +template <> +struct VariantConstAs { + typedef ArrayConstRef type; +}; +template +inline typename enable_if::value, T>::type variantAs( + const VariantData* _data) { + return _data != 0 ? _data->asIntegral() : T(0); +} +template +inline typename enable_if::value, T>::type variantAs( + const VariantData* _data) { + return _data != 0 ? _data->asBoolean() : false; +} +template +inline typename enable_if::value, T>::type variantAs( + const VariantData* _data) { + return _data != 0 ? _data->asFloat() : T(0); +} +template +inline typename enable_if::value || + is_same::value, + const char*>::type +variantAs(const VariantData* _data) { + return _data != 0 ? _data->asString() : 0; +} +template +inline typename enable_if::value, T>::type variantAs( + const VariantData* _data); +template +inline typename enable_if::value, T>::type variantAs( + const VariantData* _data); +template +inline typename enable_if::value, T>::type +variantAs(const VariantData* _data); +template +inline typename enable_if::value, T>::type variantAs( + const VariantData* _data); +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +class VariantOr { + public: + template + T operator|(const T &defaultValue) const { + if (impl()->template is()) + return impl()->template as(); + else + return defaultValue; + } + const char *operator|(const char *defaultValue) const { + const char *value = impl()->template as(); + return value ? value : defaultValue; + } + private: + const TImpl *impl() const { + return static_cast(this); + } +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +class ElementProxy; +template +class ArrayShortcuts { + public: + FORCE_INLINE ElementProxy operator[](size_t index) const; + FORCE_INLINE ObjectRef createNestedObject() const; + FORCE_INLINE ArrayRef createNestedArray() const; + template + FORCE_INLINE bool add(const T &value) const { + return impl()->addElement().set(value); + } + template + FORCE_INLINE bool add(T *value) const { + return impl()->addElement().set(value); + } + private: + const TArray *impl() const { + return static_cast(this); + } +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +class MemberProxy; +template +class ObjectShortcuts { + public: + template + FORCE_INLINE typename enable_if::value, bool>::type + containsKey(const TString &key) const; + template + FORCE_INLINE typename enable_if::value, bool>::type + containsKey(TChar *key) const; + template + FORCE_INLINE + typename enable_if::value, + MemberProxy >::type + operator[](const TString &key) const; + template + FORCE_INLINE typename enable_if::value, + MemberProxy >::type + operator[](TChar *key) const; + template + FORCE_INLINE ArrayRef createNestedArray(const TString &key) const; + template + FORCE_INLINE ArrayRef createNestedArray(TChar *key) const; + template + ObjectRef createNestedObject(const TString &key) const; + template + ObjectRef createNestedObject(TChar *key) const; + private: + const TObject *impl() const { + return static_cast(this); + } +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +class VariantShortcuts : public ObjectShortcuts, + public ArrayShortcuts { + public: + using ArrayShortcuts::createNestedArray; + using ArrayShortcuts::createNestedObject; + using ArrayShortcuts::operator[]; + using ObjectShortcuts::createNestedArray; + using ObjectShortcuts::createNestedObject; + using ObjectShortcuts::operator[]; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +class VariantOperators : public VariantCasts, + public VariantComparisons, + public VariantOr, + public VariantShortcuts {}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +inline void variantAccept(const VariantData *var, Visitor &visitor) { + if (var != 0) + var->accept(visitor); + else + visitor.visitNull(); +} +inline const CollectionData *variantAsArray(const VariantData *var) { + return var != 0 ? var->asArray() : 0; +} +inline const CollectionData *variantAsObject(const VariantData *var) { + return var != 0 ? var->asObject() : 0; +} +inline CollectionData *variantAsObject(VariantData *var) { + return var != 0 ? var->asObject() : 0; +} +inline bool variantCopyFrom(VariantData *dst, const VariantData *src, + MemoryPool *pool) { + if (!dst) return false; + if (!src) { + dst->setNull(); + return true; + } + return dst->copyFrom(*src, pool); +} +inline bool variantEquals(const VariantData *a, const VariantData *b) { + if (a == b) return true; + if (!a || !b) return false; + return a->equals(*b); +} +inline bool variantIsArray(const VariantData *var) { + return var && var->isArray(); +} +inline bool variantIsBoolean(const VariantData *var) { + return var && var->isBoolean(); +} +template +inline bool variantIsInteger(const VariantData *var) { + return var && var->isInteger(); +} +inline bool variantIsFloat(const VariantData *var) { + return var && var->isFloat(); +} +inline bool variantIsString(const VariantData *var) { + return var && var->isString(); +} +inline bool variantIsObject(const VariantData *var) { + return var && var->isObject(); +} +inline bool variantIsNull(const VariantData *var) { + return var == 0 || var->isNull(); +} +inline bool variantSetBoolean(VariantData *var, bool value) { + if (!var) return false; + var->setBoolean(value); + return true; +} +inline bool variantSetFloat(VariantData *var, Float value) { + if (!var) return false; + var->setFloat(value); + return true; +} +inline bool variantSetLinkedRaw(VariantData *var, + SerializedValue value) { + if (!var) return false; + var->setLinkedRaw(value); + return true; +} +template +inline bool variantSetOwnedRaw(VariantData *var, SerializedValue value, + MemoryPool *pool) { + return var != 0 && var->setOwnedRaw(value, pool); +} +template +inline bool variantSetSignedInteger(VariantData *var, T value) { + if (!var) return false; + var->setSignedInteger(value); + return true; +} +inline bool variantSetLinkedString(VariantData *var, const char *value) { + if (!var) return false; + var->setLinkedString(value); + return true; +} +inline void variantSetNull(VariantData *var) { + if (!var) return; + var->setNull(); +} +inline bool variantSetOwnedString(VariantData *var, char *value) { + if (!var) return false; + var->setOwnedString(value); + return true; +} +template +inline bool variantSetOwnedString(VariantData *var, T value, MemoryPool *pool) { + return var != 0 && var->setOwnedString(value, pool); +} +inline bool variantSetUnsignedInteger(VariantData *var, UInt value) { + if (!var) return false; + var->setUnsignedInteger(value); + return true; +} +inline size_t variantSize(const VariantData *var) { + return var != 0 ? var->size() : 0; +} +inline CollectionData *variantToArray(VariantData *var) { + if (!var) return 0; + return &var->toArray(); +} +inline CollectionData *variantToObject(VariantData *var) { + if (!var) return 0; + return &var->toObject(); +} +inline NO_INLINE VariantData *variantAdd(VariantData *var, MemoryPool *pool) { + return var != 0 ? var->addElement(pool) : 0; +} +template +NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TChar *key, + MemoryPool *pool) { + return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0; +} +template +NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TString &key, + MemoryPool *pool) { + return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0; +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class ArrayRef; +class ObjectRef; +template +class MemberProxy; +template +class VariantRefBase { + public: + template + FORCE_INLINE typename enable_if::value, bool>::type is() + const { + return variantIsInteger(_data); + } + template + FORCE_INLINE typename enable_if::value, bool>::type is() + const { + return variantIsFloat(_data); + } + template + FORCE_INLINE typename enable_if::value, bool>::type is() + const { + return variantIsBoolean(_data); + } + template + FORCE_INLINE typename enable_if::value || + is_same::value || + IsWriteableString::value, + bool>::type + is() const { + return variantIsString(_data); + } + template + FORCE_INLINE typename enable_if< + is_same::type, ArrayRef>::value, bool>::type + is() const { + return variantIsArray(_data); + } + template + FORCE_INLINE typename enable_if< + is_same::type, ObjectRef>::value, bool>::type + is() const { + return variantIsObject(_data); + } + FORCE_INLINE bool isNull() const { + return variantIsNull(_data); + } + FORCE_INLINE bool isUndefined() const { + return !_data; + } + FORCE_INLINE size_t memoryUsage() const { + return _data ? _data->memoryUsage() : 0; + } + FORCE_INLINE size_t nesting() const { + return _data ? _data->nesting() : 0; + } + size_t size() const { + return variantSize(_data); + } + protected: + VariantRefBase(TData *data) : _data(data) {} + TData *_data; +}; +class VariantRef : public VariantRefBase, + public VariantOperators, + public Visitable { + typedef VariantRefBase base_type; + friend class VariantConstRef; + public: + FORCE_INLINE VariantRef(MemoryPool *pool, VariantData *data) + : base_type(data), _pool(pool) {} + FORCE_INLINE VariantRef() : base_type(0), _pool(0) {} + FORCE_INLINE void clear() const { + return variantSetNull(_data); + } + FORCE_INLINE bool set(bool value) const { + return variantSetBoolean(_data, value); + } + template + FORCE_INLINE bool set( + T value, + typename enable_if::value>::type * = 0) const { + return variantSetFloat(_data, static_cast(value)); + } + template + FORCE_INLINE bool set( + T value, + typename enable_if::value && is_signed::value>::type * = + 0) const { + return variantSetSignedInteger(_data, value); + } + template + FORCE_INLINE bool set( + T value, typename enable_if::value && + is_unsigned::value>::type * = 0) const { + return variantSetUnsignedInteger(_data, static_cast(value)); + } + FORCE_INLINE bool set(SerializedValue value) const { + return variantSetLinkedRaw(_data, value); + } + template + FORCE_INLINE bool set( + SerializedValue value, + typename enable_if::value>::type * = 0) const { + return variantSetOwnedRaw(_data, value, _pool); + } + template + FORCE_INLINE bool set( + const T &value, + typename enable_if::value>::type * = 0) const { + return variantSetOwnedString(_data, adaptString(value), _pool); + } + template + FORCE_INLINE bool set( + T *value, typename enable_if::value>::type * = 0) const { + return variantSetOwnedString(_data, adaptString(value), _pool); + } + FORCE_INLINE bool set(const char *value) const { + return variantSetLinkedString(_data, value); + } + template + typename enable_if::value, bool>::type set( + const TVariant &value) const; + template + FORCE_INLINE typename enable_if::value && + !is_same::value && + !is_same::value, + typename VariantAs::type>::type + as() const { + return variantAs(_data); + } + template + FORCE_INLINE typename enable_if::value, T>::type as() + const; + template + FORCE_INLINE typename enable_if::value, T>::type as() + const; + template + FORCE_INLINE typename enable_if::value, T>::type as() + const { + return *this; + } + template + void accept(Visitor &visitor) const { + variantAccept(_data, visitor); + } + FORCE_INLINE bool operator==(VariantRef lhs) const { + return variantEquals(_data, lhs._data); + } + FORCE_INLINE bool operator!=(VariantRef lhs) const { + return !variantEquals(_data, lhs._data); + } + template + typename enable_if::value, ArrayRef>::type to() const; + template + typename enable_if::value, ObjectRef>::type to() const; + template + typename enable_if::value, VariantRef>::type to() + const; + VariantRef addElement() const; + FORCE_INLINE VariantRef getElement(size_t) const; + template + FORCE_INLINE VariantRef getMember(TChar *) const; + template + FORCE_INLINE typename enable_if::value, VariantRef>::type + getMember(const TString &) const; + template + FORCE_INLINE VariantRef getOrAddMember(TChar *) const; + template + FORCE_INLINE VariantRef getOrAddMember(const TString &) const; + FORCE_INLINE void remove(size_t index) const { + if (_data) _data->remove(index); + } + template + FORCE_INLINE typename enable_if::value>::type remove( + TChar *key) const { + if (_data) _data->remove(adaptString(key)); + } + template + FORCE_INLINE typename enable_if::value>::type remove( + const TString &key) const { + if (_data) _data->remove(adaptString(key)); + } + private: + MemoryPool *_pool; +}; // namespace ARDUINOJSON_NAMESPACE +class VariantConstRef : public VariantRefBase, + public VariantOperators, + public Visitable { + typedef VariantRefBase base_type; + friend class VariantRef; + public: + 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 + FORCE_INLINE typename VariantConstAs::type as() const { + return variantAs::type>(_data); + } + FORCE_INLINE VariantConstRef operator[](size_t index) const; + template + FORCE_INLINE + typename enable_if::value, VariantConstRef>::type + operator[](const TString &key) const { + return VariantConstRef(objectGet(variantAsObject(_data), adaptString(key))); + } + template + FORCE_INLINE + typename enable_if::value, VariantConstRef>::type + operator[](TChar *key) const { + const CollectionData *obj = variantAsObject(_data); + return VariantConstRef(obj ? obj->get(adaptString(key)) : 0); + } +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class VariantPtr { + public: + VariantPtr(MemoryPool *pool, VariantData *data) : _variant(pool, data) {} + VariantRef *operator->() { + return &_variant; + } + VariantRef &operator*() { + return _variant; + } + private: + VariantRef _variant; +}; +class ArrayIterator { + public: + ArrayIterator() : _slot(0) {} + explicit ArrayIterator(MemoryPool *pool, VariantSlot *slot) + : _pool(pool), _slot(slot) {} + VariantRef operator*() const { + return VariantRef(_pool, _slot->data()); + } + VariantPtr operator->() { + return VariantPtr(_pool, _slot->data()); + } + bool operator==(const ArrayIterator &other) const { + return _slot == other._slot; + } + bool operator!=(const ArrayIterator &other) const { + return _slot != other._slot; + } + ArrayIterator &operator++() { + _slot = _slot->next(); + return *this; + } + ArrayIterator &operator+=(size_t distance) { + _slot = _slot->next(distance); + return *this; + } + VariantSlot *internal() { + return _slot; + } + private: + MemoryPool *_pool; + VariantSlot *_slot; +}; +class VariantConstPtr { + public: + VariantConstPtr(const VariantData *data) : _variant(data) {} + VariantConstRef *operator->() { + return &_variant; + } + VariantConstRef &operator*() { + return _variant; + } + private: + VariantConstRef _variant; +}; +class ArrayConstRefIterator { + public: + ArrayConstRefIterator() : _slot(0) {} + explicit ArrayConstRefIterator(const VariantSlot *slot) : _slot(slot) {} + VariantConstRef operator*() const { + return VariantConstRef(_slot->data()); + } + VariantConstPtr operator->() { + return VariantConstPtr(_slot->data()); + } + bool operator==(const ArrayConstRefIterator &other) const { + return _slot == other._slot; + } + bool operator!=(const ArrayConstRefIterator &other) const { + return _slot != other._slot; + } + ArrayConstRefIterator &operator++() { + _slot = _slot->next(); + return *this; + } + ArrayConstRefIterator &operator+=(size_t distance) { + _slot = _slot->next(distance); + return *this; + } + const VariantSlot *internal() { + return _slot; + } + private: + const VariantSlot *_slot; +}; +} // namespace ARDUINOJSON_NAMESPACE +#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \ + ((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot)) +namespace ARDUINOJSON_NAMESPACE { +class ObjectRef; +template +class ElementProxy; +template +class ArrayRefBase { + public: + operator VariantConstRef() const { + const void* data = _data; // prevent warning cast-align + return VariantConstRef(reinterpret_cast(data)); + } + template + FORCE_INLINE void accept(Visitor& visitor) const { + arrayAccept(_data, visitor); + } + FORCE_INLINE bool isNull() const { + return _data == 0; + } + FORCE_INLINE size_t memoryUsage() const { + return _data ? _data->memoryUsage() : 0; + } + FORCE_INLINE size_t nesting() const { + return _data ? _data->nesting() : 0; + } + FORCE_INLINE size_t size() const { + return _data ? _data->size() : 0; + } + protected: + ArrayRefBase(TData* data) : _data(data) {} + TData* _data; +}; +class ArrayConstRef : public ArrayRefBase, + public Visitable { + friend class ArrayRef; + typedef ArrayRefBase base_type; + public: + typedef ArrayConstRefIterator iterator; + FORCE_INLINE iterator begin() const { + if (!_data) return iterator(); + return iterator(_data->head()); + } + FORCE_INLINE iterator end() const { + return iterator(); + } + FORCE_INLINE ArrayConstRef() : base_type(0) {} + FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {} + FORCE_INLINE bool operator==(ArrayConstRef rhs) const { + return arrayEquals(_data, rhs._data); + } + FORCE_INLINE VariantConstRef operator[](size_t index) const { + return getElement(index); + } + FORCE_INLINE VariantConstRef getElement(size_t index) const { + return VariantConstRef(_data ? _data->get(index) : 0); + } +}; +class ArrayRef : public ArrayRefBase, + public ArrayShortcuts, + public Visitable { + typedef ArrayRefBase base_type; + public: + typedef ArrayIterator iterator; + FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {} + FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data) + : base_type(data), _pool(pool) {} + operator VariantRef() { + void* data = _data; // prevent warning cast-align + return VariantRef(_pool, reinterpret_cast(data)); + } + operator ArrayConstRef() const { + return ArrayConstRef(_data); + } + VariantRef addElement() const { + return VariantRef(_pool, arrayAdd(_data, _pool)); + } + FORCE_INLINE iterator begin() const { + if (!_data) return iterator(); + return iterator(_pool, _data->head()); + } + FORCE_INLINE iterator end() const { + return iterator(); + } + FORCE_INLINE bool set(ArrayConstRef src) const { + if (!_data || !src._data) return false; + return _data->copyFrom(*src._data, _pool); + } + FORCE_INLINE bool operator==(ArrayRef rhs) const { + return arrayEquals(_data, rhs._data); + } + FORCE_INLINE VariantRef getElement(size_t index) const { + return VariantRef(_pool, _data ? _data->get(index) : 0); + } + FORCE_INLINE void remove(iterator it) const { + if (!_data) return; + _data->remove(it.internal()); + } + FORCE_INLINE void remove(size_t index) const { + if (!_data) return; + _data->remove(index); + } + private: + MemoryPool* _pool; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +void objectAccept(const CollectionData *obj, Visitor &visitor) { + if (obj) + visitor.visitObject(*obj); + else + visitor.visitNull(); +} +inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) { + if (lhs == rhs) return true; + if (!lhs || !rhs) return false; + return lhs->equalsObject(*rhs); +} +template +inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) { + if (!obj) return 0; + return obj->get(key); +} +template +void objectRemove(CollectionData *obj, TAdaptedString key) { + if (!obj) return; + obj->remove(key); +} +template +inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key, + MemoryPool *pool) { + if (!obj) return 0; + if (key.isNull()) return 0; + VariantData *var = obj->get(key); + if (var) return var; + return obj->add(key, pool); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class String { + public: + String() : _data(0), _isStatic(true) {} + String(const char* data, bool isStaticData = true) + : _data(data), _isStatic(isStaticData) {} + const char* c_str() const { + return _data; + } + bool isNull() const { + return !_data; + } + bool isStatic() const { + return _isStatic; + } + friend bool operator==(String lhs, String rhs) { + if (lhs._data == rhs._data) return true; + if (!lhs._data) return false; + if (!rhs._data) return false; + return strcmp(lhs._data, rhs._data) == 0; + } + private: + const char* _data; + bool _isStatic; +}; +class StringAdapter : public RamStringAdapter { + public: + StringAdapter(const String& str) + : RamStringAdapter(str.c_str()), _isStatic(str.isStatic()) {} + bool isStatic() const { + return _isStatic; + } + /* const char* save(MemoryPool* pool) const { + if (_isStatic) return c_str(); + return RamStringAdapter::save(pool); + }*/ + private: + bool _isStatic; +}; +template <> +struct IsString : true_type {}; +inline StringAdapter adaptString(const String& str) { + return StringAdapter(str); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class Pair { + public: + Pair(MemoryPool* pool, VariantSlot* slot) { + if (slot) { + _key = String(slot->key(), !slot->ownsKey()); + _value = VariantRef(pool, slot->data()); + } + } + String key() const { + return _key; + } + VariantRef value() const { + return _value; + } + private: + String _key; + VariantRef _value; +}; +class PairConst { + public: + PairConst(const VariantSlot* slot) { + if (slot) { + _key = String(slot->key(), !slot->ownsKey()); + _value = VariantConstRef(slot->data()); + } + } + String key() const { + return _key; + } + VariantConstRef value() const { + return _value; + } + private: + String _key; + VariantConstRef _value; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class PairPtr { + public: + PairPtr(MemoryPool *pool, VariantSlot *slot) : _pair(pool, slot) {} + const Pair *operator->() const { + return &_pair; + } + const Pair &operator*() const { + return _pair; + } + private: + Pair _pair; +}; +class ObjectIterator { + public: + ObjectIterator() : _slot(0) {} + explicit ObjectIterator(MemoryPool *pool, VariantSlot *slot) + : _pool(pool), _slot(slot) {} + Pair operator*() const { + return Pair(_pool, _slot); + } + PairPtr operator->() { + return PairPtr(_pool, _slot); + } + bool operator==(const ObjectIterator &other) const { + return _slot == other._slot; + } + bool operator!=(const ObjectIterator &other) const { + return _slot != other._slot; + } + ObjectIterator &operator++() { + _slot = _slot->next(); + return *this; + } + ObjectIterator &operator+=(size_t distance) { + _slot = _slot->next(distance); + return *this; + } + VariantSlot *internal() { + return _slot; + } + private: + MemoryPool *_pool; + VariantSlot *_slot; +}; +class PairConstPtr { + public: + PairConstPtr(const VariantSlot *slot) : _pair(slot) {} + const PairConst *operator->() const { + return &_pair; + } + const PairConst &operator*() const { + return _pair; + } + private: + PairConst _pair; +}; +class ObjectConstIterator { + public: + ObjectConstIterator() : _slot(0) {} + explicit ObjectConstIterator(const VariantSlot *slot) : _slot(slot) {} + PairConst operator*() const { + return PairConst(_slot); + } + PairConstPtr operator->() { + return PairConstPtr(_slot); + } + bool operator==(const ObjectConstIterator &other) const { + return _slot == other._slot; + } + bool operator!=(const ObjectConstIterator &other) const { + return _slot != other._slot; + } + ObjectConstIterator &operator++() { + _slot = _slot->next(); + return *this; + } + ObjectConstIterator &operator+=(size_t distance) { + _slot = _slot->next(distance); + return *this; + } + const VariantSlot *internal() { + return _slot; + } + private: + const VariantSlot *_slot; +}; +} // namespace ARDUINOJSON_NAMESPACE +#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \ + ((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot)) +namespace ARDUINOJSON_NAMESPACE { +template +class ObjectRefBase { + public: + operator VariantConstRef() const { + const void* data = _data; // prevent warning cast-align + return VariantConstRef(reinterpret_cast(data)); + } + template + FORCE_INLINE void accept(Visitor& visitor) const { + objectAccept(_data, visitor); + } + FORCE_INLINE bool isNull() const { + return _data == 0; + } + FORCE_INLINE size_t memoryUsage() const { + return _data ? _data->memoryUsage() : 0; + } + FORCE_INLINE size_t nesting() const { + return _data ? _data->nesting() : 0; + } + FORCE_INLINE size_t size() const { + return _data ? _data->size() : 0; + } + protected: + ObjectRefBase(TData* data) : _data(data) {} + TData* _data; +}; +class ObjectConstRef : public ObjectRefBase, + public Visitable { + friend class ObjectRef; + typedef ObjectRefBase base_type; + public: + typedef ObjectConstIterator iterator; + ObjectConstRef() : base_type(0) {} + ObjectConstRef(const CollectionData* data) : base_type(data) {} + FORCE_INLINE iterator begin() const { + if (!_data) return iterator(); + return iterator(_data->head()); + } + FORCE_INLINE iterator end() const { + return iterator(); + } + template + FORCE_INLINE bool containsKey(const TString& key) const { + return !getMember(key).isUndefined(); + } + template + FORCE_INLINE bool containsKey(TChar* key) const { + return !getMember(key).isUndefined(); + } + template + FORCE_INLINE VariantConstRef getMember(const TString& key) const { + return get_impl(adaptString(key)); + } + template + FORCE_INLINE VariantConstRef getMember(TChar* key) const { + return get_impl(adaptString(key)); + } + template + FORCE_INLINE + typename enable_if::value, VariantConstRef>::type + operator[](const TString& key) const { + return get_impl(adaptString(key)); + } + template + FORCE_INLINE + typename enable_if::value, VariantConstRef>::type + operator[](TChar* key) const { + return get_impl(adaptString(key)); + } + FORCE_INLINE bool operator==(ObjectConstRef rhs) const { + return objectEquals(_data, rhs._data); + } + private: + template + FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const { + return VariantConstRef(objectGet(_data, key)); + } +}; +class ObjectRef : public ObjectRefBase, + public ObjectShortcuts, + public Visitable { + typedef ObjectRefBase base_type; + public: + typedef ObjectIterator iterator; + FORCE_INLINE ObjectRef() : base_type(0), _pool(0) {} + FORCE_INLINE ObjectRef(MemoryPool* buf, CollectionData* data) + : base_type(data), _pool(buf) {} + operator VariantRef() const { + void* data = _data; // prevent warning cast-align + return VariantRef(_pool, reinterpret_cast(data)); + } + operator ObjectConstRef() const { + return ObjectConstRef(_data); + } + FORCE_INLINE iterator begin() const { + if (!_data) return iterator(); + return iterator(_pool, _data->head()); + } + FORCE_INLINE iterator end() const { + return iterator(); + } + void clear() const { + if (!_data) return; + _data->clear(); + } + FORCE_INLINE bool set(ObjectConstRef src) { + if (!_data || !src._data) return false; + return _data->copyFrom(*src._data, _pool); + } + template + FORCE_INLINE VariantRef getMember(const TString& key) const { + return get_impl(adaptString(key)); + } + template + FORCE_INLINE VariantRef getMember(TChar* key) const { + return get_impl(adaptString(key)); + } + template + FORCE_INLINE VariantRef getOrAddMember(const TString& key) const { + return getOrCreate_impl(adaptString(key)); + } + template + FORCE_INLINE VariantRef getOrAddMember(TChar* key) const { + return getOrCreate_impl(adaptString(key)); + } + FORCE_INLINE bool operator==(ObjectRef rhs) const { + return objectEquals(_data, rhs._data); + } + FORCE_INLINE void remove(iterator it) const { + if (!_data) return; + _data->remove(it.internal()); + } + template + FORCE_INLINE void remove(const TString& key) const { + objectRemove(_data, adaptString(key)); + } + template + FORCE_INLINE void remove(TChar* key) const { + objectRemove(_data, adaptString(key)); + } + private: + template + FORCE_INLINE VariantRef get_impl(TAdaptedString key) const { + return VariantRef(_pool, objectGet(_data, key)); + } + template + FORCE_INLINE VariantRef getOrCreate_impl(TAdaptedString key) const { + return VariantRef(_pool, objectGetOrCreate(_data, key, _pool)); + } + MemoryPool* _pool; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class ArrayRef; +class ObjectRef; +class VariantRef; +template +struct VariantTo {}; +template <> +struct VariantTo { + typedef ArrayRef type; +}; +template <> +struct VariantTo { + typedef ObjectRef type; +}; +template <> +struct VariantTo { + typedef VariantRef type; +}; +} // namespace ARDUINOJSON_NAMESPACE +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4522) +#endif +namespace ARDUINOJSON_NAMESPACE { +template +class ElementProxy : public VariantOperators >, + public Visitable { + typedef ElementProxy this_type; + public: + FORCE_INLINE ElementProxy(TArray array, size_t index) + : _array(array), _index(index) {} + FORCE_INLINE this_type& operator=(const this_type& src) { + getUpstreamElement().set(src.as()); + return *this; + } + template + FORCE_INLINE this_type& operator=(const T& src) { + getUpstreamElement().set(src); + return *this; + } + template + FORCE_INLINE this_type& operator=(T* src) { + getUpstreamElement().set(src); + return *this; + } + FORCE_INLINE void clear() const { + getUpstreamElement().clear(); + } + FORCE_INLINE bool isNull() const { + return getUpstreamElement().isNull(); + } + template + FORCE_INLINE typename VariantAs::type as() const { + return getUpstreamElement().template as(); + } + template + FORCE_INLINE bool is() const { + return getUpstreamElement().template is(); + } + template + FORCE_INLINE typename VariantTo::type to() const { + return getUpstreamElement().template to(); + } + template + FORCE_INLINE bool set(const TValue& value) const { + return getUpstreamElement().set(value); + } + template + FORCE_INLINE bool set(TValue* value) const { + return getUpstreamElement().set(value); + } + template + void accept(Visitor& visitor) const { + return getUpstreamElement().accept(visitor); + } + FORCE_INLINE size_t size() const { + return getUpstreamElement().size(); + } + template + VariantRef getMember(TNestedKey* key) const { + return getUpstreamElement().getMember(key); + } + template + VariantRef getMember(const TNestedKey& key) const { + return getUpstreamElement().getMember(key); + } + template + VariantRef getOrAddMember(TNestedKey* key) const { + return getUpstreamElement().getOrAddMember(key); + } + template + VariantRef getOrAddMember(const TNestedKey& key) const { + return getUpstreamElement().getOrAddMember(key); + } + VariantRef addElement() const { + return getUpstreamElement().addElement(); + } + VariantRef getElement(size_t index) const { + return getUpstreamElement().getElement(index); + } + FORCE_INLINE void remove(size_t index) const { + getUpstreamElement().remove(index); + } + template + FORCE_INLINE typename enable_if::value>::type remove( + TChar* key) const { + getUpstreamElement().remove(key); + } + template + FORCE_INLINE typename enable_if::value>::type remove( + const TString& key) const { + getUpstreamElement().remove(key); + } + private: + FORCE_INLINE VariantRef getUpstreamElement() const { + return _array.getElement(_index); + } + TArray _array; + const size_t _index; +}; +template +inline ElementProxy ArrayShortcuts::operator[]( + size_t index) const { + return ElementProxy(*impl(), index); +} +} // namespace ARDUINOJSON_NAMESPACE +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4522) +#endif +namespace ARDUINOJSON_NAMESPACE { +template +class MemberProxy : public VariantOperators >, + public Visitable { + typedef MemberProxy this_type; + public: + FORCE_INLINE MemberProxy(TObject variant, TStringRef key) + : _object(variant), _key(key) {} + FORCE_INLINE operator VariantConstRef() const { + return getUpstreamMember(); + } + FORCE_INLINE this_type &operator=(const this_type &src) { + getOrAddUpstreamMember().set(src); + return *this; + } + template + FORCE_INLINE typename enable_if::value, this_type &>::type + operator=(const TValue &src) { + getOrAddUpstreamMember().set(src); + return *this; + } + template + FORCE_INLINE this_type &operator=(TChar *src) { + getOrAddUpstreamMember().set(src); + return *this; + } + FORCE_INLINE void clear() const { + getUpstreamMember().clear(); + } + FORCE_INLINE bool isNull() const { + return getUpstreamMember().isNull(); + } + template + FORCE_INLINE typename VariantAs::type as() const { + return getUpstreamMember().template as(); + } + template + FORCE_INLINE bool is() const { + return getUpstreamMember().template is(); + } + FORCE_INLINE size_t size() const { + return getUpstreamMember().size(); + } + FORCE_INLINE void remove(size_t index) const { + getUpstreamMember().remove(index); + } + template + FORCE_INLINE typename enable_if::value>::type remove( + TChar *key) const { + getUpstreamMember().remove(key); + } + template + FORCE_INLINE typename enable_if::value>::type remove( + const TString &key) const { + getUpstreamMember().remove(key); + } + template + FORCE_INLINE typename VariantTo::type to() { + return getOrAddUpstreamMember().template to(); + } + template + FORCE_INLINE typename enable_if::value, bool>::type set( + const TValue &value) { + return getOrAddUpstreamMember().set(value); + } + template + FORCE_INLINE bool set(const TChar *value) { + return getOrAddUpstreamMember().set(value); + } + template + void accept(Visitor &visitor) const { + return getUpstreamMember().accept(visitor); + } + FORCE_INLINE VariantRef addElement() const { + return getOrAddUpstreamMember().addElement(); + } + FORCE_INLINE VariantRef getElement(size_t index) const { + return getUpstreamMember().getElement(index); + } + template + FORCE_INLINE VariantRef getMember(TChar *key) const { + return getUpstreamMember().getMember(key); + } + template + FORCE_INLINE VariantRef getMember(const TString &key) const { + return getUpstreamMember().getMember(key); + } + template + FORCE_INLINE VariantRef getOrAddMember(TChar *key) const { + return getOrAddUpstreamMember().getOrAddMember(key); + } + template + FORCE_INLINE VariantRef getOrAddMember(const TString &key) const { + return getOrAddUpstreamMember().getOrAddMember(key); + } + private: + FORCE_INLINE VariantRef getUpstreamMember() const { + return _object.getMember(_key); + } + FORCE_INLINE VariantRef getOrAddUpstreamMember() const { + return _object.getOrAddMember(_key); + } + TObject _object; + TStringRef _key; +}; +template +template +inline typename enable_if::value, + MemberProxy >::type + ObjectShortcuts::operator[](const TString &key) const { + return MemberProxy(*impl(), key); +} +template +template +inline typename enable_if::value, + MemberProxy >::type + ObjectShortcuts::operator[](TString *key) const { + return MemberProxy(*impl(), key); +} +} // namespace ARDUINOJSON_NAMESPACE +#ifdef _MSC_VER +#pragma warning(pop) +#endif +namespace ARDUINOJSON_NAMESPACE { +class JsonDocument : public Visitable { + public: + template + void accept(Visitor& visitor) const { + return getVariant().accept(visitor); + } + template + typename VariantAs::type as() { + return getVariant().template as(); + } + template + typename VariantConstAs::type as() const { + return getVariant().template as(); + } + void clear() { + _pool.clear(); + _data.setNull(); + } + template + bool is() const { + return getVariant().template is(); + } + bool isNull() const { + return getVariant().isNull(); + } + size_t memoryUsage() const { + return _pool.size(); + } + size_t nesting() const { + return _data.nesting(); + } + size_t capacity() const { + return _pool.capacity(); + } + size_t size() const { + return _data.size(); + } + bool set(const JsonDocument& src) { + return to().set(src.as()); + } + template + typename enable_if::value, bool>::type set( + const T& src) { + return to().set(src); + } + template + typename VariantTo::type to() { + clear(); + return getVariant().template to(); + } + MemoryPool& memoryPool() { + return _pool; + } + VariantData& data() { + return _data; + } + ArrayRef createNestedArray() { + return addElement().to(); + } + template + ArrayRef createNestedArray(TChar* key) { + return getOrAddMember(key).template to(); + } + template + ArrayRef createNestedArray(const TString& key) { + return getOrAddMember(key).template to(); + } + ObjectRef createNestedObject() { + return addElement().to(); + } + template + ObjectRef createNestedObject(TChar* key) { + return getOrAddMember(key).template to(); + } + template + ObjectRef createNestedObject(const TString& key) { + return getOrAddMember(key).template to(); + } + template + bool containsKey(TChar* key) const { + return !getMember(key).isUndefined(); + } + template + bool containsKey(const TString& key) const { + return !getMember(key).isUndefined(); + } + template + FORCE_INLINE + typename enable_if::value, + MemberProxy >::type + operator[](const TString& key) { + return MemberProxy(*this, key); + } + template + FORCE_INLINE typename enable_if::value, + MemberProxy >::type + operator[](TChar* key) { + return MemberProxy(*this, key); + } + template + FORCE_INLINE + typename enable_if::value, VariantConstRef>::type + operator[](const TString& key) const { + return getMember(key); + } + template + FORCE_INLINE + typename enable_if::value, VariantConstRef>::type + operator[](TChar* key) const { + return getMember(key); + } + FORCE_INLINE ElementProxy operator[](size_t index) { + return ElementProxy(*this, index); + } + FORCE_INLINE VariantConstRef operator[](size_t index) const { + return getElement(index); + } + FORCE_INLINE VariantRef getElement(size_t index) { + return VariantRef(&_pool, _data.getElement(index)); + } + FORCE_INLINE VariantConstRef getElement(size_t index) const { + return VariantConstRef(_data.getElement(index)); + } + template + FORCE_INLINE VariantConstRef getMember(TChar* key) const { + return VariantConstRef(_data.getMember(adaptString(key))); + } + template + FORCE_INLINE + typename enable_if::value, VariantConstRef>::type + getMember(const TString& key) const { + return VariantConstRef(_data.getMember(adaptString(key))); + } + template + FORCE_INLINE VariantRef getMember(TChar* key) { + return VariantRef(&_pool, _data.getMember(adaptString(key))); + } + template + FORCE_INLINE typename enable_if::value, VariantRef>::type + getMember(const TString& key) { + return VariantRef(&_pool, _data.getMember(adaptString(key))); + } + template + FORCE_INLINE VariantRef getOrAddMember(TChar* key) { + return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool)); + } + template + FORCE_INLINE VariantRef getOrAddMember(const TString& key) { + return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool)); + } + FORCE_INLINE VariantRef addElement() { + return VariantRef(&_pool, _data.addElement(&_pool)); + } + template + FORCE_INLINE bool add(const TValue& value) { + return addElement().set(value); + } + template + FORCE_INLINE bool add(TChar* value) { + return addElement().set(value); + } + FORCE_INLINE void remove(size_t index) { + _data.remove(index); + } + template + FORCE_INLINE typename enable_if::value>::type remove( + TChar* key) { + _data.remove(adaptString(key)); + } + template + FORCE_INLINE typename enable_if::value>::type remove( + const TString& key) { + _data.remove(adaptString(key)); + } + protected: + JsonDocument(MemoryPool pool) : _pool(pool) { + _data.setNull(); + } + JsonDocument(char* buf, size_t capa) : _pool(buf, capa) { + _data.setNull(); + } + void replacePool(MemoryPool pool) { + _pool = pool; + } + private: + VariantRef getVariant() { + return VariantRef(&_pool, &_data); + } + VariantConstRef getVariant() const { + return VariantConstRef(&_data); + } + MemoryPool _pool; + VariantData _data; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +class AllocatorOwner { + protected: + AllocatorOwner() {} + AllocatorOwner(const AllocatorOwner& src) : _allocator(src._allocator) {} + AllocatorOwner(TAllocator allocator) : _allocator(allocator) {} + void* allocate(size_t n) { + return _allocator.allocate(n); + } + void deallocate(void* p) { + _allocator.deallocate(p); + } + private: + TAllocator _allocator; +}; +template +class BasicJsonDocument : AllocatorOwner, public JsonDocument { + public: + explicit BasicJsonDocument(size_t capa, TAllocator allocator = TAllocator()) + : AllocatorOwner(allocator), JsonDocument(allocPool(capa)) {} + BasicJsonDocument(const BasicJsonDocument& src) + : AllocatorOwner(src), + JsonDocument(allocPool(src.memoryUsage())) { + set(src); + } + template + BasicJsonDocument(const T& src, + typename enable_if::value>::type* = 0) + : JsonDocument(allocPool(src.memoryUsage())) { + set(src); + } + BasicJsonDocument(VariantRef src) + : JsonDocument(allocPool(src.memoryUsage())) { + set(src); + } + ~BasicJsonDocument() { + freePool(); + } + BasicJsonDocument& operator=(const BasicJsonDocument& src) { + reallocPoolIfTooSmall(src.memoryUsage()); + set(src); + return *this; + } + template + BasicJsonDocument& operator=(const T& src) { + reallocPoolIfTooSmall(src.memoryUsage()); + set(src); + return *this; + } + private: + MemoryPool allocPool(size_t requiredSize) { + size_t capa = addPadding(requiredSize); + return MemoryPool(reinterpret_cast(this->allocate(capa)), capa); + } + void reallocPoolIfTooSmall(size_t requiredSize) { + if (requiredSize <= capacity()) return; + freePool(); + replacePool(allocPool(addPadding(requiredSize))); + } + void freePool() { + this->deallocate(memoryPool().buffer()); + } +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +struct DefaultAllocator { + void* allocate(size_t n) { + return malloc(n); + } + void deallocate(void* p) { + free(p); + } +}; +typedef BasicJsonDocument DynamicJsonDocument; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +class StaticJsonDocument : public JsonDocument { + static const size_t _capacity = + AddPadding::value>::value; + public: + StaticJsonDocument() : JsonDocument(_buffer, _capacity) {} + StaticJsonDocument(const StaticJsonDocument& src) + : JsonDocument(_buffer, _capacity) { + set(src); + } + template + StaticJsonDocument(const T& src, + typename enable_if::value>::type* = 0) + : JsonDocument(_buffer, _capacity) { + set(src); + } + StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, _capacity) { + set(src); + } + StaticJsonDocument operator=(const StaticJsonDocument& src) { + set(src); + return *this; + } + template + StaticJsonDocument operator=(const T& src) { + set(src); + return *this; + } + private: + char _buffer[_capacity]; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +inline ArrayRef ArrayShortcuts::createNestedArray() const { + return impl()->addElement().template to(); +} +template +inline ObjectRef ArrayShortcuts::createNestedObject() const { + return impl()->addElement().template to(); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +inline bool copyArray(T (&src)[N], ArrayRef dst) { + return copyArray(src, N, dst); +} +template +inline bool copyArray(T* src, size_t len, ArrayRef dst) { + bool ok = true; + for (size_t i = 0; i < len; i++) { + ok &= dst.add(src[i]); + } + return ok; +} +template +inline bool copyArray(T (&src)[N1][N2], ArrayRef dst) { + bool ok = true; + for (size_t i = 0; i < N1; i++) { + ArrayRef nestedArray = dst.createNestedArray(); + for (size_t j = 0; j < N2; j++) { + ok &= nestedArray.add(src[i][j]); + } + } + return ok; +} +template +inline size_t copyArray(ArrayConstRef src, T (&dst)[N]) { + return copyArray(src, dst, N); +} +template +inline size_t copyArray(ArrayConstRef src, T* dst, size_t len) { + size_t i = 0; + for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < len; + ++it) + dst[i++] = *it; + return i; +} +template +inline void copyArray(ArrayConstRef src, T (&dst)[N1][N2]) { + size_t i = 0; + for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < N1; + ++it) { + copyArray(it->as(), dst[i++]); + } +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) { + VariantSlot* slot = pool->allocVariant(); + if (!slot) return 0; + if (_tail) { + _tail->setNextNotNull(slot); + _tail = slot; + } else { + _head = slot; + _tail = slot; + } + slot->clear(); + return slot; +} +inline VariantData* CollectionData::add(MemoryPool* pool) { + return slotData(addSlot(pool)); +} +template +inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) { + VariantSlot* slot = addSlot(pool); + if (!slotSetKey(slot, key, pool)) return 0; + return slot->data(); +} +inline void CollectionData::clear() { + _head = 0; + _tail = 0; +} +template +inline bool CollectionData::containsKey(const TAdaptedString& key) const { + return getSlot(key) != 0; +} +inline bool CollectionData::copyFrom(const CollectionData& src, + MemoryPool* pool) { + clear(); + for (VariantSlot* s = src._head; s; s = s->next()) { + VariantData* var; + if (s->key() != 0) { + if (s->ownsKey()) + var = add(RamStringAdapter(s->key()), pool); + else + var = add(ConstRamStringAdapter(s->key()), pool); + } else { + var = add(pool); + } + if (!var) return false; + if (!var->copyFrom(*s->data(), pool)) return false; + } + return true; +} +inline bool CollectionData::equalsObject(const CollectionData& other) const { + size_t count = 0; + for (VariantSlot* slot = _head; slot; slot = slot->next()) { + VariantData* v1 = slot->data(); + VariantData* v2 = other.get(adaptString(slot->key())); + if (!variantEquals(v1, v2)) return false; + count++; + } + return count == other.size(); +} +inline bool CollectionData::equalsArray(const CollectionData& other) const { + VariantSlot* s1 = _head; + VariantSlot* s2 = other._head; + for (;;) { + if (s1 == s2) return true; + if (!s1 || !s2) return false; + if (!variantEquals(s1->data(), s2->data())) return false; + s1 = s1->next(); + s2 = s2->next(); + } +} +template +inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const { + VariantSlot* slot = _head; + while (slot) { + if (key.equals(slot->key())) break; + slot = slot->next(); + } + return slot; +} +inline VariantSlot* CollectionData::getSlot(size_t index) const { + return _head->next(index); +} +inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const { + VariantSlot* current = _head; + while (current) { + VariantSlot* next = current->next(); + if (next == target) return current; + current = next; + } + return 0; +} +template +inline VariantData* CollectionData::get(TAdaptedString key) const { + VariantSlot* slot = getSlot(key); + return slot ? slot->data() : 0; +} +inline VariantData* CollectionData::get(size_t index) const { + VariantSlot* slot = getSlot(index); + return slot ? slot->data() : 0; +} +inline void CollectionData::remove(VariantSlot* slot) { + if (!slot) return; + VariantSlot* prev = getPreviousSlot(slot); + VariantSlot* next = slot->next(); + if (prev) + prev->setNext(next); + else + _head = next; + if (!next) _tail = prev; +} +inline void CollectionData::remove(size_t index) { + remove(getSlot(index)); +} +inline size_t CollectionData::memoryUsage() const { + size_t total = 0; + for (VariantSlot* s = _head; s; s = s->next()) { + total += sizeof(VariantSlot) + s->data()->memoryUsage(); + if (s->ownsKey()) total += strlen(s->key()) + 1; + } + return total; +} +inline size_t CollectionData::nesting() const { + size_t maxChildNesting = 0; + for (VariantSlot* s = _head; s; s = s->next()) { + size_t childNesting = s->data()->nesting(); + if (childNesting > maxChildNesting) maxChildNesting = childNesting; + } + return maxChildNesting + 1; +} +inline size_t CollectionData::size() const { + return slotSize(_head); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +template +inline ArrayRef ObjectShortcuts::createNestedArray( + const TString& key) const { + return impl()->getOrAddMember(key).template to(); +} +template +template +inline ArrayRef ObjectShortcuts::createNestedArray(TChar* key) const { + return impl()->getOrAddMember(key).template to(); +} +template +template +inline ObjectRef ObjectShortcuts::createNestedObject( + const TString& key) const { + return impl()->getOrAddMember(key).template to(); +} +template +template +inline ObjectRef ObjectShortcuts::createNestedObject( + TChar* key) const { + return impl()->getOrAddMember(key).template to(); +} +template +template +inline typename enable_if::value, bool>::type +ObjectShortcuts::containsKey(const TString& key) const { + return !impl()->getMember(key).isUndefined(); +} +template +template +inline typename enable_if::value, bool>::type +ObjectShortcuts::containsKey(TChar* key) const { + return !impl()->getMember(key).isUndefined(); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +inline typename enable_if::value, T>::type variantAs( + const VariantData* _data) { + return ArrayConstRef(variantAsArray(_data)); +} +template +inline typename enable_if::value, T>::type variantAs( + const VariantData* _data) { + return ObjectConstRef(variantAsObject(_data)); +} +template +inline typename enable_if::value, T>::type +variantAs(const VariantData* _data) { + return VariantConstRef(_data); +} +template +inline typename enable_if::value, T>::type variantAs( + const VariantData* _data) { + const char* cstr = _data != 0 ? _data->asString() : 0; + if (cstr) return T(cstr); + T s; + serializeJson(VariantConstRef(_data), s); + return s; +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +inline bool isdigit(char c) { + return '0' <= c && c <= '9'; +} +inline bool issign(char c) { + return '-' == c || c == '+'; +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct ParsedNumber { + ParsedNumber() : uintValue(0), floatValue(0), _type(VALUE_IS_NULL) {} + ParsedNumber(TUInt value, bool is_negative) + : uintValue(value), + floatValue(TFloat(value)), + _type(uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER + : VALUE_IS_POSITIVE_INTEGER)) {} + ParsedNumber(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; + } + TUInt uintValue; + TFloat floatValue; + uint8_t _type; +}; +template +struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {}; +template +inline ParsedNumber parseNumber(const char *s) { + typedef FloatTraits traits; + typedef typename choose_largest::type + mantissa_t; + typedef typename traits::exponent_type exponent_t; + typedef ParsedNumber return_type; + ARDUINOJSON_ASSERT(s != 0); + bool is_negative = false; + switch (*s) { + case '-': + is_negative = true; + s++; + break; + case '+': + s++; + break; + } +#if ARDUINOJSON_ENABLE_NAN + if (*s == 'n' || *s == 'N') return traits::nan(); +#endif +#if ARDUINOJSON_ENABLE_INFINITY + if (*s == 'i' || *s == 'I') + return is_negative ? -traits::inf() : traits::inf(); +#endif + if (!isdigit(*s) && *s != '.') return return_type(); + mantissa_t mantissa = 0; + exponent_t exponent_offset = 0; + const mantissa_t maxUint = TUInt(-1); + while (isdigit(*s)) { + uint8_t digit = uint8_t(*s - '0'); + if (mantissa > maxUint / 10) break; + mantissa *= 10; + if (mantissa > maxUint - digit) break; + mantissa += digit; + s++; + } + if (*s == '\0') return return_type(TUInt(mantissa), is_negative); + while (mantissa > traits::mantissa_max) { + mantissa /= 10; + exponent_offset++; + } + while (isdigit(*s)) { + exponent_offset++; + s++; + } + if (*s == '.') { + s++; + while (isdigit(*s)) { + if (mantissa < traits::mantissa_max / 10) { + mantissa = mantissa * 10 + uint8_t(*s - '0'); + exponent_offset--; + } + s++; + } + } + int exponent = 0; + if (*s == 'e' || *s == 'E') { + s++; + bool negative_exponent = false; + if (*s == '-') { + negative_exponent = true; + s++; + } else if (*s == '+') { + s++; + } + while (isdigit(*s)) { + exponent = exponent * 10 + (*s - '0'); + if (exponent + exponent_offset > traits::exponent_max) { + if (negative_exponent) + return is_negative ? -0.0f : 0.0f; + else + return is_negative ? -traits::inf() : traits::inf(); + } + s++; + } + if (negative_exponent) exponent = -exponent; + } + exponent += exponent_offset; + if (*s != '\0') return return_type(); + TFloat result = traits::make_float(static_cast(mantissa), exponent); + return is_negative ? -result : result; +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +inline T parseFloat(const char* s) { + typedef typename choose_largest::type TFloat; + return parseNumber(s).template as(); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +T parseInteger(const char *s) { + typedef typename choose_largest::type>::type + TUInt; + return parseNumber(s).template as(); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +inline T VariantData::asIntegral() const { + switch (type()) { + case VALUE_IS_POSITIVE_INTEGER: + case VALUE_IS_BOOLEAN: + return convertPositiveInteger(_content.asInteger); + case VALUE_IS_NEGATIVE_INTEGER: + return convertNegativeInteger(_content.asInteger); + case VALUE_IS_LINKED_STRING: + case VALUE_IS_OWNED_STRING: + return parseInteger(_content.asString); + case VALUE_IS_FLOAT: + return convertFloat(_content.asFloat); + default: + return 0; + } +} +inline bool VariantData::asBoolean() const { + switch (type()) { + case VALUE_IS_POSITIVE_INTEGER: + case VALUE_IS_BOOLEAN: + case VALUE_IS_NEGATIVE_INTEGER: + return _content.asInteger != 0; + case VALUE_IS_FLOAT: + return _content.asFloat != 0; + case VALUE_IS_LINKED_STRING: + case VALUE_IS_OWNED_STRING: + return strcmp("true", _content.asString) == 0; + default: + return false; + } +} +template +inline T VariantData::asFloat() const { + switch (type()) { + case VALUE_IS_POSITIVE_INTEGER: + case VALUE_IS_BOOLEAN: + return static_cast(_content.asInteger); + case VALUE_IS_NEGATIVE_INTEGER: + return -static_cast(_content.asInteger); + case VALUE_IS_LINKED_STRING: + case VALUE_IS_OWNED_STRING: + return parseFloat(_content.asString); + case VALUE_IS_FLOAT: + return static_cast(_content.asFloat); + default: + return 0; + } +} +inline const char *VariantData::asString() const { + switch (type()) { + case VALUE_IS_LINKED_STRING: + case VALUE_IS_OWNED_STRING: + return _content.asString; + default: + return 0; + } +} +template +typename enable_if::value, bool>::type VariantRef::set( + const TVariant &value) const { + VariantConstRef v = value; + return variantCopyFrom(_data, v._data, _pool); +} +template +inline typename enable_if::value, T>::type VariantRef::as() + const { + return ArrayRef(_pool, _data != 0 ? _data->asArray() : 0); +} +template +inline typename enable_if::value, T>::type +VariantRef::as() const { + return ObjectRef(_pool, variantAsObject(_data)); +} +template +inline typename enable_if::value, ArrayRef>::type +VariantRef::to() const { + return ArrayRef(_pool, variantToArray(_data)); +} +template +typename enable_if::value, ObjectRef>::type +VariantRef::to() const { + return ObjectRef(_pool, variantToObject(_data)); +} +template +typename enable_if::value, VariantRef>::type +VariantRef::to() const { + variantSetNull(_data); + return *this; +} +inline VariantConstRef VariantConstRef::operator[](size_t index) const { + return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index]; +} +inline VariantRef VariantRef::addElement() const { + return VariantRef(_pool, variantAdd(_data, _pool)); +} +inline VariantRef VariantRef::getElement(size_t index) const { + return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0); +} +template +inline VariantRef VariantRef::getMember(TChar *key) const { + return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0); +} +template +inline typename enable_if::value, VariantRef>::type +VariantRef::getMember(const TString &key) const { + return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0); +} +template +inline VariantRef VariantRef::getOrAddMember(TChar *key) const { + return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); +} +template +inline VariantRef VariantRef::getOrAddMember(const TString &key) const { + return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class StringBuilder { + public: + explicit StringBuilder(MemoryPool* parent) : _parent(parent), _size(0) { + _slot = _parent->allocExpandableString(); + } + void append(const char* s) { + while (*s) append(*s++); + } + void append(const char* s, size_t n) { + while (n-- > 0) append(*s++); + } + void append(char c) { + if (!_slot.value) return; + if (_size >= _slot.size) { + _slot.value = 0; + return; + } + _slot.value[_size++] = c; + } + char* complete() { + append('\0'); + if (_slot.value) { + _parent->freezeString(_slot, _size); + } + return _slot.value; + } + private: + MemoryPool* _parent; + size_t _size; + StringSlot _slot; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class StringCopier { + public: + typedef ARDUINOJSON_NAMESPACE::StringBuilder StringBuilder; + StringCopier(MemoryPool* pool) : _pool(pool) {} + StringBuilder startString() { + return StringBuilder(_pool); + } + private: + MemoryPool* _pool; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +class StringMover { + public: + class StringBuilder { + public: + StringBuilder(char** ptr) : _writePtr(ptr), _startPtr(*ptr) {} + void append(char c) { + *(*_writePtr)++ = char(c); + } + char* complete() const { + *(*_writePtr)++ = 0; + return _startPtr; + } + private: + char** _writePtr; + char* _startPtr; + }; + StringMover(char* ptr) : _ptr(ptr) {} + StringBuilder startString() { + return StringBuilder(&_ptr); + } + private: + char* _ptr; +}; +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +template +struct StringStorage { + typedef StringCopier type; + static type create(MemoryPool& pool, TInput&) { + return type(&pool); + } +}; +template +struct StringStorage::value>::type> { + typedef StringMover type; + static type create(MemoryPool&, TChar* input) { + return type(reinterpret_cast(input)); + } +}; +template +typename StringStorage::type makeStringStorage(MemoryPool& pool, + TInput& input) { + return StringStorage::create(pool, input); +} +template +typename StringStorage::type makeStringStorage(MemoryPool& pool, + TChar* input) { + return StringStorage::create(pool, input); +} +} // namespace ARDUINOJSON_NAMESPACE +#if ARDUINOJSON_ENABLE_ARDUINO_STREAM +#include +namespace ARDUINOJSON_NAMESPACE { +struct ArduinoStreamReader { + Stream& _stream; + public: + explicit ArduinoStreamReader(Stream& stream) : _stream(stream) {} + int read() { + uint8_t c; + return _stream.readBytes(&c, 1) ? c : -1; + } +}; +inline ArduinoStreamReader makeReader(Stream& input) { + return ArduinoStreamReader(input); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +namespace ARDUINOJSON_NAMESPACE { +template +struct IsCharOrVoid { + static const bool value = + is_same::value || is_same::value || + is_same::value || is_same::value; +}; +template +struct IsCharOrVoid : IsCharOrVoid {}; +class UnsafeCharPointerReader { + const char* _ptr; + public: + explicit UnsafeCharPointerReader(const char* ptr) + : _ptr(ptr ? ptr : reinterpret_cast("")) {} + int read() { + return static_cast(*_ptr++); + } +}; +class SafeCharPointerReader { + const char* _ptr; + const char* _end; + public: + explicit SafeCharPointerReader(const char* ptr, size_t len) + : _ptr(ptr ? ptr : reinterpret_cast("")), _end(_ptr + len) {} + int read() { + if (_ptr < _end) + return static_cast(*_ptr++); + else + return -1; + } +}; +template +inline typename enable_if::value, + UnsafeCharPointerReader>::type +makeReader(TChar* input) { + return UnsafeCharPointerReader(reinterpret_cast(input)); +} +template +inline + typename enable_if::value, SafeCharPointerReader>::type + makeReader(TChar* input, size_t n) { + return SafeCharPointerReader(reinterpret_cast(input), n); +} +#if ARDUINOJSON_ENABLE_ARDUINO_STRING +inline SafeCharPointerReader makeReader(const ::String& input) { + return SafeCharPointerReader(input.c_str(), input.length()); +} +#endif +} // namespace ARDUINOJSON_NAMESPACE +#if ARDUINOJSON_ENABLE_STD_STREAM +#include +#endif +namespace ARDUINOJSON_NAMESPACE { +class DeserializationError { + typedef void (DeserializationError::*bool_type)() const; + void safeBoolHelper() const {} + public: + enum Code { + Ok, + IncompleteInput, + InvalidInput, + NoMemory, + NotSupported, + TooDeep + }; + DeserializationError() {} + DeserializationError(Code c) : _code(c) {} + friend bool operator==(const DeserializationError& lhs, + const DeserializationError& rhs) { + return lhs._code == rhs._code; + } + friend bool operator!=(const DeserializationError& lhs, + const DeserializationError& rhs) { + return lhs._code != rhs._code; + } + friend bool operator==(const DeserializationError& lhs, Code rhs) { + return lhs._code == rhs; + } + friend bool operator==(Code lhs, const DeserializationError& rhs) { + return lhs == rhs._code; + } + friend bool operator!=(const DeserializationError& lhs, Code rhs) { + return lhs._code != rhs; + } + friend bool operator!=(Code lhs, const DeserializationError& rhs) { + return lhs != rhs._code; + } + operator bool_type() const { + return _code != Ok ? &DeserializationError::safeBoolHelper : 0; + } + friend bool operator==(bool value, const DeserializationError& err) { + return static_cast(err) == value; + } + friend bool operator==(const DeserializationError& err, bool value) { + return static_cast(err) == value; + } + friend bool operator!=(bool value, const DeserializationError& err) { + return static_cast(err) != value; + } + friend bool operator!=(const DeserializationError& err, bool value) { + return static_cast(err) != value; + } + Code code() const { + 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 "???"; + } + } + private: + Code _code; +}; +#if ARDUINOJSON_ENABLE_STD_STREAM +inline std::ostream& operator<<(std::ostream& s, + const DeserializationError& e) { + s << e.c_str(); + return s; +} +inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) { + s << DeserializationError(c).c_str(); + return s; +} +#endif +} // namespace ARDUINOJSON_NAMESPACE +#if ARDUINOJSON_ENABLE_PROGMEM +namespace ARDUINOJSON_NAMESPACE { +class UnsafeFlashStringReader { + const char* _ptr; + public: + explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr) + : _ptr(reinterpret_cast(ptr)) {} + int read() { + return pgm_read_byte_near(_ptr++); + } +}; +class SafeFlashStringReader { + const char* _ptr; + const char* _end; + public: + explicit SafeFlashStringReader(const __FlashStringHelper* ptr, size_t size) + : _ptr(reinterpret_cast(ptr)), _end(_ptr + size) {} + int read() { + if (_ptr < _end) + return pgm_read_byte_near(_ptr++); + else + return -1; + } +}; +inline UnsafeFlashStringReader makeReader(const __FlashStringHelper* input) { + return UnsafeFlashStringReader(input); +} +inline SafeFlashStringReader makeReader(const __FlashStringHelper* input, + size_t size) { + return SafeFlashStringReader(input, size); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +namespace ARDUINOJSON_NAMESPACE { +template +class IteratorReader { + TIterator _ptr, _end; + public: + explicit IteratorReader(TIterator begin, TIterator end) + : _ptr(begin), _end(end) {} + int read() { + if (_ptr < _end) + return static_cast(*_ptr++); + else + return -1; + } +}; +template +inline IteratorReader makeReader( + const TInput& input) { + return IteratorReader(input.begin(), + input.end()); +} +} // namespace ARDUINOJSON_NAMESPACE +namespace ARDUINOJSON_NAMESPACE { +struct NestingLimit { + NestingLimit() : value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {} + explicit NestingLimit(uint8_t n) : value(n) {} + uint8_t value; +}; +} // namespace ARDUINOJSON_NAMESPACE +#if ARDUINOJSON_ENABLE_STD_STREAM +#include +namespace ARDUINOJSON_NAMESPACE { +class StdStreamReader { + std::istream& _stream; + char _current; + public: + explicit StdStreamReader(std::istream& stream) + : _stream(stream), _current(0) {} + int read() { + return _stream.get(); + } + private: + StdStreamReader& operator=(const StdStreamReader&); // Visual Studio C4512 +}; +inline StdStreamReader makeReader(std::istream& input) { + return StdStreamReader(input); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +namespace ARDUINOJSON_NAMESPACE { +template