8#ifndef FASTLED_JSON_GUARD 
    9#error "You must include json.h instead of json.hpp" 
   16#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_VER < 1910) 
   17#  error ArduinoJson requires C++11 or newer. Configure your compiler for C++11 or downgrade ArduinoJson to 6.20. 
   19#ifndef ARDUINOJSON_ENABLE_STD_STREAM 
   21#    if __has_include(<istream>) && \ 
   22    __has_include(<ostream>) && \ 
   25#      define ARDUINOJSON_ENABLE_STD_STREAM 1 
   27#      define ARDUINOJSON_ENABLE_STD_STREAM 0 
   31#      define ARDUINOJSON_ENABLE_STD_STREAM 0 
   33#      define ARDUINOJSON_ENABLE_STD_STREAM 1 
   37#ifndef ARDUINOJSON_ENABLE_STD_STRING 
   39#    if __has_include(<string>) && !defined(min) && !defined(max) 
   40#      define ARDUINOJSON_ENABLE_STD_STRING 1 
   42#      define ARDUINOJSON_ENABLE_STD_STRING 0 
   46#      define ARDUINOJSON_ENABLE_STD_STRING 0 
   48#      define ARDUINOJSON_ENABLE_STD_STRING 1 
   52#ifndef ARDUINOJSON_ENABLE_STRING_VIEW 
   54#    if __has_include(<string_view>) && __cplusplus >= 201703L 
   55#      define ARDUINOJSON_ENABLE_STRING_VIEW 1 
   57#      define ARDUINOJSON_ENABLE_STRING_VIEW 0 
   60#    define ARDUINOJSON_ENABLE_STRING_VIEW 0 
   63#ifndef ARDUINOJSON_SIZEOF_POINTER 
   64#  if defined(__SIZEOF_POINTER__) 
   65#    define ARDUINOJSON_SIZEOF_POINTER __SIZEOF_POINTER__ 
   66#  elif defined(_WIN64) && _WIN64 
   67#    define ARDUINOJSON_SIZEOF_POINTER 8   
   69#    define ARDUINOJSON_SIZEOF_POINTER 4   
   72#ifndef ARDUINOJSON_USE_DOUBLE 
   73#  if ARDUINOJSON_SIZEOF_POINTER >= 4   
   74#    define ARDUINOJSON_USE_DOUBLE 1 
   76#    define ARDUINOJSON_USE_DOUBLE 0 
   79#ifndef ARDUINOJSON_USE_LONG_LONG 
   80#  if ARDUINOJSON_SIZEOF_POINTER >= 4   
   81#    define ARDUINOJSON_USE_LONG_LONG 1 
   83#    define ARDUINOJSON_USE_LONG_LONG 0 
   86#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT 
   87#  define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 
   89#ifndef ARDUINOJSON_SLOT_ID_SIZE 
   90#  if ARDUINOJSON_SIZEOF_POINTER <= 2 
   91#    define ARDUINOJSON_SLOT_ID_SIZE 1 
   92#  elif ARDUINOJSON_SIZEOF_POINTER == 4 
   93#    define ARDUINOJSON_SLOT_ID_SIZE 2 
   95#    define ARDUINOJSON_SLOT_ID_SIZE 4 
   98#ifndef ARDUINOJSON_POOL_CAPACITY 
   99#  if ARDUINOJSON_SLOT_ID_SIZE == 1 
  100#    define ARDUINOJSON_POOL_CAPACITY 16   
  101#  elif ARDUINOJSON_SLOT_ID_SIZE == 2 
  102#    define ARDUINOJSON_POOL_CAPACITY 128   
  104#    define ARDUINOJSON_POOL_CAPACITY 256   
  107#ifndef ARDUINOJSON_INITIAL_POOL_COUNT 
  108#  define ARDUINOJSON_INITIAL_POOL_COUNT 4 
  110#ifndef ARDUINOJSON_AUTO_SHRINK 
  111#  if ARDUINOJSON_SIZEOF_POINTER <= 2 
  112#    define ARDUINOJSON_AUTO_SHRINK 0 
  114#    define ARDUINOJSON_AUTO_SHRINK 1 
  117#ifndef ARDUINOJSON_STRING_LENGTH_SIZE 
  118#  if ARDUINOJSON_SIZEOF_POINTER <= 2 
  119#    define ARDUINOJSON_STRING_LENGTH_SIZE 1   
  121#    define ARDUINOJSON_STRING_LENGTH_SIZE 2   
  125#  ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING 
  126#    define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 
  128#  ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM 
  129#    define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 
  131#  ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT 
  132#    define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1 
  134#  ifndef ARDUINOJSON_ENABLE_PROGMEM 
  135#    define ARDUINOJSON_ENABLE_PROGMEM 1 
  138#  ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING 
  139#    define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 
  141#  ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM 
  142#    define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0 
  144#  ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT 
  145#    define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0 
  147#  ifndef ARDUINOJSON_ENABLE_PROGMEM 
  149#      define ARDUINOJSON_ENABLE_PROGMEM 1 
  151#      define ARDUINOJSON_ENABLE_PROGMEM 0 
  155#ifndef ARDUINOJSON_DECODE_UNICODE 
  156#  define ARDUINOJSON_DECODE_UNICODE 1 
  158#ifndef ARDUINOJSON_ENABLE_COMMENTS 
  159#  define ARDUINOJSON_ENABLE_COMMENTS 0 
  161#ifndef ARDUINOJSON_ENABLE_NAN 
  162#  define ARDUINOJSON_ENABLE_NAN 0 
  164#ifndef ARDUINOJSON_ENABLE_INFINITY 
  165#  define ARDUINOJSON_ENABLE_INFINITY 0 
  167#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 
  168#  define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 
  170#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 
  171#  define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5 
  173#ifndef ARDUINOJSON_LITTLE_ENDIAN 
  174#  if defined(_MSC_VER) ||                           \ 
  175      (defined(__BYTE_ORDER__) &&                    \ 
  176       __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ 
  177      defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64) 
  178#    define ARDUINOJSON_LITTLE_ENDIAN 1 
  180#    define ARDUINOJSON_LITTLE_ENDIAN 0 
  183#ifndef ARDUINOJSON_ENABLE_ALIGNMENT 
  185#    define ARDUINOJSON_ENABLE_ALIGNMENT 0 
  187#    define ARDUINOJSON_ENABLE_ALIGNMENT 1 
  190#ifndef ARDUINOJSON_TAB 
  191#  define ARDUINOJSON_TAB "  " 
  193#ifndef ARDUINOJSON_STRING_BUFFER_SIZE 
  194#  define ARDUINOJSON_STRING_BUFFER_SIZE 32 
  196#ifndef ARDUINOJSON_DEBUG 
  197#  ifdef __PLATFORMIO_BUILD_DEBUG__ 
  198#    define ARDUINOJSON_DEBUG 1 
  200#    define ARDUINOJSON_DEBUG 0 
  203#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_DOUBLE 
  204#  define ARDUINOJSON_USE_EXTENSIONS 1 
  206#  define ARDUINOJSON_USE_EXTENSIONS 0 
  209#  error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr 
  211#if ARDUINOJSON_ENABLE_ARDUINO_STRING || ARDUINOJSON_ENABLE_ARDUINO_STREAM || \ 
  212    ARDUINOJSON_ENABLE_ARDUINO_PRINT ||                                       \ 
  213    (ARDUINOJSON_ENABLE_PROGMEM && defined(ARDUINO)) 
  216#if !ARDUINOJSON_DEBUG 
  218#    pragma clang system_header 
  219#  elif defined __GNUC__ 
  220#    pragma GCC system_header 
  223#define ARDUINOJSON_CONCAT_(A, B) A##B 
  224#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B) 
  225#define ARDUINOJSON_CONCAT3(A, B, C) \ 
  226  ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), C) 
  227#define ARDUINOJSON_CONCAT4(A, B, C, D) \ 
  228  ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT3(A, B, C), D) 
  229#define ARDUINOJSON_CONCAT5(A, B, C, D, E) \ 
  230  ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT4(A, B, C, D), E) 
  231#define ARDUINOJSON_BIN2ALPHA_0000() A 
  232#define ARDUINOJSON_BIN2ALPHA_0001() B 
  233#define ARDUINOJSON_BIN2ALPHA_0010() C 
  234#define ARDUINOJSON_BIN2ALPHA_0011() D 
  235#define ARDUINOJSON_BIN2ALPHA_0100() E 
  236#define ARDUINOJSON_BIN2ALPHA_0101() F 
  237#define ARDUINOJSON_BIN2ALPHA_0110() G 
  238#define ARDUINOJSON_BIN2ALPHA_0111() H 
  239#define ARDUINOJSON_BIN2ALPHA_1000() I 
  240#define ARDUINOJSON_BIN2ALPHA_1001() J 
  241#define ARDUINOJSON_BIN2ALPHA_1010() K 
  242#define ARDUINOJSON_BIN2ALPHA_1011() L 
  243#define ARDUINOJSON_BIN2ALPHA_1100() M 
  244#define ARDUINOJSON_BIN2ALPHA_1101() N 
  245#define ARDUINOJSON_BIN2ALPHA_1110() O 
  246#define ARDUINOJSON_BIN2ALPHA_1111() P 
  247#define ARDUINOJSON_BIN2ALPHA_(A, B, C, D) ARDUINOJSON_BIN2ALPHA_##A##B##C##D() 
  248#define ARDUINOJSON_BIN2ALPHA(A, B, C, D) ARDUINOJSON_BIN2ALPHA_(A, B, C, D) 
  249#define ARDUINOJSON_VERSION "7.2.0" 
  250#define ARDUINOJSON_VERSION_MAJOR 7 
  251#define ARDUINOJSON_VERSION_MINOR 2 
  252#define ARDUINOJSON_VERSION_REVISION 0 
  253#define ARDUINOJSON_VERSION_MACRO V720 
  254#ifndef ARDUINOJSON_VERSION_NAMESPACE 
  255#  define ARDUINOJSON_VERSION_NAMESPACE                               \ 
  256    ARDUINOJSON_CONCAT5(                                              \ 
  257        ARDUINOJSON_VERSION_MACRO,                                    \ 
  258        ARDUINOJSON_BIN2ALPHA(ARDUINOJSON_ENABLE_PROGMEM,             \ 
  259                              ARDUINOJSON_USE_LONG_LONG,              \ 
  260                              ARDUINOJSON_USE_DOUBLE, 1),             \ 
  261        ARDUINOJSON_BIN2ALPHA(                                        \ 
  262            ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY,      \ 
  263            ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE), \ 
  264        ARDUINOJSON_SLOT_ID_SIZE, ARDUINOJSON_STRING_LENGTH_SIZE) 
  266#define ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE \ 
  267  namespace FLArduinoJson {                  \ 
  268  inline namespace ARDUINOJSON_VERSION_NAMESPACE { 
  269#define ARDUINOJSON_END_PUBLIC_NAMESPACE \ 
  272#define ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE        \ 
  273  namespace FLArduinoJson {                          \ 
  274  inline namespace ARDUINOJSON_VERSION_NAMESPACE { \ 
  276#define ARDUINOJSON_END_PRIVATE_NAMESPACE \ 
  280ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
  281template <
typename T, 
typename Enable = 
void>
 
  283ARDUINOJSON_END_PUBLIC_NAMESPACE
 
  284ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
  285template <
typename T1, 
typename T2>
 
  286class InvalidConversion;  
 
  287ARDUINOJSON_END_PRIVATE_NAMESPACE
 
  291ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
  294  virtual void* allocate(
size_t size) = 0;
 
  295  virtual void deallocate(
void* ptr) = 0;
 
  296  virtual void* reallocate(
void* ptr, 
size_t new_size) = 0;
 
  298  ~Allocator() = 
default;
 
  301class DefaultAllocator : 
public Allocator {
 
  303  void* allocate(
size_t size)
 override {
 
  306  void deallocate(
void* ptr)
 override {
 
  309  void* reallocate(
void* ptr, 
size_t new_size)
 override {
 
  310    return realloc(ptr, new_size);
 
  312  static Allocator* instance() {
 
  313    static DefaultAllocator allocator;
 
  317  DefaultAllocator() = 
default;
 
  318  ~DefaultAllocator() = 
default;
 
  321ARDUINOJSON_END_PUBLIC_NAMESPACE
 
  324#  define ARDUINOJSON_ASSERT(X) assert(X) 
  326#  define ARDUINOJSON_ASSERT(X) ((void)0) 
  328ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
  333  typedef uint8_t type;
 
  337  typedef uint16_t type;
 
  341  typedef uint32_t type;
 
  344using uint_t = 
typename uint_<Bits>::type;
 
  345using SlotId = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>;
 
  346using SlotCount = SlotId;
 
  347const SlotId NULL_SLOT = SlotId(-1);
 
  351  Slot() : ptr_(nullptr), id_(NULL_SLOT) {}
 
  352  Slot(T* p, SlotId 
id) : ptr_(p), id_(id) {
 
  353    ARDUINOJSON_ASSERT((p == 
nullptr) == (
id == NULL_SLOT));
 
  355  explicit operator bool()
 const {
 
  356    return ptr_ != 
nullptr;
 
  364  T* operator->()
 const {
 
  365    ARDUINOJSON_ASSERT(ptr_ != 
nullptr);
 
  375  void create(SlotCount cap, Allocator* allocator) {
 
  376    ARDUINOJSON_ASSERT(cap > 0);
 
  377    slots_ = 
reinterpret_cast<T*
>(allocator->allocate(slotsToBytes(cap)));
 
  378    capacity_ = slots_ ? cap : 0;
 
  381  void destroy(Allocator* allocator) {
 
  383      allocator->deallocate(slots_);
 
  388  Slot<T> allocSlot() {
 
  391    if (usage_ >= capacity_)
 
  393    auto index = usage_++;
 
  394    return {slots_ + index, SlotId(index)};
 
  396  T* getSlot(SlotId 
id)
 const {
 
  397    ARDUINOJSON_ASSERT(
id < usage_);
 
  403  void shrinkToFit(Allocator* allocator) {
 
  404    auto newSlots = 
reinterpret_cast<T*
>(
 
  405        allocator->reallocate(slots_, slotsToBytes(usage_)));
 
  411  SlotCount usage()
 const {
 
  414  static SlotCount bytesToSlots(
size_t n) {
 
  415    return static_cast<SlotCount
>(n / 
sizeof(T));
 
  417  static size_t slotsToBytes(SlotCount n) {
 
  418    return n * 
sizeof(T);
 
  425template <
bool Condition, 
class TrueType, 
class FalseType>
 
  427  typedef TrueType type;
 
  429template <
class TrueType, 
class FalseType>
 
  430struct conditional<false, TrueType, FalseType> {
 
  431  typedef FalseType type;
 
  433template <
bool Condition, 
class TrueType, 
class FalseType>
 
  435    typename conditional<Condition, TrueType, FalseType>::type;
 
  436template <
bool Condition, 
typename T = 
void>
 
  439struct enable_if<true, T> {
 
  442template <
bool Condition, 
typename T = 
void>
 
  443using enable_if_t = 
typename enable_if<Condition, T>::type;
 
  444template <
typename Sig>
 
  445struct function_traits;
 
  446template <
typename ReturnType, 
typename Arg1>
 
  447struct function_traits<ReturnType (*)(Arg1)> {
 
  448  using return_type = ReturnType;
 
  449  using arg1_type = Arg1;
 
  451template <
typename ReturnType, 
typename Arg1, 
typename Arg2>
 
  452struct function_traits<ReturnType (*)(Arg1, Arg2)> {
 
  453  using return_type = ReturnType;
 
  454  using arg1_type = Arg1;
 
  455  using arg2_type = Arg2;
 
  457template <
typename T, T v>
 
  458struct integral_constant {
 
  459  static const T value = v;
 
  461typedef integral_constant<bool, true> 
true_type;
 
  462typedef integral_constant<bool, false> 
false_type;
 
  467template <
typename T, 
size_t N>
 
  470struct remove_reference {
 
  474struct remove_reference<T&> {
 
  479template <
typename TBase, 
typename TDerived>
 
  482  static int probe(
const TBase*);
 
  483  static char probe(...);
 
  485  static const bool value =
 
  486      sizeof(probe(
reinterpret_cast<remove_reference_t<TDerived>*
>(0))) ==
 
  494  template <
typename U>
 
  495  static int probe(
void (U::*)(
void));
 
  497  static char probe(...);
 
  499  static const bool value = 
sizeof(probe<T>(0)) == 
sizeof(
int);
 
  505ARDUINOJSON_END_PRIVATE_NAMESPACE
 
  507#  pragma warning(push) 
  508#  pragma warning(disable : 4244) 
  511#pragma diag_suppress=Pa093 
  513ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
  514template <
typename From, 
typename To>
 
  515struct is_convertible {
 
  517  static int probe(To);
 
  518  static char probe(...);
 
  521  static const bool value = 
sizeof(probe(from_)) == 
sizeof(
int);
 
  523ARDUINOJSON_END_PRIVATE_NAMESPACE
 
  528#pragma diag_default=Pa093 
  530ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
  531template <
typename T, 
typename U>
 
  540struct remove_cv<const T> {
 
  544struct remove_cv<volatile T> {
 
  548struct remove_cv<const volatile T> {
 
  554struct is_floating_point
 
  555    : integral_constant<bool,  
 
  556                        is_same<float, remove_cv_t<T>>::value ||
 
  557                            is_same<double, remove_cv_t<T>>::value> {};
 
  559struct is_integral : integral_constant<bool,
 
  560    is_same<remove_cv_t<T>, signed char>::value ||
 
  561    is_same<remove_cv_t<T>, unsigned char>::value ||
 
  562    is_same<remove_cv_t<T>, signed short>::value ||
 
  563    is_same<remove_cv_t<T>, unsigned short>::value ||
 
  564    is_same<remove_cv_t<T>, signed int>::value ||
 
  565    is_same<remove_cv_t<T>, unsigned int>::value ||
 
  566    is_same<remove_cv_t<T>, signed long>::value ||
 
  567    is_same<remove_cv_t<T>, unsigned long>::value ||
 
  568    is_same<remove_cv_t<T>, signed long long>::value ||
 
  569    is_same<remove_cv_t<T>, unsigned long long>::value ||
 
  570    is_same<remove_cv_t<T>, char>::value ||
 
  571    is_same<remove_cv_t<T>, bool>::value> {};
 
  574  static const bool value = is_convertible<T, long long>::value &&
 
  575                            !is_class<T>::value && !is_integral<T>::value &&
 
  576                            !is_floating_point<T>::value;
 
  583struct is_signed : integral_constant<bool,
 
  584    is_same<remove_cv_t<T>, char>::value ||
 
  585    is_same<remove_cv_t<T>, signed char>::value ||
 
  586    is_same<remove_cv_t<T>, signed short>::value ||
 
  587    is_same<remove_cv_t<T>, signed int>::value ||
 
  588    is_same<remove_cv_t<T>, signed long>::value ||
 
  589    is_same<remove_cv_t<T>, signed long long>::value ||
 
  590    is_same<remove_cv_t<T>, float>::value ||
 
  591    is_same<remove_cv_t<T>, double>::value> {};
 
  593struct is_unsigned : integral_constant<bool,
 
  594    is_same<remove_cv_t<T>, unsigned char>::value ||
 
  595    is_same<remove_cv_t<T>, unsigned short>::value ||
 
  596    is_same<remove_cv_t<T>, unsigned int>::value ||
 
  597    is_same<remove_cv_t<T>, unsigned long>::value ||
 
  598    is_same<remove_cv_t<T>, unsigned long long>::value ||
 
  599    is_same<remove_cv_t<T>, bool>::value> {};
 
  601struct type_identity {
 
  607struct make_unsigned<char> : type_identity<unsigned char> {};
 
  609struct make_unsigned<signed char> : type_identity<unsigned char> {};
 
  611struct make_unsigned<unsigned char> : type_identity<unsigned char> {};
 
  613struct make_unsigned<signed short> : type_identity<unsigned short> {};
 
  615struct make_unsigned<unsigned short> : type_identity<unsigned short> {};
 
  617struct make_unsigned<signed int> : type_identity<unsigned int> {};
 
  619struct make_unsigned<unsigned int> : type_identity<unsigned int> {};
 
  621struct make_unsigned<signed long> : type_identity<unsigned long> {};
 
  623struct make_unsigned<unsigned long> : type_identity<unsigned long> {};
 
  625struct make_unsigned<signed long long> : type_identity<unsigned long long> {};
 
  627struct make_unsigned<unsigned long long> : type_identity<unsigned long long> {};
 
  629using make_unsigned_t = 
typename make_unsigned<T>::type;
 
  635struct remove_const<const T> {
 
  639using remove_const_t = 
typename remove_const<T>::type;
 
  640template <
typename...>
 
  644template <
typename... Args>
 
  645using void_t = 
typename make_void<Args...>::type;
 
  648T&& 
forward(remove_reference_t<T>& 
t) 
noexcept {
 
  649  return static_cast<T&&
>(
t);
 
  652remove_reference_t<T>&& 
move(T&& 
t) {
 
  653  return static_cast<remove_reference_t<T>&&
>(
t);
 
  656void swap_(T& a, T& b) {
 
  661ARDUINOJSON_END_PRIVATE_NAMESPACE
 
  663ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
  664using PoolCount = SlotId;
 
  666class MemoryPoolList {
 
  670  static_assert(
sizeof(FreeSlot) <= 
sizeof(T), 
"T is too small");
 
  672  using Pool = MemoryPool<T>;
 
  673  MemoryPoolList() = 
default;
 
  675    ARDUINOJSON_ASSERT(count_ == 0);
 
  677  friend void swap(MemoryPoolList& a, MemoryPoolList& b) {
 
  678    bool aUsedPreallocated = a.pools_ == a.preallocatedPools_;
 
  679    bool bUsedPreallocated = b.pools_ == b.preallocatedPools_;
 
  680    if (aUsedPreallocated && bUsedPreallocated) {
 
  681      for (PoolCount i = 0; i < ARDUINOJSON_INITIAL_POOL_COUNT; i++)
 
  682        swap_(a.preallocatedPools_[i], b.preallocatedPools_[i]);
 
  683    } 
else if (bUsedPreallocated) {
 
  684      for (PoolCount i = 0; i < b.count_; i++)
 
  685        a.preallocatedPools_[i] = b.preallocatedPools_[i];
 
  687      a.pools_ = a.preallocatedPools_;
 
  688    } 
else if (aUsedPreallocated) {
 
  689      for (PoolCount i = 0; i < a.count_; i++)
 
  690        b.preallocatedPools_[i] = a.preallocatedPools_[i];
 
  692      b.pools_ = b.preallocatedPools_;
 
  694      swap_(a.pools_, b.pools_);
 
  696    swap_(a.count_, b.count_);
 
  697    swap_(a.capacity_, b.capacity_);
 
  698    swap_(a.freeList_, b.freeList_);
 
  700  MemoryPoolList& operator=(MemoryPoolList&& src) {
 
  701    ARDUINOJSON_ASSERT(count_ == 0);
 
  702    if (src.pools_ == src.preallocatedPools_) {
 
  703      memcpy(preallocatedPools_, src.preallocatedPools_,
 
  704             sizeof(preallocatedPools_));
 
  705      pools_ = preallocatedPools_;
 
  708      src.pools_ = 
nullptr;
 
  711    capacity_ = src.capacity_;
 
  716  Slot<T> allocSlot(Allocator* allocator) {
 
  717    if (freeList_ != NULL_SLOT) {
 
  718      return allocFromFreeList();
 
  721      auto slot = allocFromLastPool();
 
  725    auto pool = addPool(allocator);
 
  728    return allocFromLastPool();
 
  730  void freeSlot(Slot<T> slot) {
 
  731    reinterpret_cast<FreeSlot*
>(slot.ptr())->next = freeList_;
 
  732    freeList_ = slot.id();
 
  734  T* getSlot(SlotId 
id)
 const {
 
  737    auto poolIndex = SlotId(
id / ARDUINOJSON_POOL_CAPACITY);
 
  738    auto indexInPool = SlotId(
id % ARDUINOJSON_POOL_CAPACITY);
 
  739    ARDUINOJSON_ASSERT(poolIndex < count_);
 
  740    return pools_[poolIndex].getSlot(indexInPool);
 
  742  void clear(Allocator* allocator) {
 
  743    for (PoolCount i = 0; i < count_; i++)
 
  744      pools_[i].destroy(allocator);
 
  746    freeList_ = NULL_SLOT;
 
  747    if (pools_ != preallocatedPools_) {
 
  748      allocator->deallocate(pools_);
 
  749      pools_ = preallocatedPools_;
 
  750      capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
 
  753  SlotCount usage()
 const {
 
  755    for (PoolCount i = 0; i < count_; i++)
 
  756      total = SlotCount(total + pools_[i].usage());
 
  759  size_t size()
 const {
 
  760    return Pool::slotsToBytes(usage());
 
  762  void shrinkToFit(Allocator* allocator) {
 
  764      pools_[count_ - 1].shrinkToFit(allocator);
 
  765    if (pools_ != preallocatedPools_ && count_ != capacity_) {
 
  766      pools_ = 
static_cast<Pool*
>(
 
  767          allocator->reallocate(pools_, count_ * 
sizeof(Pool)));
 
  768      ARDUINOJSON_ASSERT(pools_ != 
nullptr);  
 
  773  Slot<T> allocFromFreeList() {
 
  774    ARDUINOJSON_ASSERT(freeList_ != NULL_SLOT);
 
  776    auto slot = getSlot(freeList_);
 
  777    freeList_ = 
reinterpret_cast<FreeSlot*
>(slot)->next;
 
  780  Slot<T> allocFromLastPool() {
 
  781    ARDUINOJSON_ASSERT(count_ > 0);
 
  782    auto poolIndex = SlotId(count_ - 1);
 
  783    auto slot = pools_[poolIndex].allocSlot();
 
  787            SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
 
  789  Pool* addPool(Allocator* allocator) {
 
  790    if (count_ == capacity_ && !increaseCapacity(allocator))
 
  792    auto pool = &pools_[count_++];
 
  793    SlotCount poolCapacity = ARDUINOJSON_POOL_CAPACITY;
 
  794    if (count_ == maxPools)  
 
  796    pool->create(poolCapacity, allocator);
 
  799  bool increaseCapacity(Allocator* allocator) {
 
  800    if (capacity_ == maxPools)
 
  803    auto newCapacity = PoolCount(capacity_ * 2);
 
  804    if (pools_ == preallocatedPools_) {
 
  805      newPools = allocator->allocate(newCapacity * 
sizeof(Pool));
 
  808      ::memcpy(newPools, preallocatedPools_, 
sizeof(preallocatedPools_));
 
  810      newPools = allocator->reallocate(pools_, newCapacity * 
sizeof(Pool));
 
  814    pools_ = 
static_cast<Pool*
>(newPools);
 
  815    capacity_ = newCapacity;
 
  818  Pool preallocatedPools_[ARDUINOJSON_INITIAL_POOL_COUNT];
 
  819  Pool* pools_ = preallocatedPools_;
 
  820  PoolCount count_ = 0;
 
  821  PoolCount capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
 
  822  SlotId freeList_ = NULL_SLOT;
 
  824  static const PoolCount maxPools =
 
  825      PoolCount(NULL_SLOT / ARDUINOJSON_POOL_CAPACITY + 1);
 
  827ARDUINOJSON_END_PRIVATE_NAMESPACE
 
  829#  pragma warning(push) 
  830#  pragma warning(disable : 4310) 
  832ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
  833template <
typename T, 
typename Enable = 
void>
 
  834struct numeric_limits;
 
  836struct numeric_limits<T, 
enable_if_t<is_unsigned<T>::value>> {
 
  837  static constexpr T lowest() {
 
  840  static constexpr T highest() {
 
  845struct numeric_limits<
 
  846    T, 
enable_if_t<is_integral<T>::value && is_signed<T>::value>> {
 
  847  static constexpr T lowest() {
 
  848    return T(T(1) << (
sizeof(T) * 8 - 1));
 
  850  static constexpr T highest() {
 
  854ARDUINOJSON_END_PRIVATE_NAMESPACE
 
  858ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
  860  using references_type = uint_t<ARDUINOJSON_SLOT_ID_SIZE * 8>;
 
  861  using length_type = uint_t<ARDUINOJSON_STRING_LENGTH_SIZE * 8>;
 
  862  struct StringNode* next;
 
  863  references_type references;
 
  866  static constexpr size_t maxLength = numeric_limits<length_type>::highest();
 
  867  static constexpr size_t sizeForLength(
size_t n) {
 
  868    return n + 1 + offsetof(StringNode, data);
 
  870  static StringNode* create(
size_t length, Allocator* allocator) {
 
  873    auto size = sizeForLength(
length);
 
  876    auto node = 
reinterpret_cast<StringNode*
>(allocator->allocate(size));
 
  878      node->length = length_type(
length);
 
  879      node->references = 1;
 
  883  static StringNode* resize(StringNode* node, 
size_t length,
 
  884                            Allocator* allocator) {
 
  885    ARDUINOJSON_ASSERT(node != 
nullptr);
 
  888      newNode = 
reinterpret_cast<StringNode*
>(
 
  889          allocator->reallocate(node, sizeForLength(
length)));
 
  893      newNode->length = length_type(
length);
 
  895      allocator->deallocate(node);
 
  898  static void destroy(StringNode* node, Allocator* allocator) {
 
  899    allocator->deallocate(node);
 
  902constexpr size_t sizeofString(
size_t n) {
 
  903  return StringNode::sizeForLength(n);
 
  905ARDUINOJSON_END_PRIVATE_NAMESPACE
 
  908#  ifndef ARDUINOJSON_DEPRECATED 
  909#    define ARDUINOJSON_DEPRECATED(msg) __declspec(deprecated(msg)) 
  911#elif defined(__GNUC__)   
  912#  define FORCE_INLINE __attribute__((always_inline)) 
  913#  ifndef ARDUINOJSON_DEPRECATED 
  914#    if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) 
  915#      define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated(msg))) 
  917#      define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated)) 
  922#  ifndef ARDUINOJSON_DEPRECATED 
  923#    define ARDUINOJSON_DEPRECATED(msg) 
  926#if defined(__has_attribute) 
  927#  if __has_attribute(no_sanitize) 
  928#    define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check))) 
  930#    define ARDUINOJSON_NO_SANITIZE(check) 
  933#  define ARDUINOJSON_NO_SANITIZE(check) 
  935ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
  936template <
typename TString, 
typename Enable = 
void>
 
  938template <
typename TString, 
typename Enable = 
void>
 
  939struct SizedStringAdapter;
 
  940template <
typename TString>
 
  941typename StringAdapter<TString>::AdaptedString adaptString(
const TString& s) {
 
  942  return StringAdapter<TString>::adapt(s);
 
  944template <
typename TChar>
 
  945typename StringAdapter<TChar*>::AdaptedString adaptString(TChar* p) {
 
  946  return StringAdapter<TChar*>::adapt(p);
 
  948template <
typename TChar>
 
  949typename SizedStringAdapter<TChar*>::AdaptedString adaptString(TChar* p,
 
  951  return SizedStringAdapter<TChar*>::adapt(p, n);
 
  955    : integral_constant<bool, is_integral<T>::value && sizeof(T) == 1> {};
 
  956class ZeroTerminatedRamString {
 
  958  static const size_t typeSortKey = 3;
 
  959  ZeroTerminatedRamString(
const char* str) : str_(str) {}
 
  960  bool isNull()
 const {
 
  963  FORCE_INLINE 
size_t size()
 const {
 
  964    return str_ ? ::strlen(str_) : 0;
 
  966  char operator[](
size_t i)
 const {
 
  967    ARDUINOJSON_ASSERT(str_ != 0);
 
  968    ARDUINOJSON_ASSERT(i <= size());
 
  971  const char* data()
 const {
 
  974  friend int stringCompare(ZeroTerminatedRamString a,
 
  975                           ZeroTerminatedRamString b) {
 
  976    ARDUINOJSON_ASSERT(!a.isNull());
 
  977    ARDUINOJSON_ASSERT(!b.isNull());
 
  978    return ::strcmp(a.str_, b.str_);
 
  980  friend bool stringEquals(ZeroTerminatedRamString a,
 
  981                           ZeroTerminatedRamString b) {
 
  982    return stringCompare(a, b) == 0;
 
  984  bool isLinked()
 const {
 
  990template <
typename TChar>
 
  991struct StringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
 
  992  typedef ZeroTerminatedRamString AdaptedString;
 
  993  static AdaptedString adapt(
const TChar* p) {
 
  994    return AdaptedString(
reinterpret_cast<const char*
>(p));
 
  997template <
typename TChar, 
size_t N>
 
  998struct StringAdapter<TChar[N], 
enable_if_t<IsChar<TChar>::value>> {
 
  999  typedef ZeroTerminatedRamString AdaptedString;
 
 1000  static AdaptedString adapt(
const TChar* p) {
 
 1001    return AdaptedString(
reinterpret_cast<const char*
>(p));
 
 1004class StaticStringAdapter : 
public ZeroTerminatedRamString {
 
 1006  StaticStringAdapter(
const char* str) : ZeroTerminatedRamString(str) {}
 
 1007  bool isLinked()
 const {
 
 1012struct StringAdapter<const char*, 
void> {
 
 1013  typedef StaticStringAdapter AdaptedString;
 
 1014  static AdaptedString adapt(
const char* p) {
 
 1015    return AdaptedString(p);
 
 1018class SizedRamString {
 
 1020  static const size_t typeSortKey = 2;
 
 1021  SizedRamString(
const char* str, 
size_t size) : str_(str), size_(size) {}
 
 1022  bool isNull()
 const {
 
 1025  size_t size()
 const {
 
 1028  char operator[](
size_t i)
 const {
 
 1029    ARDUINOJSON_ASSERT(str_ != 0);
 
 1030    ARDUINOJSON_ASSERT(i <= size());
 
 1033  const char* data()
 const {
 
 1036  bool isLinked()
 const {
 
 1043template <
typename TChar>
 
 1044struct SizedStringAdapter<TChar*, enable_if_t<IsChar<TChar>::value>> {
 
 1045  typedef SizedRamString AdaptedString;
 
 1046  static AdaptedString adapt(
const TChar* p, 
size_t n) {
 
 1047    return AdaptedString(
reinterpret_cast<const char*
>(p), n);
 
 1050ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 1051#if ARDUINOJSON_ENABLE_STD_STREAM 
 1054ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 1057  enum Ownership { Copied, Linked };
 
 1058  JsonString() : data_(0), size_(0), ownership_(Linked) {}
 
 1059  JsonString(
const char* data, Ownership ownership = Linked)
 
 1060      : data_(data), size_(data ? ::strlen(data) : 0), ownership_(ownership) {}
 
 1061  JsonString(
const char* data, 
size_t size, Ownership ownership = Linked)
 
 1062      : data_(data), size_(size), ownership_(ownership) {}
 
 1063  const char* c_str()
 const {
 
 1066  bool isNull()
 const {
 
 1069  bool isLinked()
 const {
 
 1070    return ownership_ == Linked;
 
 1072  size_t size()
 const {
 
 1075  explicit operator bool()
 const {
 
 1078  friend bool operator==(JsonString lhs, JsonString rhs) {
 
 1079    if (lhs.size_ != rhs.size_)
 
 1081    if (lhs.data_ == rhs.data_)
 
 1087    return memcmp(lhs.data_, rhs.data_, lhs.size_) == 0;
 
 1089  friend bool operator!=(JsonString lhs, JsonString rhs) {
 
 1090    return !(lhs == rhs);
 
 1092#if ARDUINOJSON_ENABLE_STD_STREAM 
 1093  friend std::ostream& 
operator<<(std::ostream& lhs, 
const JsonString& rhs) {
 
 1094    lhs.write(rhs.c_str(), 
static_cast<std::streamsize
>(rhs.size()));
 
 1101  Ownership ownership_;
 
 1103ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 1104ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 1105class JsonStringAdapter : 
public SizedRamString {
 
 1107  JsonStringAdapter(
const JsonString& s)
 
 1108      : SizedRamString(s.c_str(), s.size()), linked_(s.isLinked()) {}
 
 1109  bool isLinked()
 const {
 
 1116struct StringAdapter<JsonString> {
 
 1117  typedef JsonStringAdapter AdaptedString;
 
 1118  static AdaptedString adapt(
const JsonString& s) {
 
 1119    return AdaptedString(s);
 
 1122namespace string_traits_impl {
 
 1123template <
class T, 
class = 
void>
 
 1128template <
class T, 
class = 
void>
 
 1133template <
class T, 
class = 
void>
 
 1139template <
class T, 
class = 
void>
 
 1146template <
typename T>
 
 1147struct string_traits {
 
 1149    has_cstr = string_traits_impl::has_cstr<T>::value,
 
 1150    has_length = string_traits_impl::has_length<T>::value,
 
 1151    has_data = string_traits_impl::has_data<T>::value,
 
 1152    has_size = string_traits_impl::has_size<T>::value
 
 1155template <
typename T>
 
 1156struct StringAdapter<
 
 1158    enable_if_t<(string_traits<T>::has_cstr || string_traits<T>::has_data) &&
 
 1159                (string_traits<T>::has_length || string_traits<T>::has_size)>> {
 
 1160  typedef SizedRamString AdaptedString;
 
 1161  static AdaptedString adapt(
const T& s) {
 
 1162    return AdaptedString(get_data(s), get_size(s));
 
 1165  template <
typename U>
 
 1166  static enable_if_t<string_traits<U>::has_size, 
size_t> get_size(
const U& s) {
 
 1169  template <
typename U>
 
 1170  static enable_if_t<!string_traits<U>::has_size, 
size_t> get_size(
const U& s) {
 
 1173  template <
typename U>
 
 1174  static enable_if_t<string_traits<U>::has_data, 
const char*> get_data(
 
 1178  template <
typename U>
 
 1179  static enable_if_t<!string_traits<U>::has_data, 
const char*> get_data(
 
 1184ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 1185#if ARDUINOJSON_ENABLE_PROGMEM 
 1188class __FlashStringHelper;
 
 1189#include <avr/pgmspace.h> 
 1191ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 1193  pgm_p(
const void* p) : address(reinterpret_cast<const char*>(p)) {}
 
 1194  const char* address;
 
 1196ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 1198inline size_t strlen_P(FLArduinoJson::detail::pgm_p s) {
 
 1199  const char* p = s.address;
 
 1200  ARDUINOJSON_ASSERT(p != NULL);
 
 1201  while (pgm_read_byte(p))
 
 1203  return size_t(p - s.address);
 
 1207inline int strncmp_P(
const char* a, FLArduinoJson::detail::pgm_p b, 
size_t n) {
 
 1209  const char* s2 = b.address;
 
 1210  ARDUINOJSON_ASSERT(s1 != NULL);
 
 1211  ARDUINOJSON_ASSERT(s2 != NULL);
 
 1214    char c2 = 
static_cast<char>(pgm_read_byte(s2++));
 
 1226inline int strcmp_P(
const char* a, FLArduinoJson::detail::pgm_p b) {
 
 1228  const char* s2 = b.address;
 
 1229  ARDUINOJSON_ASSERT(s1 != NULL);
 
 1230  ARDUINOJSON_ASSERT(s2 != NULL);
 
 1233    char c2 = 
static_cast<char>(pgm_read_byte(s2++));
 
 1244inline int memcmp_P(
const void* a, FLArduinoJson::detail::pgm_p b, 
size_t n) {
 
 1245  const uint8_t* p1 = 
reinterpret_cast<const uint8_t*
>(a);
 
 1246  const char* p2 = b.address;
 
 1247  ARDUINOJSON_ASSERT(p1 != NULL);
 
 1248  ARDUINOJSON_ASSERT(p2 != NULL);
 
 1251    uint8_t v2 = pgm_read_byte(p2++);
 
 1259inline void* memcpy_P(
void* dst, FLArduinoJson::detail::pgm_p src, 
size_t n) {
 
 1260  uint8_t* d = 
reinterpret_cast<uint8_t*
>(dst);
 
 1261  const char* s = src.address;
 
 1262  ARDUINOJSON_ASSERT(d != NULL);
 
 1263  ARDUINOJSON_ASSERT(s != NULL);
 
 1265    *d++ = pgm_read_byte(s++);
 
 1270#ifndef pgm_read_dword 
 1271inline uint32_t pgm_read_dword(FLArduinoJson::detail::pgm_p p) {
 
 1273  memcpy_P(&result, p.address, 4);
 
 1277#ifndef pgm_read_float 
 1278inline float pgm_read_float(FLArduinoJson::detail::pgm_p p) {
 
 1280  memcpy_P(&result, p.address, 
sizeof(
float));
 
 1284#ifndef pgm_read_double 
 1285#  if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_FLOAT__) && \ 
 1286      __SIZEOF_DOUBLE__ == __SIZEOF_FLOAT__ 
 1287inline double pgm_read_double(FLArduinoJson::detail::pgm_p p) {
 
 1288  return pgm_read_float(p.address);
 
 1291inline double pgm_read_double(FLArduinoJson::detail::pgm_p p) {
 
 1293  memcpy_P(&result, p.address, 
sizeof(
double));
 
 1299inline void* pgm_read_ptr(FLArduinoJson::detail::pgm_p p) {
 
 1301  memcpy_P(&result, p.address, 
sizeof(result));
 
 1305ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 1308  static const size_t typeSortKey = 1;
 
 1309  FlashString(
const __FlashStringHelper* str, 
size_t size)
 
 1310      : str_(reinterpret_cast<const char*>(str)), size_(size) {}
 
 1311  bool isNull()
 const {
 
 1314  char operator[](
size_t i)
 const {
 
 1315    ARDUINOJSON_ASSERT(str_ != 0);
 
 1316    ARDUINOJSON_ASSERT(i <= size_);
 
 1317    return static_cast<char>(pgm_read_byte(str_ + i));
 
 1319  const char* data()
 const {
 
 1322  size_t size()
 const {
 
 1325  friend bool stringEquals(FlashString a, SizedRamString b) {
 
 1326    ARDUINOJSON_ASSERT(a.typeSortKey < b.typeSortKey);
 
 1327    ARDUINOJSON_ASSERT(!a.isNull());
 
 1328    ARDUINOJSON_ASSERT(!b.isNull());
 
 1329    if (a.size() != b.size())
 
 1331    return ::memcmp_P(b.data(), a.str_, a.size_) == 0;
 
 1333  friend int stringCompare(FlashString a, SizedRamString b) {
 
 1334    ARDUINOJSON_ASSERT(a.typeSortKey < b.typeSortKey);
 
 1335    ARDUINOJSON_ASSERT(!a.isNull());
 
 1336    ARDUINOJSON_ASSERT(!b.isNull());
 
 1337    size_t minsize = a.size() < b.size() ? a.size() : b.size();
 
 1338    int res = ::memcmp_P(b.data(), a.str_, minsize);
 
 1341    if (a.size() < b.size())
 
 1343    if (a.size() > b.size())
 
 1347  friend void stringGetChars(FlashString s, 
char* p, 
size_t n) {
 
 1348    ARDUINOJSON_ASSERT(s.size() <= n);
 
 1349    ::memcpy_P(p, s.str_, n);
 
 1351  bool isLinked()
 const {
 
 1359struct StringAdapter<const __FlashStringHelper*, 
void> {
 
 1360  typedef FlashString AdaptedString;
 
 1361  static AdaptedString adapt(
const __FlashStringHelper* s) {
 
 1362    return AdaptedString(s, s ? strlen_P(
reinterpret_cast<const char*
>(s)) : 0);
 
 1366struct SizedStringAdapter<const __FlashStringHelper*, 
void> {
 
 1367  typedef FlashString AdaptedString;
 
 1368  static AdaptedString adapt(
const __FlashStringHelper* s, 
size_t n) {
 
 1369    return AdaptedString(s, n);
 
 1372ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 1374ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 1375template <
typename TAdaptedString1, 
typename TAdaptedString2>
 
 1376enable_if_t<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey, int>
 
 1377stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) {
 
 1378  ARDUINOJSON_ASSERT(!s1.isNull());
 
 1379  ARDUINOJSON_ASSERT(!s2.isNull());
 
 1380  size_t size1 = s1.size();
 
 1381  size_t size2 = s2.size();
 
 1382  size_t n = size1 < size2 ? size1 : size2;
 
 1383  for (
size_t i = 0; i < n; i++) {
 
 1385      return s1[i] - s2[i];
 
 1393template <
typename TAdaptedString1, 
typename TAdaptedString2>
 
 1394enable_if_t<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), 
int>
 
 1395stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) {
 
 1396  return -stringCompare(s2, s1);
 
 1398template <
typename TAdaptedString1, 
typename TAdaptedString2>
 
 1399enable_if_t<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey, bool>
 
 1400stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) {
 
 1401  ARDUINOJSON_ASSERT(!s1.isNull());
 
 1402  ARDUINOJSON_ASSERT(!s2.isNull());
 
 1403  size_t size1 = s1.size();
 
 1404  size_t size2 = s2.size();
 
 1407  for (
size_t i = 0; i < size1; i++) {
 
 1413template <
typename TAdaptedString1, 
typename TAdaptedString2>
 
 1414enable_if_t<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), 
bool>
 
 1415stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) {
 
 1416  return stringEquals(s2, s1);
 
 1418template <
typename TAdaptedString>
 
 1419static void stringGetChars(TAdaptedString s, 
char* p, 
size_t n) {
 
 1420  ARDUINOJSON_ASSERT(s.size() <= n);
 
 1421  for (
size_t i = 0; i < n; i++) {
 
 1427  StringPool() = 
default;
 
 1428  StringPool(
const StringPool&) = 
delete;
 
 1429  void operator=(StringPool&& src) = 
delete;
 
 1431    ARDUINOJSON_ASSERT(strings_ == 
nullptr);
 
 1433  friend void swap(StringPool& a, StringPool& b) {
 
 1434    swap_(a.strings_, b.strings_);
 
 1436  void clear(Allocator* allocator) {
 
 1438      auto node = strings_;
 
 1439      strings_ = node->next;
 
 1440      StringNode::destroy(node, allocator);
 
 1443  size_t size()
 const {
 
 1445    for (
auto node = strings_; node; node = node->next)
 
 1446      total += sizeofString(node->length);
 
 1449  template <
typename TAdaptedString>
 
 1450  StringNode* add(TAdaptedString str, Allocator* allocator) {
 
 1451    ARDUINOJSON_ASSERT(str.isNull() == 
false);
 
 1452    auto node = 
get(str);
 
 1457    size_t n = str.size();
 
 1458    node = StringNode::create(n, allocator);
 
 1461    stringGetChars(str, node->data, n);
 
 1466  void add(StringNode* node) {
 
 1467    ARDUINOJSON_ASSERT(node != 
nullptr);
 
 1468    node->next = strings_;
 
 1471  template <
typename TAdaptedString>
 
 1472  StringNode* 
get(
const TAdaptedString& str)
 const {
 
 1473    for (
auto node = strings_; node; node = node->next) {
 
 1474      if (stringEquals(str, adaptString(node->data, node->length)))
 
 1479  void dereference(
const char* s, Allocator* allocator) {
 
 1480    StringNode* prev = 
nullptr;
 
 1481    for (
auto node = strings_; node; node = node->next) {
 
 1482      if (node->data == s) {
 
 1483        if (--node->references == 0) {
 
 1485            prev->next = node->next;
 
 1487            strings_ = node->next;
 
 1488          StringNode::destroy(node, allocator);
 
 1496  StringNode* strings_ = 
nullptr;
 
 1498ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 1499ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 1500template <
typename T>
 
 1501class SerializedValue {
 
 1503  explicit SerializedValue(T str) : str_(str) {}
 
 1504  operator T()
 const {
 
 1507  const char* data()
 const {
 
 1508    return str_.c_str();
 
 1510  size_t size()
 const {
 
 1511    return str_.length();
 
 1516template <
typename TChar>
 
 1517class SerializedValue<TChar*> {
 
 1519  explicit SerializedValue(TChar* p, 
size_t n) : data_(p), size_(n) {}
 
 1520  operator TChar*() 
const {
 
 1523  TChar* data()
 const {
 
 1526  size_t size()
 const {
 
 1533using RawString = SerializedValue<const char*>;
 
 1534template <
typename T>
 
 1535inline SerializedValue<T> serialized(T str) {
 
 1536  return SerializedValue<T>(str);
 
 1538template <
typename TChar>
 
 1539inline SerializedValue<TChar*> serialized(TChar* p) {
 
 1540  return SerializedValue<TChar*>(p, detail::adaptString(p).size());
 
 1542template <
typename TChar>
 
 1543inline SerializedValue<TChar*> serialized(TChar* p, 
size_t n) {
 
 1544  return SerializedValue<TChar*>(p, n);
 
 1546ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 1547#if defined(__clang__) 
 1548#  pragma clang diagnostic push 
 1549#  pragma clang diagnostic ignored "-Wconversion" 
 1550#elif defined(__GNUC__) 
 1551#  pragma GCC diagnostic push 
 1552#  pragma GCC diagnostic ignored "-Wconversion" 
 1554ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 1556template <
typename T>
 
 1562template <
typename T>
 
 1564  return x != 0.0 && 
x * 2 == 
x;
 
 1567template <
typename T, 
typename F>
 
 1568struct alias_cast_t {
 
 1574template <
typename T, 
typename F>
 
 1575T alias_cast(F raw_data) {
 
 1576  alias_cast_t<T, F> ac;
 
 1580ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 1581#if ARDUINOJSON_ENABLE_PROGMEM 
 1583ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 1584#if ARDUINOJSON_ENABLE_PROGMEM 
 1585#  ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY 
 1586#    define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, ...) \ 
 1587      static type const name[] PROGMEM = __VA_ARGS__; 
 1589template <
typename T>
 
 1590inline const T* pgm_read(
const T* 
const* p) {
 
 1591  return reinterpret_cast<const T*
>(pgm_read_ptr(p));
 
 1593inline uint32_t pgm_read(
const uint32_t* p) {
 
 1594  return pgm_read_dword(p);
 
 1596inline double pgm_read(
const double* p) {
 
 1597  return pgm_read_double(p);
 
 1599inline float pgm_read(
const float* p) {
 
 1600  return pgm_read_float(p);
 
 1603#  ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY 
 1604#    define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, ...) \ 
 1605      static type const name[] = __VA_ARGS__; 
 1607template <
typename T>
 
 1608inline T pgm_read(
const T* p) {
 
 1612template <
typename T>
 
 1615  explicit pgm_ptr(
const T* ptr) : ptr_(ptr) {}
 
 1616  T operator[](intptr_t index)
 const {
 
 1617    return pgm_read(ptr_ + index);
 
 1622template <
typename T, 
size_t = sizeof(T)>
 
 1623struct FloatTraits {};
 
 1624template <
typename T>
 
 1625struct FloatTraits<T, 8 > {
 
 1626  typedef uint64_t mantissa_type;
 
 1627  static const short mantissa_bits = 52;
 
 1628  static const mantissa_type mantissa_max =
 
 1629      (mantissa_type(1) << mantissa_bits) - 1;
 
 1630  typedef int16_t exponent_type;
 
 1631  static const exponent_type exponent_max = 308;
 
 1632  static pgm_ptr<T> positiveBinaryPowersOfTen() {
 
 1633    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(  
 
 1646    return pgm_ptr<T>(
reinterpret_cast<const T*
>(factors));
 
 1648  static pgm_ptr<T> negativeBinaryPowersOfTen() {
 
 1649    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(  
 
 1662    return pgm_ptr<T>(
reinterpret_cast<const T*
>(factors));
 
 1665    return forge(0x7ff8000000000000);
 
 1668    return forge(0x7ff0000000000000);
 
 1670  static T highest() {
 
 1671    return forge(0x7FEFFFFFFFFFFFFF);
 
 1673  template <
typename TOut>  
 
 1674  static T highest_for(
 
 1675      enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
 
 1678    return forge(0x43DFFFFFFFFFFFFF);  
 
 1680  template <
typename TOut>  
 
 1681  static T highest_for(
 
 1682      enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
 
 1685    return forge(0x43EFFFFFFFFFFFFF);  
 
 1688    return forge(0xFFEFFFFFFFFFFFFF);
 
 1690  static T forge(uint64_t bits) {
 
 1691    return alias_cast<T>(bits);
 
 1694template <
typename T>
 
 1695struct FloatTraits<T, 4 > {
 
 1696  typedef uint32_t mantissa_type;
 
 1697  static const short mantissa_bits = 23;
 
 1698  static const mantissa_type mantissa_max =
 
 1699      (mantissa_type(1) << mantissa_bits) - 1;
 
 1700  typedef int8_t exponent_type;
 
 1701  static const exponent_type exponent_max = 38;
 
 1702  static pgm_ptr<T> positiveBinaryPowersOfTen() {
 
 1703    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
 
 1712    return pgm_ptr<T>(
reinterpret_cast<const T*
>(factors));
 
 1714  static pgm_ptr<T> negativeBinaryPowersOfTen() {
 
 1715    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
 
 1724    return pgm_ptr<T>(
reinterpret_cast<const T*
>(factors));
 
 1726  static T forge(uint32_t bits) {
 
 1727    return alias_cast<T>(bits);
 
 1730    return forge(0x7fc00000);
 
 1733    return forge(0x7f800000);
 
 1735  static T highest() {
 
 1736    return forge(0x7f7fffff);
 
 1738  template <
typename TOut>  
 
 1739  static T highest_for(
 
 1740      enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
 
 1743    return forge(0x4EFFFFFF);  
 
 1745  template <
typename TOut>  
 
 1746  static T highest_for(
 
 1747      enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
 
 1750    return forge(0x4F7FFFFF);  
 
 1752  template <
typename TOut>  
 
 1753  static T highest_for(
 
 1754      enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
 
 1757    return forge(0x5EFFFFFF);  
 
 1759  template <
typename TOut>  
 
 1760  static T highest_for(
 
 1761      enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
 
 1764    return forge(0x5F7FFFFF);  
 
 1767    return forge(0xFf7fffff);
 
 1770template <
typename TFloat, 
typename TExponent>
 
 1771inline TFloat make_float(TFloat m, TExponent e) {
 
 1772  using traits = FloatTraits<TFloat>;
 
 1773  auto powersOfTen = e > 0 ? traits::positiveBinaryPowersOfTen()
 
 1774                           : traits::negativeBinaryPowersOfTen();
 
 1777  for (uint8_t index = 0; e != 0; index++) {
 
 1779      m *= powersOfTen[index];
 
 1784ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 1785ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 1786#if ARDUINOJSON_USE_DOUBLE 
 1787typedef double JsonFloat;
 
 1789typedef float JsonFloat;
 
 1791ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 1792ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 1793template <
typename TOut, 
typename TIn>
 
 1794enable_if_t<is_integral<TIn>::value && is_unsigned<TIn>::value &&
 
 1795                is_integral<TOut>::value && 
sizeof(TOut) <= 
sizeof(TIn),
 
 1797canConvertNumber(TIn value) {
 
 1798  return value <= TIn(numeric_limits<TOut>::highest());
 
 1800template <
typename TOut, 
typename TIn>
 
 1801enable_if_t<is_integral<TIn>::value && is_unsigned<TIn>::value &&
 
 1802                is_integral<TOut>::value && 
sizeof(TIn) < 
sizeof(TOut),
 
 1804canConvertNumber(TIn) {
 
 1807template <
typename TOut, 
typename TIn>
 
 1808enable_if_t<is_integral<TIn>::value && is_floating_point<TOut>::value, 
bool>
 
 1809canConvertNumber(TIn) {
 
 1812template <
typename TOut, 
typename TIn>
 
 1813enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value &&
 
 1814                is_integral<TOut>::value && is_signed<TOut>::value &&
 
 1815                sizeof(TOut) < 
sizeof(TIn),
 
 1817canConvertNumber(TIn value) {
 
 1818  return value >= TIn(numeric_limits<TOut>::lowest()) &&
 
 1819         value <= TIn(numeric_limits<TOut>::highest());
 
 1821template <
typename TOut, 
typename TIn>
 
 1822enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value &&
 
 1823                is_integral<TOut>::value && is_signed<TOut>::value &&
 
 1824                sizeof(TIn) <= 
sizeof(TOut),
 
 1826canConvertNumber(TIn) {
 
 1829template <
typename TOut, 
typename TIn>
 
 1830enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value &&
 
 1831                is_integral<TOut>::value && is_unsigned<TOut>::value &&
 
 1832                sizeof(TOut) >= 
sizeof(TIn),
 
 1834canConvertNumber(TIn value) {
 
 1837  return TOut(value) <= numeric_limits<TOut>::highest();
 
 1839template <
typename TOut, 
typename TIn>
 
 1840enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value &&
 
 1841                is_integral<TOut>::value && is_unsigned<TOut>::value &&
 
 1842                sizeof(TOut) < 
sizeof(TIn),
 
 1844canConvertNumber(TIn value) {
 
 1847  return value <= TIn(numeric_limits<TOut>::highest());
 
 1849template <
typename TOut, 
typename TIn>
 
 1850enable_if_t<is_floating_point<TIn>::value && is_integral<TOut>::value &&
 
 1851                sizeof(TOut) < 
sizeof(TIn),
 
 1853canConvertNumber(TIn value) {
 
 1854  return value >= numeric_limits<TOut>::lowest() &&
 
 1855         value <= numeric_limits<TOut>::highest();
 
 1857template <
typename TOut, 
typename TIn>
 
 1858enable_if_t<is_floating_point<TIn>::value && is_integral<TOut>::value &&
 
 1859                sizeof(TOut) >= 
sizeof(TIn),
 
 1861canConvertNumber(TIn value) {
 
 1862  return value >= numeric_limits<TOut>::lowest() &&
 
 1863         value <= FloatTraits<TIn>::template highest_for<TOut>();
 
 1865template <
typename TOut, 
typename TIn>
 
 1866enable_if_t<is_floating_point<TIn>::value && is_floating_point<TOut>::value,
 
 1868canConvertNumber(TIn) {
 
 1871template <
typename TOut, 
typename TIn>
 
 1872TOut convertNumber(TIn value) {
 
 1873  return canConvertNumber<TOut>(value) ? TOut(value) : 0;
 
 1875ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 1876#if defined(__clang__) 
 1877#  pragma clang diagnostic pop 
 1878#elif defined(__GNUC__) 
 1879#  pragma GCC diagnostic pop 
 1881ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 1883class ResourceManager;
 
 1884class CollectionIterator {
 
 1885  friend class CollectionData;
 
 1887  CollectionIterator() : slot_(nullptr), currentId_(NULL_SLOT) {}
 
 1888  void next(
const ResourceManager* resources);
 
 1890    return slot_ == 
nullptr;
 
 1892  bool operator==(
const CollectionIterator& other)
 const {
 
 1893    return slot_ == other.slot_;
 
 1895  bool operator!=(
const CollectionIterator& other)
 const {
 
 1896    return slot_ != other.slot_;
 
 1898  VariantData* operator->() {
 
 1899    ARDUINOJSON_ASSERT(slot_ != 
nullptr);
 
 1903    ARDUINOJSON_ASSERT(slot_ != 
nullptr);
 
 1907    ARDUINOJSON_ASSERT(slot_ != 
nullptr);
 
 1910  VariantData* data() {
 
 1911    return reinterpret_cast<VariantData*
>(slot_);
 
 1913  const VariantData* data()
 const {
 
 1914    return reinterpret_cast<const VariantData*
>(slot_);
 
 1917  CollectionIterator(VariantData* slot, SlotId slotId);
 
 1919  SlotId currentId_, nextId_;
 
 1921class CollectionData {
 
 1922  SlotId head_ = NULL_SLOT;
 
 1923  SlotId tail_ = NULL_SLOT;
 
 1925  static void* 
operator new(
size_t, 
void* p) 
noexcept {
 
 1928  static void operator delete(
void*, 
void*) 
noexcept {}
 
 1929  using iterator = CollectionIterator;
 
 1930  iterator createIterator(
const ResourceManager* resources) 
const;
 
 1931  size_t size(
const ResourceManager*) 
const;
 
 1932  size_t nesting(
const ResourceManager*) 
const;
 
 1933  void clear(ResourceManager* resources);
 
 1934  static void clear(CollectionData* collection, ResourceManager* resources) {
 
 1937    collection->clear(resources);
 
 1939  SlotId head()
 const {
 
 1943  void appendOne(Slot<VariantData> slot, 
const ResourceManager* resources);
 
 1944  void appendPair(Slot<VariantData> key, Slot<VariantData> value,
 
 1945                  const ResourceManager* resources);
 
 1946  void removeOne(iterator it, ResourceManager* resources);
 
 1947  void removePair(iterator it, ResourceManager* resources);
 
 1949  Slot<VariantData> getPreviousSlot(VariantData*, 
const ResourceManager*) 
const;
 
 1951inline const VariantData* collectionToVariant(
 
 1952    const CollectionData* collection) {
 
 1953  const void* data = collection;  
 
 1954  return reinterpret_cast<const VariantData*
>(data);
 
 1956inline VariantData* collectionToVariant(CollectionData* collection) {
 
 1957  void* data = collection;  
 
 1958  return reinterpret_cast<VariantData*
>(data);
 
 1960class ArrayData : 
public CollectionData {
 
 1962  VariantData* addElement(ResourceManager* resources);
 
 1963  static VariantData* addElement(ArrayData* array, ResourceManager* resources) {
 
 1966    return array->addElement(resources);
 
 1968  template <
typename T>
 
 1969  bool addValue(T&& value, ResourceManager* resources);
 
 1970  template <
typename T>
 
 1971  static bool addValue(ArrayData* array, T&& value,
 
 1972                       ResourceManager* resources) {
 
 1975    return array->addValue(value, resources);
 
 1977  VariantData* getOrAddElement(
size_t index, ResourceManager* resources);
 
 1978  VariantData* getElement(
size_t index, 
const ResourceManager* resources) 
const;
 
 1979  static VariantData* getElement(
const ArrayData* array, 
size_t index,
 
 1980                                 const ResourceManager* resources) {
 
 1983    return array->getElement(index, resources);
 
 1985  void removeElement(
size_t index, ResourceManager* resources);
 
 1986  static void removeElement(ArrayData* array, 
size_t index,
 
 1987                            ResourceManager* resources) {
 
 1990    array->removeElement(index, resources);
 
 1992  void remove(iterator it, ResourceManager* resources) {
 
 1993    CollectionData::removeOne(it, resources);
 
 1995  static void remove(ArrayData* array, iterator it,
 
 1996                     ResourceManager* resources) {
 
 1998      return array->remove(it, resources);
 
 2001  iterator at(
size_t index, 
const ResourceManager* resources) 
const;
 
 2003ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 2004ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 2005#if ARDUINOJSON_USE_LONG_LONG 
 2006typedef int64_t JsonInteger;
 
 2007typedef uint64_t JsonUInt;
 
 2009typedef long JsonInteger;
 
 2010typedef unsigned long JsonUInt;
 
 2012ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 2013#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T)                  \ 
 2014  static_assert(sizeof(T) <= sizeof(FLArduinoJson::JsonInteger),           \ 
 2015                "To use 64-bit integers with ArduinoJson, you must set " \ 
 2016                "ARDUINOJSON_USE_LONG_LONG to 1. See "                   \ 
 2017                "https://arduinojson.org/v7/api/config/use_long_long/"); 
 2018ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 2019class ObjectData : 
public CollectionData {
 
 2021  template <
typename TAdaptedString>  
 
 2022  VariantData* addMember(TAdaptedString key, ResourceManager* resources);
 
 2023  template <
typename TAdaptedString>
 
 2024  VariantData* getOrAddMember(TAdaptedString key, ResourceManager* resources);
 
 2025  template <
typename TAdaptedString>
 
 2026  VariantData* getMember(TAdaptedString key,
 
 2027                         const ResourceManager* resources) 
const;
 
 2028  template <
typename TAdaptedString>
 
 2029  static VariantData* getMember(
const ObjectData* 
object, TAdaptedString key,
 
 2030                                const ResourceManager* resources) {
 
 2033    return object->getMember(key, resources);
 
 2035  template <
typename TAdaptedString>
 
 2036  void removeMember(TAdaptedString key, ResourceManager* resources);
 
 2037  template <
typename TAdaptedString>
 
 2038  static void removeMember(ObjectData* obj, TAdaptedString key,
 
 2039                           ResourceManager* resources) {
 
 2042    obj->removeMember(key, resources);
 
 2044  void remove(iterator it, ResourceManager* resources) {
 
 2045    CollectionData::removePair(it, resources);
 
 2047  static void remove(ObjectData* obj, ObjectData::iterator it,
 
 2048                     ResourceManager* resources) {
 
 2051    obj->remove(it, resources);
 
 2053  size_t size(
const ResourceManager* resources)
 const {
 
 2054    return CollectionData::size(resources) / 2;
 
 2056  static size_t size(
const ObjectData* obj, 
const ResourceManager* resources) {
 
 2059    return obj->size(resources);
 
 2062  template <
typename TAdaptedString>
 
 2063  iterator findKey(TAdaptedString key, 
const ResourceManager* resources) 
const;
 
 2065enum class VariantTypeBits : uint8_t {
 
 2066  OwnedStringBit = 0x01,  
 
 2068#if ARDUINOJSON_USE_EXTENSIONS 
 2069  ExtensionBit = 0x10,  
 
 2071  CollectionMask = 0x60,
 
 2073enum class VariantType : uint8_t {
 
 2076  LinkedString = 0x04,  
 
 2082#if ARDUINOJSON_USE_LONG_LONG 
 2086#if ARDUINOJSON_USE_DOUBLE 
 2092inline bool operator&(VariantType type, VariantTypeBits bit) {
 
 2093  return (uint8_t(type) & uint8_t(bit)) != 0;
 
 2095union VariantContent {
 
 2101#if ARDUINOJSON_USE_EXTENSIONS 
 2105  ObjectData asObject;
 
 2106  CollectionData asCollection;
 
 2107  const char* asLinkedString;
 
 2108  struct StringNode* asOwnedString;
 
 2110#if ARDUINOJSON_USE_EXTENSIONS 
 2111union VariantExtension {
 
 2112#  if ARDUINOJSON_USE_LONG_LONG 
 2116#  if ARDUINOJSON_USE_DOUBLE 
 2121template <
typename T>
 
 2122T parseNumber(
const char* s);
 
 2124  VariantContent content_;  
 
 2128  static void* 
operator new(
size_t, 
void* p) 
noexcept {
 
 2131  static void operator delete(
void*, 
void*) 
noexcept {}
 
 2132  VariantData() : type_(VariantType::Null), next_(NULL_SLOT) {}
 
 2133  SlotId next()
 const {
 
 2136  void setNext(SlotId slot) {
 
 2139  template <
typename TVisitor>
 
 2140  typename TVisitor::result_type accept(
 
 2141      TVisitor& visit, 
const ResourceManager* resources)
 const {
 
 2142#if ARDUINOJSON_USE_EXTENSIONS 
 2143    auto extension = getExtension(resources);
 
 2148      case VariantType::Float:
 
 2149        return visit.visit(content_.asFloat);
 
 2150#if ARDUINOJSON_USE_DOUBLE 
 2151      case VariantType::Double:
 
 2152        return visit.visit(extension->asDouble);
 
 2154      case VariantType::Array:
 
 2155        return visit.visit(content_.asArray);
 
 2156      case VariantType::Object:
 
 2157        return visit.visit(content_.asObject);
 
 2158      case VariantType::LinkedString:
 
 2159        return visit.visit(JsonString(content_.asLinkedString));
 
 2160      case VariantType::OwnedString:
 
 2161        return visit.visit(JsonString(content_.asOwnedString->data,
 
 2162                                      content_.asOwnedString->length,
 
 2163                                      JsonString::Copied));
 
 2164      case VariantType::RawString:
 
 2165        return visit.visit(RawString(content_.asOwnedString->data,
 
 2166                                     content_.asOwnedString->length));
 
 2167      case VariantType::Int32:
 
 2168        return visit.visit(
static_cast<JsonInteger
>(content_.asInt32));
 
 2169      case VariantType::Uint32:
 
 2170        return visit.visit(
static_cast<JsonUInt
>(content_.asUint32));
 
 2171#if ARDUINOJSON_USE_LONG_LONG 
 2172      case VariantType::Int64:
 
 2173        return visit.visit(extension->asInt64);
 
 2174      case VariantType::Uint64:
 
 2175        return visit.visit(extension->asUint64);
 
 2177      case VariantType::Boolean:
 
 2178        return visit.visit(content_.asBoolean != 0);
 
 2180        return visit.visit(
nullptr);
 
 2183  template <
typename TVisitor>
 
 2184  static typename TVisitor::result_type accept(
const VariantData* var,
 
 2185                                               const ResourceManager* resources,
 
 2188      return var->accept(visit, resources);
 
 2190      return visit.visit(
nullptr);
 
 2192  VariantData* addElement(ResourceManager* resources) {
 
 2193    auto array = isNull() ? &toArray() : asArray();
 
 2194    return detail::ArrayData::addElement(array, resources);
 
 2196  static VariantData* addElement(VariantData* var, ResourceManager* resources) {
 
 2199    return var->addElement(resources);
 
 2201  template <
typename T>
 
 2202  bool addValue(T&& value, ResourceManager* resources) {
 
 2203    auto array = isNull() ? &toArray() : asArray();
 
 2204    return detail::ArrayData::addValue(array, detail::forward<T>(value),
 
 2207  template <
typename T>
 
 2208  static bool addValue(VariantData* var, T&& value,
 
 2209                       ResourceManager* resources) {
 
 2212    return var->addValue(value, resources);
 
 2214  bool asBoolean(
const ResourceManager* resources)
 const {
 
 2215#if ARDUINOJSON_USE_EXTENSIONS 
 2216    auto extension = getExtension(resources);
 
 2221      case VariantType::Boolean:
 
 2222        return content_.asBoolean;
 
 2223      case VariantType::Uint32:
 
 2224      case VariantType::Int32:
 
 2225        return content_.asUint32 != 0;
 
 2226      case VariantType::Float:
 
 2227        return content_.asFloat != 0;
 
 2228#if ARDUINOJSON_USE_DOUBLE 
 2229      case VariantType::Double:
 
 2230        return extension->asDouble != 0;
 
 2232      case VariantType::Null:
 
 2234#if ARDUINOJSON_USE_LONG_LONG 
 2235      case VariantType::Uint64:
 
 2236      case VariantType::Int64:
 
 2237        return extension->asUint64 != 0;
 
 2243  ArrayData* asArray() {
 
 2244    return isArray() ? &content_.asArray : 0;
 
 2246  const ArrayData* asArray()
 const {
 
 2247    return const_cast<VariantData*
>(
this)->asArray();
 
 2249  CollectionData* asCollection() {
 
 2250    return isCollection() ? &content_.asCollection : 0;
 
 2252  const CollectionData* asCollection()
 const {
 
 2253    return const_cast<VariantData*
>(
this)->asCollection();
 
 2255  template <
typename T>
 
 2256  T asFloat(
const ResourceManager* resources)
 const {
 
 2257    static_assert(is_floating_point<T>::value, 
"T must be a floating point");
 
 2258#if ARDUINOJSON_USE_EXTENSIONS 
 2259    auto extension = getExtension(resources);
 
 2264      case VariantType::Boolean:
 
 2265        return static_cast<T
>(content_.asBoolean);
 
 2266      case VariantType::Uint32:
 
 2267        return static_cast<T
>(content_.asUint32);
 
 2268      case VariantType::Int32:
 
 2269        return static_cast<T
>(content_.asInt32);
 
 2270#if ARDUINOJSON_USE_LONG_LONG 
 2271      case VariantType::Uint64:
 
 2272        return static_cast<T
>(extension->asUint64);
 
 2273      case VariantType::Int64:
 
 2274        return static_cast<T
>(extension->asInt64);
 
 2276      case VariantType::LinkedString:
 
 2277      case VariantType::OwnedString:
 
 2278        return parseNumber<T>(content_.asOwnedString->data);
 
 2279      case VariantType::Float:
 
 2280        return static_cast<T
>(content_.asFloat);
 
 2281#if ARDUINOJSON_USE_DOUBLE 
 2282      case VariantType::Double:
 
 2283        return static_cast<T
>(extension->asDouble);
 
 2289  template <
typename T>
 
 2290  T asIntegral(
const ResourceManager* resources)
 const {
 
 2291    static_assert(is_integral<T>::value, 
"T must be an integral type");
 
 2292#if ARDUINOJSON_USE_EXTENSIONS 
 2293    auto extension = getExtension(resources);
 
 2298      case VariantType::Boolean:
 
 2299        return content_.asBoolean;
 
 2300      case VariantType::Uint32:
 
 2301        return convertNumber<T>(content_.asUint32);
 
 2302      case VariantType::Int32:
 
 2303        return convertNumber<T>(content_.asInt32);
 
 2304#if ARDUINOJSON_USE_LONG_LONG 
 2305      case VariantType::Uint64:
 
 2306        return convertNumber<T>(extension->asUint64);
 
 2307      case VariantType::Int64:
 
 2308        return convertNumber<T>(extension->asInt64);
 
 2310      case VariantType::LinkedString:
 
 2311        return parseNumber<T>(content_.asLinkedString);
 
 2312      case VariantType::OwnedString:
 
 2313        return parseNumber<T>(content_.asOwnedString->data);
 
 2314      case VariantType::Float:
 
 2315        return convertNumber<T>(content_.asFloat);
 
 2316#if ARDUINOJSON_USE_DOUBLE 
 2317      case VariantType::Double:
 
 2318        return convertNumber<T>(extension->asDouble);
 
 2324  ObjectData* asObject() {
 
 2325    return isObject() ? &content_.asObject : 0;
 
 2327  const ObjectData* asObject()
 const {
 
 2328    return const_cast<VariantData*
>(
this)->asObject();
 
 2330  JsonString asRawString()
 const {
 
 2332      case VariantType::RawString:
 
 2333        return JsonString(content_.asOwnedString->data,
 
 2334                          content_.asOwnedString->length, JsonString::Copied);
 
 2336        return JsonString();
 
 2339  JsonString asString()
 const {
 
 2341      case VariantType::LinkedString:
 
 2342        return JsonString(content_.asLinkedString, JsonString::Linked);
 
 2343      case VariantType::OwnedString:
 
 2344        return JsonString(content_.asOwnedString->data,
 
 2345                          content_.asOwnedString->length, JsonString::Copied);
 
 2347        return JsonString();
 
 2350#if ARDUINOJSON_USE_EXTENSIONS 
 2351  const VariantExtension* getExtension(
const ResourceManager* resources) 
const;
 
 2353  VariantData* getElement(
size_t index,
 
 2354                          const ResourceManager* resources)
 const {
 
 2355    return ArrayData::getElement(asArray(), index, resources);
 
 2357  static VariantData* getElement(
const VariantData* var, 
size_t index,
 
 2358                                 const ResourceManager* resources) {
 
 2359    return var != 0 ? var->getElement(index, resources) : 0;
 
 2361  template <
typename TAdaptedString>
 
 2362  VariantData* getMember(TAdaptedString key,
 
 2363                         const ResourceManager* resources)
 const {
 
 2364    return ObjectData::getMember(asObject(), key, resources);
 
 2366  template <
typename TAdaptedString>
 
 2367  static VariantData* getMember(
const VariantData* var, TAdaptedString key,
 
 2368                                const ResourceManager* resources) {
 
 2371    return var->getMember(key, resources);
 
 2373  VariantData* getOrAddElement(
size_t index, ResourceManager* resources) {
 
 2374    auto array = isNull() ? &toArray() : asArray();
 
 2377    return array->getOrAddElement(index, resources);
 
 2379  template <
typename TAdaptedString>
 
 2380  VariantData* getOrAddMember(TAdaptedString key, ResourceManager* resources) {
 
 2383    auto obj = isNull() ? &toObject() : asObject();
 
 2386    return obj->getOrAddMember(key, resources);
 
 2388  bool isArray()
 const {
 
 2389    return type_ == VariantType::Array;
 
 2391  bool isBoolean()
 const {
 
 2392    return type_ == VariantType::Boolean;
 
 2394  bool isCollection()
 const {
 
 2395    return type_ & VariantTypeBits::CollectionMask;
 
 2397  bool isFloat()
 const {
 
 2398    return type_ & VariantTypeBits::NumberBit;
 
 2400  template <
typename T>
 
 2401  bool isInteger(
const ResourceManager* resources)
 const {
 
 2402#if ARDUINOJSON_USE_LONG_LONG 
 2403    auto extension = getExtension(resources);
 
 2408      case VariantType::Uint32:
 
 2409        return canConvertNumber<T>(content_.asUint32);
 
 2410      case VariantType::Int32:
 
 2411        return canConvertNumber<T>(content_.asInt32);
 
 2412#if ARDUINOJSON_USE_LONG_LONG 
 2413      case VariantType::Uint64:
 
 2414        return canConvertNumber<T>(extension->asUint64);
 
 2415      case VariantType::Int64:
 
 2416        return canConvertNumber<T>(extension->asInt64);
 
 2422  bool isNull()
 const {
 
 2423    return type_ == VariantType::Null;
 
 2425  static bool isNull(
const VariantData* var) {
 
 2428    return var->isNull();
 
 2430  bool isObject()
 const {
 
 2431    return type_ == VariantType::Object;
 
 2433  bool isString()
 const {
 
 2434    return type_ == VariantType::LinkedString ||
 
 2435           type_ == VariantType::OwnedString;
 
 2437  size_t nesting(
const ResourceManager* resources)
 const {
 
 2438    auto collection = asCollection();
 
 2440      return collection->nesting(resources);
 
 2444  static size_t nesting(
const VariantData* var,
 
 2445                        const ResourceManager* resources) {
 
 2448    return var->nesting(resources);
 
 2450  void removeElement(
size_t index, ResourceManager* resources) {
 
 2451    ArrayData::removeElement(asArray(), index, resources);
 
 2453  static void removeElement(VariantData* var, 
size_t index,
 
 2454                            ResourceManager* resources) {
 
 2457    var->removeElement(index, resources);
 
 2459  template <
typename TAdaptedString>
 
 2460  void removeMember(TAdaptedString key, ResourceManager* resources) {
 
 2461    ObjectData::removeMember(asObject(), key, resources);
 
 2463  template <
typename TAdaptedString>
 
 2464  static void removeMember(VariantData* var, TAdaptedString key,
 
 2465                           ResourceManager* resources) {
 
 2468    var->removeMember(key, resources);
 
 2471    type_ = VariantType::Null;
 
 2473  void setBoolean(
bool value) {
 
 2474    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 2475    type_ = VariantType::Boolean;
 
 2476    content_.asBoolean = value;
 
 2478  template <
typename T>
 
 2479  enable_if_t<
sizeof(T) == 4, 
bool> setFloat(T value, ResourceManager*) {
 
 2480    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 2481    type_ = VariantType::Float;
 
 2482    content_.asFloat = value;
 
 2485  template <
typename T>
 
 2486  enable_if_t<
sizeof(T) == 8, 
bool> setFloat(T value, ResourceManager*);
 
 2487  template <
typename T>
 
 2488  enable_if_t<is_signed<T>::value, 
bool> setInteger(T value,
 
 2489                                                    ResourceManager* resources);
 
 2490  template <
typename T>
 
 2491  enable_if_t<is_unsigned<T>::value, 
bool> setInteger(
 
 2492      T value, ResourceManager* resources);
 
 2493  void setRawString(StringNode* s) {
 
 2494    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 2495    ARDUINOJSON_ASSERT(s);
 
 2496    type_ = VariantType::RawString;
 
 2497    content_.asOwnedString = s;
 
 2499  template <
typename T>
 
 2500  void setRawString(SerializedValue<T> value, ResourceManager* resources);
 
 2501  template <
typename T>
 
 2502  static void setRawString(VariantData* var, SerializedValue<T> value,
 
 2503                           ResourceManager* resources) {
 
 2506    var->clear(resources);
 
 2507    var->setRawString(value, resources);
 
 2509  template <
typename TAdaptedString>
 
 2510  bool setString(TAdaptedString value, ResourceManager* resources);
 
 2511  bool setString(StringNode* s, ResourceManager*) {
 
 2515  template <
typename TAdaptedString>
 
 2516  static void setString(VariantData* var, TAdaptedString value,
 
 2517                        ResourceManager* resources) {
 
 2520    var->clear(resources);
 
 2521    var->setString(value, resources);
 
 2523  void setLinkedString(
const char* s) {
 
 2524    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 2525    ARDUINOJSON_ASSERT(s);
 
 2526    type_ = VariantType::LinkedString;
 
 2527    content_.asLinkedString = s;
 
 2529  void setOwnedString(StringNode* s) {
 
 2530    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 2531    ARDUINOJSON_ASSERT(s);
 
 2532    type_ = VariantType::OwnedString;
 
 2533    content_.asOwnedString = s;
 
 2535  size_t size(
const ResourceManager* resources)
 const {
 
 2537      return content_.asObject.size(resources);
 
 2539      return content_.asArray.size(resources);
 
 2542  static size_t size(
const VariantData* var, 
const ResourceManager* resources) {
 
 2543    return var != 0 ? var->size(resources) : 0;
 
 2545  ArrayData& toArray() {
 
 2546    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 2547    type_ = VariantType::Array;
 
 2548    new (&content_.asArray) ArrayData();
 
 2549    return content_.asArray;
 
 2551  static ArrayData* toArray(VariantData* var, ResourceManager* resources) {
 
 2554    var->clear(resources);
 
 2555    return &var->toArray();
 
 2557  ObjectData& toObject() {
 
 2558    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 2559    type_ = VariantType::Object;
 
 2560    new (&content_.asObject) ObjectData();
 
 2561    return content_.asObject;
 
 2563  static ObjectData* toObject(VariantData* var, ResourceManager* resources) {
 
 2566    var->clear(resources);
 
 2567    return &var->toObject();
 
 2569  VariantType type()
 const {
 
 2572  void clear(ResourceManager* resources);
 
 2573  static void clear(VariantData* var, ResourceManager* resources) {
 
 2576    var->clear(resources);
 
 2581class ResourceManager {
 
 2583    VariantData variant;
 
 2584#if ARDUINOJSON_USE_EXTENSIONS 
 2585    VariantExtension extension;
 
 2589  constexpr static size_t slotSize = 
sizeof(SlotData);
 
 2590  ResourceManager(Allocator* allocator = DefaultAllocator::instance())
 
 2591      : allocator_(allocator), overflowed_(false) {}
 
 2592  ~ResourceManager() {
 
 2593    stringPool_.clear(allocator_);
 
 2594    variantPools_.clear(allocator_);
 
 2596  ResourceManager(
const ResourceManager&) = 
delete;
 
 2597  ResourceManager& operator=(
const ResourceManager& src) = 
delete;
 
 2598  friend void swap(ResourceManager& a, ResourceManager& b) {
 
 2599    swap(a.stringPool_, b.stringPool_);
 
 2600    swap(a.variantPools_, b.variantPools_);
 
 2601    swap_(a.allocator_, b.allocator_);
 
 2602    swap_(a.overflowed_, b.overflowed_);
 
 2604  Allocator* allocator()
 const {
 
 2607  size_t size()
 const {
 
 2608    return variantPools_.size() + stringPool_.size();
 
 2610  bool overflowed()
 const {
 
 2613  Slot<VariantData> allocVariant();
 
 2614  void freeVariant(Slot<VariantData> slot);
 
 2615  VariantData* getVariant(SlotId 
id) 
const;
 
 2616#if ARDUINOJSON_USE_EXTENSIONS 
 2617  Slot<VariantExtension> allocExtension();
 
 2618  void freeExtension(SlotId slot);
 
 2619  VariantExtension* getExtension(SlotId 
id) 
const;
 
 2621  template <
typename TAdaptedString>
 
 2622  StringNode* saveString(TAdaptedString str) {
 
 2625    auto node = stringPool_.add(str, allocator_);
 
 2630  void saveString(StringNode* node) {
 
 2631    stringPool_.add(node);
 
 2633  template <
typename TAdaptedString>
 
 2634  StringNode* getString(
const TAdaptedString& str)
 const {
 
 2635    return stringPool_.get(str);
 
 2637  StringNode* createString(
size_t length) {
 
 2638    auto node = StringNode::create(
length, allocator_);
 
 2643  StringNode* resizeString(StringNode* node, 
size_t length) {
 
 2644    node = StringNode::resize(node, 
length, allocator_);
 
 2649  void destroyString(StringNode* node) {
 
 2650    StringNode::destroy(node, allocator_);
 
 2652  void dereferenceString(
const char* s) {
 
 2653    stringPool_.dereference(s, allocator_);
 
 2656    variantPools_.clear(allocator_);
 
 2657    overflowed_ = 
false;
 
 2658    stringPool_.clear(allocator_);
 
 2660  void shrinkToFit() {
 
 2661    variantPools_.shrinkToFit(allocator_);
 
 2664  Allocator* allocator_;
 
 2666  StringPool stringPool_;
 
 2667  MemoryPoolList<SlotData> variantPools_;
 
 2669template <
typename T, 
typename Enable = 
void>
 
 2671template <
typename T>
 
 2672struct IsString<T, void_t<typename StringAdapter<T>::AdaptedString>>
 
 2674ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 2675ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 2679ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 2680ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 2681template <
typename T>
 
 2692struct VariantTo<JsonVariant> {
 
 2693  typedef JsonVariant type;
 
 2695class VariantAttorney {
 
 2697  template <
typename TClient>
 
 2698  static auto getResourceManager(TClient& client)
 
 2699      -> 
decltype(client.getResourceManager()) {
 
 2700    return client.getResourceManager();
 
 2702  template <
typename TClient>
 
 2703  static auto getData(TClient& client) -> 
decltype(client.getData()) {
 
 2704    return client.getData();
 
 2706  template <
typename TClient>
 
 2707  static VariantData* getOrCreateData(TClient& client) {
 
 2708    return client.getOrCreateData();
 
 2712  COMPARE_RESULT_DIFFER = 0,
 
 2713  COMPARE_RESULT_EQUAL = 1,
 
 2714  COMPARE_RESULT_GREATER = 2,
 
 2715  COMPARE_RESULT_LESS = 4,
 
 2716  COMPARE_RESULT_GREATER_OR_EQUAL = 3,
 
 2717  COMPARE_RESULT_LESS_OR_EQUAL = 5
 
 2719template <
typename T>
 
 2720CompareResult arithmeticCompare(
const T& lhs, 
const T& rhs) {
 
 2722    return COMPARE_RESULT_LESS;
 
 2724    return COMPARE_RESULT_GREATER;
 
 2726    return COMPARE_RESULT_EQUAL;
 
 2728template <
typename T1, 
typename T2>
 
 2729CompareResult arithmeticCompare(
 
 2730    const T1& lhs, 
const T2& rhs,
 
 2731    enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
 
 2732                sizeof(T1) < 
sizeof(T2)>* = 0) {
 
 2733  return arithmeticCompare<T2>(
static_cast<T2
>(lhs), rhs);
 
 2735template <
typename T1, 
typename T2>
 
 2736CompareResult arithmeticCompare(
 
 2737    const T1& lhs, 
const T2& rhs,
 
 2738    enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
 
 2739                sizeof(T2) < 
sizeof(T1)>* = 0) {
 
 2740  return arithmeticCompare<T1>(lhs, 
static_cast<T1
>(rhs));
 
 2742template <
typename T1, 
typename T2>
 
 2743CompareResult arithmeticCompare(
 
 2744    const T1& lhs, 
const T2& rhs,
 
 2745    enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
 
 2746                is_signed<T1>::value == is_signed<T2>::value &&
 
 2747                sizeof(T2) == 
sizeof(T1)>* = 0) {
 
 2748  return arithmeticCompare<T1>(lhs, 
static_cast<T1
>(rhs));
 
 2750template <
typename T1, 
typename T2>
 
 2751CompareResult arithmeticCompare(
 
 2752    const T1& lhs, 
const T2& rhs,
 
 2753    enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
 
 2754                is_unsigned<T1>::value && is_signed<T2>::value &&
 
 2755                sizeof(T2) == 
sizeof(T1)>* = 0) {
 
 2757    return COMPARE_RESULT_GREATER;
 
 2758  return arithmeticCompare<T1>(lhs, 
static_cast<T1
>(rhs));
 
 2760template <
typename T1, 
typename T2>
 
 2761CompareResult arithmeticCompare(
 
 2762    const T1& lhs, 
const T2& rhs,
 
 2763    enable_if_t<is_integral<T1>::value && is_integral<T2>::value &&
 
 2764                is_signed<T1>::value && is_unsigned<T2>::value &&
 
 2765                sizeof(T2) == 
sizeof(T1)>* = 0) {
 
 2767    return COMPARE_RESULT_LESS;
 
 2768  return arithmeticCompare<T2>(
static_cast<T2
>(lhs), rhs);
 
 2770template <
typename T1, 
typename T2>
 
 2771CompareResult arithmeticCompare(
 
 2772    const T1& lhs, 
const T2& rhs,
 
 2773    enable_if_t<is_floating_point<T1>::value || is_floating_point<T2>::value>* =
 
 2775  return arithmeticCompare<double>(
static_cast<double>(lhs),
 
 2776                                   static_cast<double>(rhs));
 
 2778template <
typename T2>
 
 2779CompareResult arithmeticCompareNegateLeft(
 
 2780    JsonUInt, 
const T2&, enable_if_t<is_unsigned<T2>::value>* = 0) {
 
 2781  return COMPARE_RESULT_LESS;
 
 2783template <
typename T2>
 
 2784CompareResult arithmeticCompareNegateLeft(
 
 2785    JsonUInt lhs, 
const T2& rhs, enable_if_t<is_signed<T2>::value>* = 0) {
 
 2787    return COMPARE_RESULT_LESS;
 
 2788  return arithmeticCompare(-rhs, 
static_cast<T2
>(lhs));
 
 2790template <
typename T1>
 
 2791CompareResult arithmeticCompareNegateRight(
 
 2792    const T1&, JsonUInt, enable_if_t<is_unsigned<T1>::value>* = 0) {
 
 2793  return COMPARE_RESULT_GREATER;
 
 2795template <
typename T1>
 
 2796CompareResult arithmeticCompareNegateRight(
 
 2797    const T1& lhs, JsonUInt rhs, enable_if_t<is_signed<T1>::value>* = 0) {
 
 2799    return COMPARE_RESULT_GREATER;
 
 2800  return arithmeticCompare(
static_cast<T1
>(rhs), -lhs);
 
 2802struct VariantTag {};
 
 2803template <
typename T>
 
 2804struct IsVariant : is_base_of<VariantTag, T> {};
 
 2805ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 2806ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 2807class JsonVariantConst;
 
 2808ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 2809ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 2810template <
typename T>
 
 2811CompareResult compare(JsonVariantConst lhs,
 
 2813struct VariantOperatorTag {};
 
 2814template <
typename TVariant>
 
 2815struct VariantOperators : VariantOperatorTag {
 
 2816  template <
typename T>
 
 2817  friend enable_if_t<!IsVariant<T>::value && !is_array<T>::value, T> 
operator|(
 
 2818      const TVariant& variant, 
const T& defaultValue) {
 
 2819    if (variant.template is<T>())
 
 2820      return variant.template as<T>();
 
 2822      return defaultValue;
 
 2824  friend const char* 
operator|(
const TVariant& variant,
 
 2825                               const char* defaultValue) {
 
 2826    if (variant.template is<const char*>())
 
 2827      return variant.template as<const char*>();
 
 2829      return defaultValue;
 
 2831  template <
typename T>
 
 2832  friend enable_if_t<IsVariant<T>::value, JsonVariantConst> 
operator|(
 
 2833      const TVariant& variant, T defaultValue) {
 
 2837      return defaultValue;
 
 2839  template <
typename T>
 
 2840  friend bool operator==(T* lhs, TVariant rhs) {
 
 2841    return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
 
 2843  template <
typename T>
 
 2844  friend bool operator==(
const T& lhs, TVariant rhs) {
 
 2845    return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
 
 2847  template <
typename T>
 
 2848  friend bool operator==(TVariant lhs, T* rhs) {
 
 2849    return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
 
 2851  template <
typename T>
 
 2852  friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, 
bool>
 
 2854    return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
 
 2856  template <
typename T>
 
 2857  friend bool operator!=(T* lhs, TVariant rhs) {
 
 2858    return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
 
 2860  template <
typename T>
 
 2861  friend bool operator!=(
const T& lhs, TVariant rhs) {
 
 2862    return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
 
 2864  template <
typename T>
 
 2865  friend bool operator!=(TVariant lhs, T* rhs) {
 
 2866    return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
 
 2868  template <
typename T>
 
 2869  friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, 
bool>
 
 2871    return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
 
 2873  template <
typename T>
 
 2874  friend bool operator<(T* lhs, TVariant rhs) {
 
 2875    return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
 
 2877  template <
typename T>
 
 2878  friend bool operator<(
const T& lhs, TVariant rhs) {
 
 2879    return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
 
 2881  template <
typename T>
 
 2882  friend bool operator<(TVariant lhs, T* rhs) {
 
 2883    return compare(lhs, rhs) == COMPARE_RESULT_LESS;
 
 2885  template <
typename T>
 
 2886  friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, 
bool> 
operator<(
 
 2887      TVariant lhs, 
const T& rhs) {
 
 2888    return compare(lhs, rhs) == COMPARE_RESULT_LESS;
 
 2890  template <
typename T>
 
 2891  friend bool operator<=(T* lhs, TVariant rhs) {
 
 2892    return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
 
 2894  template <
typename T>
 
 2895  friend bool operator<=(
const T& lhs, TVariant rhs) {
 
 2896    return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
 
 2898  template <
typename T>
 
 2899  friend bool operator<=(TVariant lhs, T* rhs) {
 
 2900    return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
 
 2902  template <
typename T>
 
 2903  friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, 
bool>
 
 2905    return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
 
 2907  template <
typename T>
 
 2908  friend bool operator>(T* lhs, TVariant rhs) {
 
 2909    return compare(rhs, lhs) == COMPARE_RESULT_LESS;
 
 2911  template <
typename T>
 
 2912  friend bool operator>(
const T& lhs, TVariant rhs) {
 
 2913    return compare(rhs, lhs) == COMPARE_RESULT_LESS;
 
 2915  template <
typename T>
 
 2916  friend bool operator>(TVariant lhs, T* rhs) {
 
 2917    return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
 
 2919  template <
typename T>
 
 2920  friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, 
bool> 
operator>(
 
 2921      TVariant lhs, 
const T& rhs) {
 
 2922    return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
 
 2924  template <
typename T>
 
 2925  friend bool operator>=(T* lhs, TVariant rhs) {
 
 2926    return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
 
 2928  template <
typename T>
 
 2929  friend bool operator>=(
const T& lhs, TVariant rhs) {
 
 2930    return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
 
 2932  template <
typename T>
 
 2933  friend bool operator>=(TVariant lhs, T* rhs) {
 
 2934    return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
 
 2936  template <
typename T>
 
 2937  friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, 
bool>
 
 2939    return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
 
 2942ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 2943ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 2946class JsonVariantConst : 
public detail::VariantTag,
 
 2947                         public detail::VariantOperators<JsonVariantConst> {
 
 2948  friend class detail::VariantAttorney;
 
 2949  template <
typename T>
 
 2950  using ConversionSupported =
 
 2951      detail::is_same<
typename detail::function_traits<
 
 2952                          decltype(&Converter<T>::fromJson)>::arg1_type,
 
 2955  JsonVariantConst() : data_(nullptr), resources_(nullptr) {}
 
 2956  explicit JsonVariantConst(
const detail::VariantData* data,
 
 2957                            const detail::ResourceManager* resources)
 
 2958      : data_(data), resources_(resources) {}
 
 2959  bool isNull()
 const {
 
 2960    return detail::VariantData::isNull(data_);
 
 2962  bool isUnbound()
 const {
 
 2965  size_t nesting()
 const {
 
 2966    return detail::VariantData::nesting(data_, resources_);
 
 2968  size_t size()
 const {
 
 2969    return detail::VariantData::size(data_, resources_);
 
 2971  template <
typename T,
 
 2972            detail::enable_if_t<ConversionSupported<T>::value, 
bool> = 
true>
 
 2974    return Converter<T>::fromJson(*
this);
 
 2976  template <
typename T,
 
 2977            detail::enable_if_t<!ConversionSupported<T>::value, 
bool> = 
true>
 
 2978  detail::InvalidConversion<JsonVariantConst, T> as() 
const;
 
 2979  template <
typename T>
 
 2980  detail::enable_if_t<ConversionSupported<T>::value, 
bool> is()
 const {
 
 2981    return Converter<T>::checkJson(*
this);
 
 2983  template <
typename T>
 
 2984  detail::enable_if_t<!ConversionSupported<T>::value, 
bool> is()
 const {
 
 2987  template <
typename T>
 
 2988  operator T()
 const {
 
 2991  template <
typename T>
 
 2992  detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst>
 
 2993  operator[](T index)
 const {
 
 2994    return JsonVariantConst(
 
 2995        detail::VariantData::getElement(data_, 
size_t(index), resources_),
 
 2998  template <
typename TString>
 
 2999  detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
 
 3000  operator[](
const TString& key)
 const {
 
 3001    return JsonVariantConst(detail::VariantData::getMember(
 
 3002                                data_, detail::adaptString(key), resources_),
 
 3005  template <
typename TChar>
 
 3006  detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
 
 3007  operator[](TChar* key)
 const {
 
 3008    return JsonVariantConst(detail::VariantData::getMember(
 
 3009                                data_, detail::adaptString(key), resources_),
 
 3012  template <
typename TVariant>
 
 3013  detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
 
 3014  operator[](
const TVariant& key)
 const {
 
 3015    if (key.template is<size_t>())
 
 3016      return operator[](key.template as<size_t>());
 
 3018      return operator[](key.template as<const char*>());
 
 3020  template <
typename TString>
 
 3021  ARDUINOJSON_DEPRECATED(
"use var[key].is<T>() instead")
 
 3022  detail::enable_if_t<detail::IsString<TString>::value, 
bool> containsKey(
 
 3023      const TString& key)
 const {
 
 3024    return detail::VariantData::getMember(getData(), detail::adaptString(key),
 
 3027  template <
typename TChar>
 
 3028  ARDUINOJSON_DEPRECATED(
"use obj[\"key\"].is<T>() instead")
 
 3029  detail::enable_if_t<detail::IsString<TChar*>::value, 
bool> containsKey(
 
 3031    return detail::VariantData::getMember(getData(), detail::adaptString(key),
 
 3034  template <
typename TVariant>
 
 3035  ARDUINOJSON_DEPRECATED(
"use var[key].is<T>() instead")
 
 3036  detail::enable_if_t<detail::IsVariant<TVariant>::value, 
bool> containsKey(
 
 3037      const TVariant& key)
 const {
 
 3038    return containsKey(key.template as<const char*>());
 
 3040  ARDUINOJSON_DEPRECATED(
"always returns zero")
 
 3041  size_t memoryUsage()
 const {
 
 3045  const detail::VariantData* getData()
 const {
 
 3048  const detail::ResourceManager* getResourceManager()
 const {
 
 3052  const detail::VariantData* data_;
 
 3053  const detail::ResourceManager* resources_;
 
 3056ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 3057ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 3060template <
typename, 
typename>
 
 3062template <
typename TDerived>
 
 3063class VariantRefBase : 
public VariantTag {
 
 3064  friend class VariantAttorney;
 
 3066  void clear()
 const {
 
 3067    VariantData::clear(getOrCreateData(), getResourceManager());
 
 3069  bool isNull()
 const {
 
 3070    return VariantData::isNull(getData());
 
 3072  bool isUnbound()
 const {
 
 3075  template <
typename T>
 
 3077  template <typename T, typename = enable_if_t<!is_same<T, TDerived>::value>>
 
 3078  operator T()
 const {
 
 3081  template <
typename T>
 
 3082  enable_if_t<is_same<T, JsonArray>::value, 
JsonArray> to() 
const;
 
 3083  template <
typename T>
 
 3084  enable_if_t<is_same<T, JsonObject>::value, 
JsonObject> to() 
const;
 
 3085  template <
typename T>
 
 3086  enable_if_t<is_same<T, JsonVariant>::value, JsonVariant> to() 
const;
 
 3087  template <
typename T>
 
 3088  FORCE_INLINE 
bool is() 
const;
 
 3089  template <
typename T>
 
 3090  bool set(
const T& value)
 const {
 
 3091    return doSet<Converter<remove_cv_t<T>>>(value);
 
 3093  template <
typename T>
 
 3094  bool set(T* value)
 const {
 
 3095    return doSet<Converter<T*>>(value);
 
 3097  size_t size()
 const {
 
 3098    return VariantData::size(getData(), getResourceManager());
 
 3100  size_t nesting()
 const {
 
 3101    return VariantData::nesting(getData(), getResourceManager());
 
 3103  template <
typename T>
 
 3104  enable_if_t<!is_same<T, JsonVariant>::value, T> add()
 const {
 
 3105    return add<JsonVariant>().template to<T>();
 
 3107  template <
typename T>
 
 3108  enable_if_t<is_same<T, JsonVariant>::value, T> add() 
const;
 
 3109  template <
typename T>
 
 3110  bool add(
const T& value)
 const {
 
 3111    return detail::VariantData::addValue(getOrCreateData(), value,
 
 3112                                         getResourceManager());
 
 3114  template <
typename T>
 
 3115  bool add(T* value)
 const {
 
 3116    return detail::VariantData::addValue(getOrCreateData(), value,
 
 3117                                         getResourceManager());
 
 3119  void remove(
size_t index)
 const {
 
 3120    VariantData::removeElement(getData(), index, getResourceManager());
 
 3122  template <
typename TChar>
 
 3123  enable_if_t<IsString<TChar*>::value> 
remove(TChar* key)
 const {
 
 3124    VariantData::removeMember(getData(), adaptString(key),
 
 3125                              getResourceManager());
 
 3127  template <
typename TString>
 
 3128  enable_if_t<IsString<TString>::value> 
remove(
const TString& key)
 const {
 
 3129    VariantData::removeMember(getData(), adaptString(key),
 
 3130                              getResourceManager());
 
 3132  template <
typename TVariant>
 
 3133  enable_if_t<IsVariant<TVariant>::value> 
remove(
const TVariant& key)
 const {
 
 3134    if (key.template is<size_t>())
 
 3135      remove(key.template as<size_t>());
 
 3137      remove(key.template as<const char*>());
 
 3139  ElementProxy<TDerived> operator[](
size_t index) 
const;
 
 3140  template <
typename TString>
 
 3141  ARDUINOJSON_DEPRECATED(
"use obj[key].is<T>() instead")
 
 3142  enable_if_t<IsString<TString>::value, 
bool> containsKey(
 
 3143      const TString& key) const;
 
 3144  template <typename TChar>
 
 3145  ARDUINOJSON_DEPRECATED(
"use obj[\"key\"].is<T>() instead")
 
 3146  enable_if_t<IsString<TChar*>::value, 
bool> containsKey(TChar* key) const;
 
 3147  template <typename TVariant>
 
 3148  ARDUINOJSON_DEPRECATED(
"use obj[key].is<T>() instead")
 
 3149  enable_if_t<IsVariant<TVariant>::value, 
bool> containsKey(
 
 3150      const TVariant& key) const;
 
 3151  template <typename TString>
 
 3153      enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>>
 
 3154      operator[](const TString& key) const;
 
 3155  template <typename TChar>
 
 3157      enable_if_t<IsString<TChar*>::value, MemberProxy<TDerived, TChar*>>
 
 3158      operator[](TChar* key) const;
 
 3159  template <typename TVariant>
 
 3160  enable_if_t<IsVariant<TVariant>::value, JsonVariantConst> operator[](
 
 3161      const TVariant& key)
 const {
 
 3162    if (key.template is<size_t>())
 
 3163      return operator[](key.template as<size_t>());
 
 3165      return operator[](key.template as<const char*>());
 
 3167  ARDUINOJSON_DEPRECATED(
"use add<JsonVariant>() instead")
 
 3168  JsonVariant add() const;
 
 3169  ARDUINOJSON_DEPRECATED(
"use add<JsonArray>() instead")
 
 3170  JsonArray createNestedArray() const;
 
 3171  template <typename TChar>
 
 3172  ARDUINOJSON_DEPRECATED(
"use var[key].to<JsonArray>() instead")
 
 3173  JsonArray createNestedArray(TChar* key) const;
 
 3174  template <typename TString>
 
 3175  ARDUINOJSON_DEPRECATED(
"use var[key].to<JsonArray>() instead")
 
 3176  JsonArray createNestedArray(const TString& key) const;
 
 3177  ARDUINOJSON_DEPRECATED(
"use add<JsonObject>() instead")
 
 3178  JsonObject createNestedObject() const;
 
 3179  template <typename TChar>
 
 3180  ARDUINOJSON_DEPRECATED(
"use var[key].to<JsonObject>() instead")
 
 3181  JsonObject createNestedObject(TChar* key) const;
 
 3182  template <typename TString>
 
 3183  ARDUINOJSON_DEPRECATED(
"use var[key].to<JsonObject>() instead")
 
 3184  JsonObject createNestedObject(const TString& key) const;
 
 3185  ARDUINOJSON_DEPRECATED(
"always returns zero")
 
 3186  size_t memoryUsage()
 const {
 
 3189  ARDUINOJSON_DEPRECATED(
"performs a deep copy")
 
 3190  void shallowCopy(JsonVariantConst src)
 const {
 
 3194  TDerived& derived() {
 
 3195    return static_cast<TDerived&
>(*this);
 
 3197  const TDerived& derived()
 const {
 
 3198    return static_cast<const TDerived&
>(*this);
 
 3200  ResourceManager* getResourceManager()
 const {
 
 3201    return VariantAttorney::getResourceManager(derived());
 
 3203  VariantData* getData()
 const {
 
 3204    return VariantAttorney::getData(derived());
 
 3206  VariantData* getOrCreateData()
 const {
 
 3207    return VariantAttorney::getOrCreateData(derived());
 
 3209  FORCE_INLINE FLArduinoJson::JsonVariant getVariant() 
const;
 
 3210  FORCE_INLINE FLArduinoJson::JsonVariantConst getVariantConst()
 const {
 
 3211    return FLArduinoJson::JsonVariantConst(getData(), getResourceManager());
 
 3213  template <
typename T>
 
 3214  FORCE_INLINE enable_if_t<is_same<T, JsonVariantConst>::value, T> getVariant()
 
 3216    return getVariantConst();
 
 3218  template <
typename T>
 
 3219  FORCE_INLINE enable_if_t<is_same<T, JsonVariant>::value, T> getVariant()
 
 3221    return getVariant();
 
 3223  template <
typename TConverter, 
typename T>
 
 3224  bool doSet(T&& value)
 const {
 
 3225    return doSet<TConverter>(
 
 3226        detail::forward<T>(value),
 
 3227        is_same<
typename function_traits<
 
 3228                    decltype(&TConverter::toJson)>::return_type,
 
 3231  template <
typename TConverter, 
typename T>
 
 3232  bool doSet(T&& value, false_type) 
const;
 
 3233  template <
typename TConverter, 
typename T>
 
 3234  bool doSet(T&& value, true_type) 
const;
 
 3235  FLArduinoJson::JsonVariant getOrCreateVariant() 
const;
 
 3237template <
typename TUpstream>
 
 3238class ElementProxy : 
public VariantRefBase<ElementProxy<TUpstream>>,
 
 3239                     public VariantOperators<ElementProxy<TUpstream>> {
 
 3240  friend class VariantAttorney;
 
 3242  ElementProxy(TUpstream upstream, 
size_t index)
 
 3243      : upstream_(upstream), index_(index) {}
 
 3244  ElementProxy(
const ElementProxy& src)
 
 3245      : upstream_(src.upstream_), index_(src.index_) {}
 
 3246  ElementProxy& operator=(
const ElementProxy& src) {
 
 3250  template <
typename T>
 
 3251  ElementProxy& operator=(
const T& src) {
 
 3255  template <
typename T>
 
 3256  ElementProxy& operator=(T* src) {
 
 3261  ResourceManager* getResourceManager()
 const {
 
 3262    return VariantAttorney::getResourceManager(upstream_);
 
 3264  FORCE_INLINE VariantData* getData()
 const {
 
 3265    return VariantData::getElement(
 
 3266        VariantAttorney::getData(upstream_), index_,
 
 3267        VariantAttorney::getResourceManager(upstream_));
 
 3269  VariantData* getOrCreateData()
 const {
 
 3270    auto data = VariantAttorney::getOrCreateData(upstream_);
 
 3273    return data->getOrAddElement(
 
 3274        index_, VariantAttorney::getResourceManager(upstream_));
 
 3276  TUpstream upstream_;
 
 3279ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 3280ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 3281class JsonVariant : 
public detail::VariantRefBase<JsonVariant>,
 
 3282                    public detail::VariantOperators<JsonVariant> {
 
 3283  friend class detail::VariantAttorney;
 
 3285  JsonVariant() : data_(0), resources_(0) {}
 
 3286  JsonVariant(detail::VariantData* data, detail::ResourceManager* resources)
 
 3287      : data_(data), resources_(resources) {}
 
 3289  detail::ResourceManager* getResourceManager()
 const {
 
 3292  detail::VariantData* getData()
 const {
 
 3295  detail::VariantData* getOrCreateData()
 const {
 
 3298  detail::VariantData* data_;
 
 3299  detail::ResourceManager* resources_;
 
 3302bool copyVariant(JsonVariant dst, JsonVariantConst src);
 
 3305struct Converter<JsonVariant> : 
private detail::VariantAttorney {
 
 3306  static void toJson(JsonVariantConst src, JsonVariant dst) {
 
 3307    copyVariant(dst, src);
 
 3309  static JsonVariant fromJson(JsonVariant src) {
 
 3312  static bool checkJson(JsonVariant src) {
 
 3313    auto data = getData(src);
 
 3318struct Converter<JsonVariantConst> : 
private detail::VariantAttorney {
 
 3319  static void toJson(JsonVariantConst src, JsonVariant dst) {
 
 3320    copyVariant(dst, src);
 
 3322  static JsonVariantConst fromJson(JsonVariantConst src) {
 
 3323    return JsonVariantConst(getData(src), getResourceManager(src));
 
 3325  static bool checkJson(JsonVariantConst src) {
 
 3326    auto data = getData(src);
 
 3330template <
typename T>
 
 3333  Ref(T value) : value_(value) {}
 
 3343class JsonArrayIterator {
 
 3346  JsonArrayIterator() {}
 
 3347  explicit JsonArrayIterator(detail::ArrayData::iterator iterator,
 
 3348                             detail::ResourceManager* resources)
 
 3349      : iterator_(iterator), resources_(resources) {}
 
 3351    return JsonVariant(iterator_.data(), resources_);
 
 3353  Ref<JsonVariant> operator->() {
 
 3356  bool operator==(
const JsonArrayIterator& other)
 const {
 
 3357    return iterator_ == other.iterator_;
 
 3359  bool operator!=(
const JsonArrayIterator& other)
 const {
 
 3360    return iterator_ != other.iterator_;
 
 3362  JsonArrayIterator& operator++() {
 
 3363    iterator_.next(resources_);
 
 3367  detail::ArrayData::iterator iterator_;
 
 3368  detail::ResourceManager* resources_;
 
 3370class JsonArrayConstIterator {
 
 3373  JsonArrayConstIterator() {}
 
 3374  explicit JsonArrayConstIterator(detail::ArrayData::iterator iterator,
 
 3375                                  const detail::ResourceManager* resources)
 
 3376      : iterator_(iterator), resources_(resources) {}
 
 3378    return JsonVariantConst(iterator_.data(), resources_);
 
 3380  Ref<JsonVariantConst> operator->() {
 
 3383  bool operator==(
const JsonArrayConstIterator& other)
 const {
 
 3384    return iterator_ == other.iterator_;
 
 3386  bool operator!=(
const JsonArrayConstIterator& other)
 const {
 
 3387    return iterator_ != other.iterator_;
 
 3389  JsonArrayConstIterator& operator++() {
 
 3390    iterator_.next(resources_);
 
 3394  detail::ArrayData::iterator iterator_;
 
 3395  const detail::ResourceManager* resources_;
 
 3398class JsonArrayConst : 
public detail::VariantOperators<JsonArrayConst> {
 
 3400  friend class detail::VariantAttorney;
 
 3402  typedef JsonArrayConstIterator iterator;
 
 3403  iterator 
begin()
 const {
 
 3406    return iterator(data_->createIterator(resources_), resources_);
 
 3408  iterator 
end()
 const {
 
 3411  JsonArrayConst() : data_(0), resources_(0) {}
 
 3412  JsonArrayConst(
const detail::ArrayData* data,
 
 3413                 const detail::ResourceManager* resources)
 
 3414      : data_(data), resources_(resources) {}
 
 3415  template <
typename T>
 
 3416  detail::enable_if_t<detail::is_integral<T>::value, JsonVariantConst>
 
 3417  operator[](T index)
 const {
 
 3418    return JsonVariantConst(
 
 3419        detail::ArrayData::getElement(data_, 
size_t(index), resources_),
 
 3422  template <
typename TVariant>
 
 3423  detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
 
 3424  operator[](
const TVariant& variant)
 const {
 
 3425    if (variant.template is<size_t>())
 
 3426      return operator[](variant.template as<size_t>());
 
 3428      return JsonVariantConst();
 
 3430  operator JsonVariantConst()
 const {
 
 3431    return JsonVariantConst(getData(), resources_);
 
 3433  bool isNull()
 const {
 
 3436  operator bool()
 const {
 
 3439  size_t nesting()
 const {
 
 3440    return detail::VariantData::nesting(getData(), resources_);
 
 3442  size_t size()
 const {
 
 3443    return data_ ? data_->size(resources_) : 0;
 
 3445  ARDUINOJSON_DEPRECATED(
"always returns zero")
 
 3446  size_t memoryUsage()
 const {
 
 3450  const detail::VariantData* getData()
 const {
 
 3451    return collectionToVariant(data_);
 
 3453  const detail::ArrayData* data_;
 
 3454  const detail::ResourceManager* resources_;
 
 3456inline bool operator==(JsonArrayConst lhs, JsonArrayConst rhs) {
 
 3461  auto a = lhs.begin();
 
 3462  auto b = rhs.begin();
 
 3466    if (a == lhs.end() || b == rhs.end())
 
 3475class JsonArray : 
public detail::VariantOperators<JsonArray> {
 
 3476  friend class detail::VariantAttorney;
 
 3478  typedef JsonArrayIterator iterator;
 
 3479  JsonArray() : data_(0), resources_(0) {}
 
 3480  JsonArray(detail::ArrayData* data, detail::ResourceManager* resources)
 
 3481      : data_(data), resources_(resources) {}
 
 3482  operator JsonVariant() {
 
 3484    return JsonVariant(
reinterpret_cast<detail::VariantData*
>(data),
 
 3487  operator JsonArrayConst()
 const {
 
 3488    return JsonArrayConst(data_, resources_);
 
 3490  template <
typename T>
 
 3491  detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add()
 const {
 
 3492    return add<JsonVariant>().to<T>();
 
 3494  template <
typename T>
 
 3495  detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add()
 const {
 
 3496    return JsonVariant(detail::ArrayData::addElement(data_, resources_),
 
 3499  template <
typename T>
 
 3500  bool add(
const T& value)
 const {
 
 3501    return detail::ArrayData::addValue(data_, value, resources_);
 
 3503  template <
typename T>
 
 3504  bool add(T* value)
 const {
 
 3505    return detail::ArrayData::addValue(data_, value, resources_);
 
 3507  iterator 
begin()
 const {
 
 3510    return iterator(data_->createIterator(resources_), resources_);
 
 3512  iterator 
end()
 const {
 
 3515  bool set(JsonArrayConst src)
 const {
 
 3519    for (
auto element : src) {
 
 3525  void remove(iterator it)
 const {
 
 3526    detail::ArrayData::remove(data_, it.iterator_, resources_);
 
 3528  void remove(
size_t index)
 const {
 
 3529    detail::ArrayData::removeElement(data_, index, resources_);
 
 3531  template <
typename TVariant>
 
 3532  detail::enable_if_t<detail::IsVariant<TVariant>::value> 
remove(
 
 3533      TVariant variant)
 const {
 
 3534    if (variant.template is<size_t>())
 
 3535      remove(variant.template as<size_t>());
 
 3537  void clear()
 const {
 
 3538    detail::ArrayData::clear(data_, resources_);
 
 3540  template <
typename T>
 
 3541  detail::enable_if_t<detail::is_integral<T>::value,
 
 3542                      detail::ElementProxy<JsonArray>>
 
 3543  operator[](T index)
 const {
 
 3544    return {*
this, 
size_t(index)};
 
 3546  template <
typename TVariant>
 
 3547  detail::enable_if_t<detail::IsVariant<TVariant>::value,
 
 3548                      detail::ElementProxy<JsonArray>>
 
 3549  operator[](
const TVariant& variant)
 const {
 
 3550    if (variant.template is<size_t>())
 
 3551      return operator[](variant.template as<size_t>());
 
 3553      return {*
this, 
size_t(-1)};
 
 3555  operator JsonVariantConst()
 const {
 
 3556    return JsonVariantConst(collectionToVariant(data_), resources_);
 
 3558  bool isNull()
 const {
 
 3561  operator bool()
 const {
 
 3564  size_t nesting()
 const {
 
 3565    return detail::VariantData::nesting(collectionToVariant(data_), resources_);
 
 3567  size_t size()
 const {
 
 3568    return data_ ? data_->size(resources_) : 0;
 
 3570  ARDUINOJSON_DEPRECATED(
"use add<JsonVariant>() instead")
 
 3571  JsonVariant add()
 const {
 
 3572    return add<JsonVariant>();
 
 3574  ARDUINOJSON_DEPRECATED(
"use add<JsonArray>() instead")
 
 3575  JsonArray createNestedArray()
 const {
 
 3576    return add<JsonArray>();
 
 3578  ARDUINOJSON_DEPRECATED(
"use add<JsonObject>() instead")
 
 3579  JsonObject createNestedObject() const;
 
 3580  ARDUINOJSON_DEPRECATED(
"always returns zero")
 
 3581  size_t memoryUsage()
 const {
 
 3585  detail::ResourceManager* getResourceManager()
 const {
 
 3588  detail::VariantData* getData()
 const {
 
 3589    return collectionToVariant(data_);
 
 3591  detail::VariantData* getOrCreateData()
 const {
 
 3592    return collectionToVariant(data_);
 
 3594  detail::ArrayData* data_;
 
 3595  detail::ResourceManager* resources_;
 
 3599  JsonPair(detail::ObjectData::iterator iterator,
 
 3600           detail::ResourceManager* resources) {
 
 3601    if (!iterator.done()) {
 
 3602      key_ = iterator->asString();
 
 3603      iterator.next(resources);
 
 3604      value_ = JsonVariant(iterator.data(), resources);
 
 3607  JsonString key()
 const {
 
 3610  JsonVariant value() {
 
 3617class JsonPairConst {
 
 3619  JsonPairConst(detail::ObjectData::iterator iterator,
 
 3620                const detail::ResourceManager* resources) {
 
 3621    if (!iterator.done()) {
 
 3622      key_ = iterator->asString();
 
 3623      iterator.next(resources);
 
 3624      value_ = JsonVariantConst(iterator.data(), resources);
 
 3627  JsonString key()
 const {
 
 3630  JsonVariantConst value()
 const {
 
 3635  JsonVariantConst value_;
 
 3637class JsonObjectIterator {
 
 3640  JsonObjectIterator() {}
 
 3641  explicit JsonObjectIterator(detail::ObjectData::iterator iterator,
 
 3642                              detail::ResourceManager* resources)
 
 3643      : iterator_(iterator), resources_(resources) {}
 
 3645    return JsonPair(iterator_, resources_);
 
 3647  Ref<JsonPair> operator->() {
 
 3650  bool operator==(
const JsonObjectIterator& other)
 const {
 
 3651    return iterator_ == other.iterator_;
 
 3653  bool operator!=(
const JsonObjectIterator& other)
 const {
 
 3654    return iterator_ != other.iterator_;
 
 3656  JsonObjectIterator& operator++() {
 
 3657    iterator_.next(resources_);  
 
 3658    iterator_.next(resources_);  
 
 3662  detail::ObjectData::iterator iterator_;
 
 3663  detail::ResourceManager* resources_;
 
 3665class JsonObjectConstIterator {
 
 3668  JsonObjectConstIterator() {}
 
 3669  explicit JsonObjectConstIterator(detail::ObjectData::iterator iterator,
 
 3670                                   const detail::ResourceManager* resources)
 
 3671      : iterator_(iterator), resources_(resources) {}
 
 3673    return JsonPairConst(iterator_, resources_);
 
 3675  Ref<JsonPairConst> operator->() {
 
 3678  bool operator==(
const JsonObjectConstIterator& other)
 const {
 
 3679    return iterator_ == other.iterator_;
 
 3681  bool operator!=(
const JsonObjectConstIterator& other)
 const {
 
 3682    return iterator_ != other.iterator_;
 
 3684  JsonObjectConstIterator& operator++() {
 
 3685    iterator_.next(resources_);  
 
 3686    iterator_.next(resources_);  
 
 3690  detail::ObjectData::iterator iterator_;
 
 3691  const detail::ResourceManager* resources_;
 
 3693class JsonObjectConst : 
public detail::VariantOperators<JsonObjectConst> {
 
 3695  friend class detail::VariantAttorney;
 
 3697  typedef JsonObjectConstIterator iterator;
 
 3698  JsonObjectConst() : data_(0), resources_(0) {}
 
 3699  JsonObjectConst(
const detail::ObjectData* data,
 
 3700                  const detail::ResourceManager* resources)
 
 3701      : data_(data), resources_(resources) {}
 
 3702  operator JsonVariantConst()
 const {
 
 3703    return JsonVariantConst(getData(), resources_);
 
 3705  bool isNull()
 const {
 
 3708  operator bool()
 const {
 
 3711  size_t nesting()
 const {
 
 3712    return detail::VariantData::nesting(getData(), resources_);
 
 3714  size_t size()
 const {
 
 3715    return data_ ? data_->size(resources_) : 0;
 
 3717  iterator 
begin()
 const {
 
 3720    return iterator(data_->createIterator(resources_), resources_);
 
 3722  iterator 
end()
 const {
 
 3725  template <
typename TString>
 
 3726  ARDUINOJSON_DEPRECATED(
"use obj[key].is<T>() instead")
 
 3727  detail::enable_if_t<detail::IsString<TString>::value, 
bool> containsKey(
 
 3728      const TString& key)
 const {
 
 3729    return detail::ObjectData::getMember(data_, detail::adaptString(key),
 
 3732  template <
typename TChar>
 
 3733  ARDUINOJSON_DEPRECATED(
"use obj[\"key\"].is<T>() instead")
 
 3734  bool containsKey(TChar* key)
 const {
 
 3735    return detail::ObjectData::getMember(data_, detail::adaptString(key),
 
 3738  template <
typename TVariant>
 
 3739  ARDUINOJSON_DEPRECATED(
"use obj[key].is<T>() instead")
 
 3740  detail::enable_if_t<detail::IsVariant<TVariant>::value, 
bool> containsKey(
 
 3741      const TVariant& key)
 const {
 
 3742    return containsKey(key.template as<const char*>());
 
 3744  template <
typename TString>
 
 3745  detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
 
 3746  operator[](
const TString& key)
 const {
 
 3747    return JsonVariantConst(detail::ObjectData::getMember(
 
 3748                                data_, detail::adaptString(key), resources_),
 
 3751  template <
typename TChar>
 
 3752  detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
 
 3753  operator[](TChar* key)
 const {
 
 3754    return JsonVariantConst(detail::ObjectData::getMember(
 
 3755                                data_, detail::adaptString(key), resources_),
 
 3758  template <
typename TVariant>
 
 3759  detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
 
 3760  operator[](
const TVariant& key)
 const {
 
 3761    if (key.template is<const char*>())
 
 3762      return operator[](key.template as<const char*>());
 
 3764      return JsonVariantConst();
 
 3766  ARDUINOJSON_DEPRECATED(
"always returns zero")
 
 3767  size_t memoryUsage()
 const {
 
 3771  const detail::VariantData* getData()
 const {
 
 3772    return collectionToVariant(data_);
 
 3774  const detail::ObjectData* data_;
 
 3775  const detail::ResourceManager* resources_;
 
 3777inline bool operator==(JsonObjectConst lhs, JsonObjectConst rhs) {
 
 3783  for (
auto kvp : lhs) {
 
 3784    auto rhsValue = rhs[kvp.key()];
 
 3785    if (rhsValue.isUnbound())
 
 3787    if (kvp.value() != rhsValue)
 
 3791  return count == rhs.size();
 
 3793ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 3794ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 3795template <
typename TUpstream, 
typename TStringRef>
 
 3797    : 
public VariantRefBase<MemberProxy<TUpstream, TStringRef>>,
 
 3798      public VariantOperators<MemberProxy<TUpstream, TStringRef>> {
 
 3799  friend class VariantAttorney;
 
 3801  MemberProxy(TUpstream upstream, TStringRef key)
 
 3802      : upstream_(upstream), key_(key) {}
 
 3803  MemberProxy(
const MemberProxy& src)
 
 3804      : upstream_(src.upstream_), key_(src.key_) {}
 
 3805  MemberProxy& operator=(
const MemberProxy& src) {
 
 3809  template <
typename T>
 
 3810  MemberProxy& operator=(
const T& src) {
 
 3814  template <
typename T>
 
 3815  MemberProxy& operator=(T* src) {
 
 3820  ResourceManager* getResourceManager()
 const {
 
 3821    return VariantAttorney::getResourceManager(upstream_);
 
 3823  VariantData* getData()
 const {
 
 3824    return VariantData::getMember(
 
 3825        VariantAttorney::getData(upstream_), adaptString(key_),
 
 3826        VariantAttorney::getResourceManager(upstream_));
 
 3828  VariantData* getOrCreateData()
 const {
 
 3829    auto data = VariantAttorney::getOrCreateData(upstream_);
 
 3832    return data->getOrAddMember(adaptString(key_),
 
 3833                                VariantAttorney::getResourceManager(upstream_));
 
 3836  TUpstream upstream_;
 
 3839ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 3840ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 3842class JsonObject : 
public detail::VariantOperators<JsonObject> {
 
 3843  friend class detail::VariantAttorney;
 
 3845  typedef JsonObjectIterator iterator;
 
 3847  JsonObject(detail::ObjectData* data, detail::ResourceManager* resource)
 
 3848      : data_(data), resources_(resource) {}
 
 3849  operator JsonVariant()
 const {
 
 3851    return JsonVariant(
reinterpret_cast<detail::VariantData*
>(data),
 
 3854  operator JsonObjectConst()
 const {
 
 3855    return JsonObjectConst(data_, resources_);
 
 3857  operator JsonVariantConst()
 const {
 
 3858    return JsonVariantConst(collectionToVariant(data_), resources_);
 
 3860  bool isNull()
 const {
 
 3863  operator bool()
 const {
 
 3866  size_t nesting()
 const {
 
 3867    return detail::VariantData::nesting(collectionToVariant(data_), resources_);
 
 3869  size_t size()
 const {
 
 3870    return data_ ? data_->size(resources_) : 0;
 
 3872  iterator 
begin()
 const {
 
 3875    return iterator(data_->createIterator(resources_), resources_);
 
 3877  iterator 
end()
 const {
 
 3880  void clear()
 const {
 
 3881    detail::ObjectData::clear(data_, resources_);
 
 3883  bool set(JsonObjectConst src) {
 
 3884    if (!data_ || !src.data_)
 
 3887    for (
auto kvp : src) {
 
 3888      if (!
operator[](kvp.key()).set(kvp.value()))
 
 3893  template <
typename TString>
 
 3894  detail::enable_if_t<detail::IsString<TString>::value,
 
 3895                      detail::MemberProxy<JsonObject, TString>>
 
 3896  operator[](
const TString& key)
 const {
 
 3897    return {*
this, key};
 
 3899  template <
typename TChar>
 
 3900  detail::enable_if_t<detail::IsString<TChar*>::value,
 
 3901                      detail::MemberProxy<JsonObject, TChar*>>
 
 3902  operator[](TChar* key)
 const {
 
 3903    return {*
this, key};
 
 3905  template <
typename TVariant>
 
 3906  detail::enable_if_t<detail::IsVariant<TVariant>::value,
 
 3907                      detail::MemberProxy<JsonObject, const char*>>
 
 3908  operator[](
const TVariant& key)
 const {
 
 3909    if (key.template is<const char*>())
 
 3910      return {*
this, key.template as<const char*>()};
 
 3912      return {*
this, 
nullptr};
 
 3914  FORCE_INLINE 
void remove(iterator it)
 const {
 
 3915    detail::ObjectData::remove(data_, it.iterator_, resources_);
 
 3917  template <
typename TString>
 
 3918  detail::enable_if_t<detail::IsString<TString>::value> 
remove(
 
 3919      const TString& key)
 const {
 
 3920    detail::ObjectData::removeMember(data_, detail::adaptString(key),
 
 3923  template <
typename TVariant>
 
 3924  detail::enable_if_t<detail::IsVariant<TVariant>::value> 
remove(
 
 3925      const TVariant& key)
 const {
 
 3926    if (key.template is<const char*>())
 
 3927      remove(key.template as<const char*>());
 
 3929  template <
typename TChar>
 
 3930  FORCE_INLINE 
void remove(TChar* key)
 const {
 
 3931    detail::ObjectData::removeMember(data_, detail::adaptString(key),
 
 3934  template <
typename TString>
 
 3935  ARDUINOJSON_DEPRECATED(
"use obj[key].is<T>() instead")
 
 3936  detail::enable_if_t<detail::IsString<TString>::value, 
bool> containsKey(
 
 3937      const TString& key)
 const {
 
 3938    return detail::ObjectData::getMember(data_, detail::adaptString(key),
 
 3941  template <
typename TChar>
 
 3942  ARDUINOJSON_DEPRECATED(
"use obj[\"key\"].is<T>() instead")
 
 3943  detail::enable_if_t<detail::IsString<TChar*>::value, 
bool> containsKey(
 
 3945    return detail::ObjectData::getMember(data_, detail::adaptString(key),
 
 3948  template <
typename TVariant>
 
 3949  ARDUINOJSON_DEPRECATED(
"use obj[key].is<T>() instead")
 
 3950  detail::enable_if_t<detail::IsVariant<TVariant>::value, 
bool> containsKey(
 
 3951      const TVariant& key)
 const {
 
 3952    return containsKey(key.template as<const char*>());
 
 3954  template <
typename TChar>
 
 3955  ARDUINOJSON_DEPRECATED(
"use obj[key].to<JsonArray>() instead")
 
 3956  JsonArray createNestedArray(TChar* key)
 const {
 
 3957    return operator[](key).template to<JsonArray>();
 
 3959  template <
typename TString>
 
 3960  ARDUINOJSON_DEPRECATED(
"use obj[key].to<JsonArray>() instead")
 
 3961  JsonArray createNestedArray(const TString& key)
 const {
 
 3962    return operator[](key).template to<JsonArray>();
 
 3964  template <
typename TChar>
 
 3965  ARDUINOJSON_DEPRECATED(
"use obj[key].to<JsonObject>() instead")
 
 3966  JsonObject createNestedObject(TChar* key) {
 
 3967    return operator[](key).template to<JsonObject>();
 
 3969  template <
typename TString>
 
 3970  ARDUINOJSON_DEPRECATED(
"use obj[key].to<JsonObject>() instead")
 
 3971  JsonObject createNestedObject(const TString& key) {
 
 3972    return operator[](key).template to<JsonObject>();
 
 3974  ARDUINOJSON_DEPRECATED(
"always returns zero")
 
 3975  size_t memoryUsage()
 const {
 
 3979  detail::ResourceManager* getResourceManager()
 const {
 
 3982  detail::VariantData* getData()
 const {
 
 3983    return detail::collectionToVariant(data_);
 
 3985  detail::VariantData* getOrCreateData()
 const {
 
 3986    return detail::collectionToVariant(data_);
 
 3988  detail::ObjectData* data_;
 
 3989  detail::ResourceManager* resources_;
 
 3991class JsonDocument : 
public detail::VariantOperators<const JsonDocument&> {
 
 3992  friend class detail::VariantAttorney;
 
 3994  explicit JsonDocument(Allocator* alloc = detail::DefaultAllocator::instance())
 
 3995      : resources_(alloc) {}
 
 3996  JsonDocument(
const JsonDocument& src) : JsonDocument(src.allocator()) {
 
 3999  JsonDocument(JsonDocument&& src)
 
 4000      : JsonDocument(detail::DefaultAllocator::instance()) {
 
 4003  template <
typename T>
 
 4005      const T& src, Allocator* alloc = detail::DefaultAllocator::instance(),
 
 4006      detail::enable_if_t<detail::IsVariant<T>::value ||
 
 4007                          detail::is_same<T, JsonArray>::value ||
 
 4008                          detail::is_same<T, JsonArrayConst>::value ||
 
 4009                          detail::is_same<T, JsonObject>::value ||
 
 4010                          detail::is_same<T, JsonObjectConst>::value>* = 0)
 
 4011      : JsonDocument(alloc) {
 
 4014  JsonDocument& operator=(JsonDocument src) {
 
 4018  template <
typename T>
 
 4019  JsonDocument& operator=(
const T& src) {
 
 4023  Allocator* allocator()
 const {
 
 4024    return resources_.allocator();
 
 4026  void shrinkToFit() {
 
 4027    resources_.shrinkToFit();
 
 4029  template <
typename T>
 
 4031    return getVariant().template as<T>();
 
 4033  template <
typename T>
 
 4035    return getVariant().template as<T>();
 
 4041  template <
typename T>
 
 4043    return getVariant().template is<T>();
 
 4045  template <
typename T>
 
 4047    return getVariant().template is<T>();
 
 4049  bool isNull()
 const {
 
 4050    return getVariant().isNull();
 
 4052  bool overflowed()
 const {
 
 4053    return resources_.overflowed();
 
 4055  size_t nesting()
 const {
 
 4056    return data_.nesting(&resources_);
 
 4058  size_t size()
 const {
 
 4059    return data_.size(&resources_);
 
 4061  bool set(
const JsonDocument& src) {
 
 4062    return to<JsonVariant>().set(src.as<JsonVariantConst>());
 
 4064  template <
typename T>
 
 4065  detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, 
bool> set(
 
 4067    return to<JsonVariant>().set(src);
 
 4069  template <
typename T>
 
 4070  typename detail::VariantTo<T>::type to() {
 
 4072    return getVariant().template to<T>();
 
 4074  template <
typename TChar>
 
 4075  ARDUINOJSON_DEPRECATED(
"use doc[\"key\"].is<T>() instead")
 
 4076  bool containsKey(TChar* key)
 const {
 
 4077    return data_.getMember(detail::adaptString(key), &resources_) != 0;
 
 4079  template <
typename TString>
 
 4080  ARDUINOJSON_DEPRECATED(
"use doc[key].is<T>() instead")
 
 4081  detail::enable_if_t<detail::IsString<TString>::value, 
bool> containsKey(
 
 4082      const TString& key)
 const {
 
 4083    return data_.getMember(detail::adaptString(key), &resources_) != 0;
 
 4085  template <
typename TVariant>
 
 4086  ARDUINOJSON_DEPRECATED(
"use doc[key].is<T>() instead")
 
 4087  detail::enable_if_t<detail::IsVariant<TVariant>::value, 
bool> containsKey(
 
 4088      const TVariant& key)
 const {
 
 4089    return containsKey(key.template as<const char*>());
 
 4091  template <
typename TString>
 
 4092  detail::enable_if_t<detail::IsString<TString>::value,
 
 4093                      detail::MemberProxy<JsonDocument&, TString>>
 
 4094  operator[](
const TString& key) {
 
 4095    return {*
this, key};
 
 4097  template <
typename TChar>
 
 4098  detail::enable_if_t<detail::IsString<TChar*>::value,
 
 4099                      detail::MemberProxy<JsonDocument&, TChar*>>
 
 4100  operator[](TChar* key) {
 
 4101    return {*
this, key};
 
 4103  template <
typename TString>
 
 4104  detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
 
 4105  operator[](
const TString& key)
 const {
 
 4106    return JsonVariantConst(
 
 4107        data_.getMember(detail::adaptString(key), &resources_), &resources_);
 
 4109  template <
typename TChar>
 
 4110  detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
 
 4111  operator[](TChar* key)
 const {
 
 4112    return JsonVariantConst(
 
 4113        data_.getMember(detail::adaptString(key), &resources_), &resources_);
 
 4115  template <
typename T>
 
 4116  detail::enable_if_t<detail::is_integral<T>::value,
 
 4117                      detail::ElementProxy<JsonDocument&>>
 
 4118  operator[](T index) {
 
 4119    return {*
this, 
size_t(index)};
 
 4121  JsonVariantConst operator[](
size_t index)
 const {
 
 4122    return JsonVariantConst(data_.getElement(index, &resources_), &resources_);
 
 4124  template <
typename TVariant>
 
 4125  detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
 
 4126  operator[](
const TVariant& key)
 const {
 
 4127    if (key.template is<const char*>())
 
 4128      return operator[](key.template as<const char*>());
 
 4129    if (key.template is<size_t>())
 
 4130      return operator[](key.template as<size_t>());
 
 4133  template <
typename T>
 
 4134  detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() {
 
 4135    return add<JsonVariant>().to<T>();
 
 4137  template <
typename T>
 
 4138  detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() {
 
 4139    return JsonVariant(data_.addElement(&resources_), &resources_);
 
 4141  template <
typename TValue>
 
 4142  bool add(
const TValue& value) {
 
 4143    return data_.addValue(value, &resources_);
 
 4145  template <
typename TChar>
 
 4146  bool add(TChar* value) {
 
 4147    return data_.addValue(value, &resources_);
 
 4149  template <
typename T>
 
 4150  detail::enable_if_t<detail::is_integral<T>::value> 
remove(T index) {
 
 4151    detail::VariantData::removeElement(getData(), 
size_t(index),
 
 4152                                       getResourceManager());
 
 4154  template <
typename TChar>
 
 4155  detail::enable_if_t<detail::IsString<TChar*>::value> 
remove(TChar* key) {
 
 4156    detail::VariantData::removeMember(getData(), detail::adaptString(key),
 
 4157                                      getResourceManager());
 
 4159  template <
typename TString>
 
 4160  detail::enable_if_t<detail::IsString<TString>::value> 
remove(
 
 4161      const TString& key) {
 
 4162    detail::VariantData::removeMember(getData(), detail::adaptString(key),
 
 4163                                      getResourceManager());
 
 4165  template <
typename TVariant>
 
 4166  detail::enable_if_t<detail::IsVariant<TVariant>::value> 
remove(
 
 4167      const TVariant& key) {
 
 4168    if (key.template is<const char*>())
 
 4169      remove(key.template as<const char*>());
 
 4170    if (key.template is<size_t>())
 
 4171      remove(key.template as<size_t>());
 
 4173  operator JsonVariant() {
 
 4174    return getVariant();
 
 4176  operator JsonVariantConst()
 const {
 
 4177    return getVariant();
 
 4179  friend void swap(JsonDocument& a, JsonDocument& b) {
 
 4180    swap(a.resources_, b.resources_);
 
 4181    swap_(a.data_, b.data_);
 
 4183  ARDUINOJSON_DEPRECATED(
"use add<JsonVariant>() instead")
 
 4185    return add<JsonVariant>();
 
 4187  ARDUINOJSON_DEPRECATED(
"use add<JsonArray>() instead")
 
 4188  JsonArray createNestedArray() {
 
 4189    return add<JsonArray>();
 
 4191  template <
typename TChar>
 
 4192  ARDUINOJSON_DEPRECATED(
"use doc[key].to<JsonArray>() instead")
 
 4193  JsonArray createNestedArray(TChar* key) {
 
 4194    return operator[](key).template to<JsonArray>();
 
 4196  template <
typename TString>
 
 4197  ARDUINOJSON_DEPRECATED(
"use doc[key].to<JsonArray>() instead")
 
 4198  JsonArray createNestedArray(const TString& key) {
 
 4199    return operator[](key).template to<JsonArray>();
 
 4201  ARDUINOJSON_DEPRECATED(
"use add<JsonObject>() instead")
 
 4202  JsonObject createNestedObject() {
 
 4203    return add<JsonObject>();
 
 4205  template <
typename TChar>
 
 4206  ARDUINOJSON_DEPRECATED(
"use doc[key].to<JsonObject>() instead")
 
 4207  JsonObject createNestedObject(TChar* key) {
 
 4208    return operator[](key).template to<JsonObject>();
 
 4210  template <
typename TString>
 
 4211  ARDUINOJSON_DEPRECATED(
"use doc[key].to<JsonObject>() instead")
 
 4212  JsonObject createNestedObject(const TString& key) {
 
 4213    return operator[](key).template to<JsonObject>();
 
 4215  ARDUINOJSON_DEPRECATED(
"always returns zero")
 
 4216  size_t memoryUsage()
 const {
 
 4220  JsonVariant getVariant() {
 
 4221    return JsonVariant(&data_, &resources_);
 
 4223  JsonVariantConst getVariant()
 const {
 
 4224    return JsonVariantConst(&data_, &resources_);
 
 4226  detail::ResourceManager* getResourceManager() {
 
 4229  detail::VariantData* getData() {
 
 4232  const detail::VariantData* getData()
 const {
 
 4235  detail::VariantData* getOrCreateData() {
 
 4238  detail::ResourceManager resources_;
 
 4239  detail::VariantData data_;
 
 4241inline void convertToJson(
const JsonDocument& src, JsonVariant dst) {
 
 4242  dst.set(src.as<JsonVariantConst>());
 
 4244ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 4245ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 4246template <
typename TResult>
 
 4247struct VariantDataVisitor {
 
 4248  typedef TResult result_type;
 
 4249  template <
typename T>
 
 4250  TResult visit(
const T&) {
 
 4254template <
typename TResult>
 
 4255struct JsonVariantVisitor {
 
 4256  typedef TResult result_type;
 
 4257  template <
typename T>
 
 4258  TResult visit(
const T&) {
 
 4262template <
typename TVisitor>
 
 4263class VisitorAdapter {
 
 4265  using result_type = 
typename TVisitor::result_type;
 
 4266  VisitorAdapter(TVisitor& visitor, 
const ResourceManager* resources)
 
 4267      : visitor_(&visitor), resources_(resources) {}
 
 4268  result_type visit(
const ArrayData& value) {
 
 4269    return visitor_->visit(JsonArrayConst(&value, resources_));
 
 4271  result_type visit(
const ObjectData& value) {
 
 4272    return visitor_->visit(JsonObjectConst(&value, resources_));
 
 4274  template <
typename T>
 
 4275  result_type visit(
const T& value) {
 
 4276    return visitor_->visit(value);
 
 4280  const ResourceManager* resources_;
 
 4282template <
typename TVisitor>
 
 4283typename TVisitor::result_type accept(JsonVariantConst variant,
 
 4285  auto data = VariantAttorney::getData(variant);
 
 4287    return visit.visit(
nullptr);
 
 4288  auto resources = VariantAttorney::getResourceManager(variant);
 
 4289  VisitorAdapter<TVisitor> adapter(visit, resources);
 
 4290  return data->accept(adapter, resources);
 
 4292struct ComparerBase : JsonVariantVisitor<CompareResult> {};
 
 4293template <
typename T, 
typename Enable = 
void>
 
 4295template <
typename T>
 
 4296struct Comparer<T, 
enable_if_t<IsString<T>::value>> : ComparerBase {
 
 4298  explicit Comparer(T value) : rhs(value) {}
 
 4299  CompareResult visit(JsonString lhs) {
 
 4300    int i = stringCompare(adaptString(rhs), adaptString(lhs));
 
 4302      return COMPARE_RESULT_GREATER;
 
 4304      return COMPARE_RESULT_LESS;
 
 4306      return COMPARE_RESULT_EQUAL;
 
 4308  CompareResult visit(nullptr_t) {
 
 4309    if (adaptString(rhs).isNull())
 
 4310      return COMPARE_RESULT_EQUAL;
 
 4312      return COMPARE_RESULT_DIFFER;
 
 4314  using ComparerBase::visit;
 
 4316template <
typename T>
 
 4318    T, 
enable_if_t<is_integral<T>::value || is_floating_point<T>::value>>
 
 4321  explicit Comparer(T value) : rhs(value) {}
 
 4322  template <
typename U>
 
 4323  enable_if_t<is_floating_point<U>::value || is_integral<U>::value,
 
 4325  visit(
const U& lhs) {
 
 4326    return arithmeticCompare(lhs, rhs);
 
 4328  template <
typename U>
 
 4329  enable_if_t<!is_floating_point<U>::value && !is_integral<U>::value,
 
 4331  visit(
const U& lhs) {
 
 4332    return ComparerBase::visit(lhs);
 
 4335struct NullComparer : ComparerBase {
 
 4336  CompareResult visit(nullptr_t) {
 
 4337    return COMPARE_RESULT_EQUAL;
 
 4339  using ComparerBase::visit;
 
 4342struct Comparer<
nullptr_t, void> : NullComparer {
 
 4343  explicit Comparer(nullptr_t) : NullComparer() {}
 
 4345struct ArrayComparer : ComparerBase {
 
 4346  JsonArrayConst rhs_;
 
 4347  explicit ArrayComparer(JsonArrayConst rhs) : rhs_(rhs) {}
 
 4348  CompareResult visit(JsonArrayConst lhs) {
 
 4350      return COMPARE_RESULT_EQUAL;
 
 4352      return COMPARE_RESULT_DIFFER;
 
 4354  using ComparerBase::visit;
 
 4356struct ObjectComparer : ComparerBase {
 
 4357  JsonObjectConst rhs_;
 
 4358  explicit ObjectComparer(JsonObjectConst rhs) : rhs_(rhs) {}
 
 4359  CompareResult visit(JsonObjectConst lhs) {
 
 4361      return COMPARE_RESULT_EQUAL;
 
 4363      return COMPARE_RESULT_DIFFER;
 
 4365  using ComparerBase::visit;
 
 4367struct RawComparer : ComparerBase {
 
 4369  explicit RawComparer(RawString rhs) : rhs_(rhs) {}
 
 4370  CompareResult visit(RawString lhs) {
 
 4371    size_t size = rhs_.size() < lhs.size() ? rhs_.size() : lhs.size();
 
 4372    int n = memcmp(lhs.data(), rhs_.data(), size);
 
 4374      return COMPARE_RESULT_LESS;
 
 4376      return COMPARE_RESULT_GREATER;
 
 4378      return COMPARE_RESULT_EQUAL;
 
 4380  using ComparerBase::visit;
 
 4382struct VariantComparer : ComparerBase {
 
 4383  JsonVariantConst rhs;
 
 4384  explicit VariantComparer(JsonVariantConst value) : rhs(value) {}
 
 4385  CompareResult visit(JsonArrayConst lhs) {
 
 4386    ArrayComparer comparer(lhs);
 
 4387    return reverseResult(comparer);
 
 4389  CompareResult visit(JsonObjectConst lhs) {
 
 4390    ObjectComparer comparer(lhs);
 
 4391    return reverseResult(comparer);
 
 4393  CompareResult visit(JsonFloat lhs) {
 
 4394    Comparer<JsonFloat> comparer(lhs);
 
 4395    return reverseResult(comparer);
 
 4397  CompareResult visit(JsonString lhs) {
 
 4398    Comparer<JsonString> comparer(lhs);
 
 4399    return reverseResult(comparer);
 
 4401  CompareResult visit(RawString value) {
 
 4402    RawComparer comparer(value);
 
 4403    return reverseResult(comparer);
 
 4405  CompareResult visit(JsonInteger lhs) {
 
 4406    Comparer<JsonInteger> comparer(lhs);
 
 4407    return reverseResult(comparer);
 
 4409  CompareResult visit(JsonUInt lhs) {
 
 4410    Comparer<JsonUInt> comparer(lhs);
 
 4411    return reverseResult(comparer);
 
 4413  CompareResult visit(
bool lhs) {
 
 4414    Comparer<bool> comparer(lhs);
 
 4415    return reverseResult(comparer);
 
 4417  CompareResult visit(nullptr_t) {
 
 4418    NullComparer comparer;
 
 4419    return reverseResult(comparer);
 
 4422  template <
typename TComparer>
 
 4423  CompareResult reverseResult(TComparer& comparer) {
 
 4424    CompareResult reversedResult = accept(rhs, comparer);
 
 4425    switch (reversedResult) {
 
 4426      case COMPARE_RESULT_GREATER:
 
 4427        return COMPARE_RESULT_LESS;
 
 4428      case COMPARE_RESULT_LESS:
 
 4429        return COMPARE_RESULT_GREATER;
 
 4431        return reversedResult;
 
 4435template <
typename T>
 
 4437    T, 
enable_if_t<is_convertible<T, FLArduinoJson::JsonVariantConst>::value>>
 
 4439  explicit Comparer(
const T& value)
 
 4440      : VariantComparer(static_cast<JsonVariantConst>(value)) {}
 
 4442template <
typename T>
 
 4443CompareResult compare(FLArduinoJson::JsonVariantConst lhs, 
const T& rhs) {
 
 4444  Comparer<T> comparer(rhs);
 
 4445  return accept(lhs, comparer);
 
 4447inline ArrayData::iterator ArrayData::at(
 
 4448    size_t index, 
const ResourceManager* resources)
 const {
 
 4449  auto it = createIterator(resources);
 
 4450  while (!it.done() && index) {
 
 4456inline VariantData* ArrayData::addElement(ResourceManager* resources) {
 
 4457  auto slot = resources->allocVariant();
 
 4460  CollectionData::appendOne(slot, resources);
 
 4463inline VariantData* ArrayData::getOrAddElement(
size_t index,
 
 4464                                               ResourceManager* resources) {
 
 4465  auto it = createIterator(resources);
 
 4466  while (!it.done() && index > 0) {
 
 4472  VariantData* element = it.data();
 
 4474    element = addElement(resources);
 
 4481inline VariantData* ArrayData::getElement(
 
 4482    size_t index, 
const ResourceManager* resources)
 const {
 
 4483  return at(index, resources).data();
 
 4485inline void ArrayData::removeElement(
size_t index, ResourceManager* resources) {
 
 4486  remove(at(index, resources), resources);
 
 4488template <
typename T>
 
 4489inline bool ArrayData::addValue(T&& value, ResourceManager* resources) {
 
 4490  ARDUINOJSON_ASSERT(resources != 
nullptr);
 
 4491  auto slot = resources->allocVariant();
 
 4494  JsonVariant variant(slot.ptr(), resources);
 
 4495  if (!variant.set(detail::forward<T>(value))) {
 
 4496    resources->freeVariant(slot);
 
 4499  CollectionData::appendOne(slot, resources);
 
 4502constexpr size_t sizeofArray(
size_t n) {
 
 4503  return n * ResourceManager::slotSize;
 
 4505ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 4506ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 4507template <
typename T>
 
 4508inline detail::enable_if_t<!detail::is_array<T>::value, 
bool> copyArray(
 
 4509    const T& src, JsonVariant dst) {
 
 4510  return dst.set(src);
 
 4512template <
typename T, 
size_t N, 
typename TDestination>
 
 4513inline detail::enable_if_t<
 
 4514    !detail::is_base_of<JsonDocument, TDestination>::value, 
bool>
 
 4515copyArray(T (&src)[N], 
const TDestination& dst) {
 
 4516  return copyArray(src, N, dst);
 
 4518template <
typename T, 
typename TDestination>
 
 4519inline detail::enable_if_t<
 
 4520    !detail::is_base_of<JsonDocument, TDestination>::value, 
bool>
 
 4521copyArray(
const T* src, 
size_t len, 
const TDestination& dst) {
 
 4523  for (
size_t i = 0; i < len; i++) {
 
 4524    ok &= copyArray(src[i], dst.template add<JsonVariant>());
 
 4528template <
typename TDestination>
 
 4529inline bool copyArray(
const char* src, 
size_t, 
const TDestination& dst) {
 
 4530  return dst.set(src);
 
 4532template <
typename T>
 
 4533inline bool copyArray(
const T& src, JsonDocument& dst) {
 
 4534  return copyArray(src, dst.to<JsonArray>());
 
 4536template <
typename T>
 
 4537inline bool copyArray(
const T* src, 
size_t len, JsonDocument& dst) {
 
 4538  return copyArray(src, len, dst.to<JsonArray>());
 
 4540template <
typename T>
 
 4541inline detail::enable_if_t<!detail::is_array<T>::value, 
size_t> copyArray(
 
 4542    JsonVariantConst src, T& dst) {
 
 4546template <
typename T, 
size_t N>
 
 4547inline size_t copyArray(JsonArrayConst src, T (&dst)[N]) {
 
 4548  return copyArray(src, dst, N);
 
 4550template <
typename T>
 
 4551inline size_t copyArray(JsonArrayConst src, T* dst, 
size_t len) {
 
 4553  for (JsonArrayConst::iterator it = src.begin(); it != src.end() && i < len;
 
 4555    copyArray(*it, dst[i++]);
 
 4559inline size_t copyArray(JsonVariantConst src, 
char (&dst)[N]) {
 
 4564  memcpy(dst, s.c_str(), len);
 
 4568template <
typename TSource, 
typename T>
 
 4569inline detail::enable_if_t<detail::is_array<T>::value &&
 
 4570                               detail::is_base_of<JsonDocument, TSource>::value,
 
 4572copyArray(
const TSource& src, T& dst) {
 
 4573  return copyArray(src.template as<JsonArrayConst>(), dst);
 
 4575ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 4576ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 4577#if ARDUINOJSON_ENABLE_ALIGNMENT 
 4578inline bool isAligned(
size_t value) {
 
 4579  const size_t mask = 
sizeof(
void*) - 1;
 
 4580  size_t addr = value;
 
 4581  return (addr & mask) == 0;
 
 4583inline size_t addPadding(
size_t bytes) {
 
 4584  const size_t mask = 
sizeof(
void*) - 1;
 
 4585  return (bytes + mask) & ~mask;
 
 4587template <
size_t bytes>
 
 4589  static const size_t mask = 
sizeof(
void*) - 1;
 
 4590  static const size_t value = (bytes + mask) & ~mask;
 
 4593inline bool isAligned(
size_t) {
 
 4596inline size_t addPadding(
size_t bytes) {
 
 4599template <
size_t bytes>
 
 4601  static const size_t value = bytes;
 
 4604template <
typename T>
 
 4605inline bool isAligned(T* ptr) {
 
 4606  return isAligned(
reinterpret_cast<size_t>(ptr));
 
 4608template <
typename T>
 
 4609inline T* addPadding(T* p) {
 
 4610  size_t address = addPadding(
reinterpret_cast<size_t>(p));
 
 4611  return reinterpret_cast<T*
>(address);
 
 4613inline CollectionIterator::CollectionIterator(VariantData* slot, SlotId slotId)
 
 4614    : slot_(slot), currentId_(slotId) {
 
 4615  nextId_ = slot_ ? slot_->next() : NULL_SLOT;
 
 4617inline void CollectionIterator::next(
const ResourceManager* resources) {
 
 4618  ARDUINOJSON_ASSERT(currentId_ != NULL_SLOT);
 
 4619  slot_ = resources->getVariant(nextId_);
 
 4620  currentId_ = nextId_;
 
 4622    nextId_ = slot_->next();
 
 4624inline CollectionData::iterator CollectionData::createIterator(
 
 4625    const ResourceManager* resources)
 const {
 
 4626  return iterator(resources->getVariant(head_), head_);
 
 4628inline void CollectionData::appendOne(Slot<VariantData> slot,
 
 4629                                      const ResourceManager* resources) {
 
 4630  if (tail_ != NULL_SLOT) {
 
 4631    auto tail = resources->getVariant(tail_);
 
 4632    tail->setNext(slot.id());
 
 4639inline void CollectionData::appendPair(Slot<VariantData> key,
 
 4640                                       Slot<VariantData> value,
 
 4641                                       const ResourceManager* resources) {
 
 4642  key->setNext(value.id());
 
 4643  if (tail_ != NULL_SLOT) {
 
 4644    auto tail = resources->getVariant(tail_);
 
 4645    tail->setNext(key.id());
 
 4652inline void CollectionData::clear(ResourceManager* resources) {
 
 4654  while (next != NULL_SLOT) {
 
 4656    auto slot = resources->getVariant(next);
 
 4657    next = slot->next();
 
 4658    resources->freeVariant({slot, currId});
 
 4663inline Slot<VariantData> CollectionData::getPreviousSlot(
 
 4664    VariantData* target, 
const ResourceManager* resources)
 const {
 
 4665  auto prev = Slot<VariantData>();
 
 4666  auto currentId = head_;
 
 4667  while (currentId != NULL_SLOT) {
 
 4668    auto currentSlot = resources->getVariant(currentId);
 
 4669    if (currentSlot == target)
 
 4671    prev = Slot<VariantData>(currentSlot, currentId);
 
 4672    currentId = currentSlot->next();
 
 4676inline void CollectionData::removeOne(iterator it, ResourceManager* resources) {
 
 4679  auto curr = it.slot_;
 
 4680  auto prev = getPreviousSlot(curr, resources);
 
 4681  auto next = curr->next();
 
 4683    prev->setNext(next);
 
 4686  if (next == NULL_SLOT)
 
 4688  resources->freeVariant({it.slot_, it.currentId_});
 
 4690inline void CollectionData::removePair(ObjectData::iterator it,
 
 4691                                       ResourceManager* resources) {
 
 4694  auto keySlot = it.slot_;
 
 4695  auto valueId = it.nextId_;
 
 4696  auto valueSlot = resources->getVariant(valueId);
 
 4697  keySlot->setNext(valueSlot->next());
 
 4698  resources->freeVariant({valueSlot, valueId});
 
 4699  removeOne(it, resources);
 
 4701inline size_t CollectionData::nesting(
const ResourceManager* resources)
 const {
 
 4702  size_t maxChildNesting = 0;
 
 4703  for (
auto it = createIterator(resources); !it.done(); it.next(resources)) {
 
 4704    size_t childNesting = it->nesting(resources);
 
 4705    if (childNesting > maxChildNesting)
 
 4706      maxChildNesting = childNesting;
 
 4708  return maxChildNesting + 1;
 
 4710inline size_t CollectionData::size(
const ResourceManager* resources)
 const {
 
 4712  for (
auto it = createIterator(resources); !it.done(); it.next(resources))
 
 4716inline Slot<VariantData> ResourceManager::allocVariant() {
 
 4717  auto p = variantPools_.allocSlot(allocator_);
 
 4722  return {
new (&p->variant) VariantData, p.id()};
 
 4724inline void ResourceManager::freeVariant(Slot<VariantData> variant) {
 
 4725  variant->clear(
this);
 
 4726  variantPools_.freeSlot({alias_cast<SlotData*>(variant.ptr()), variant.id()});
 
 4728inline VariantData* ResourceManager::getVariant(SlotId 
id)
 const {
 
 4729  return reinterpret_cast<VariantData*
>(variantPools_.getSlot(
id));
 
 4731#if ARDUINOJSON_USE_EXTENSIONS 
 4732inline Slot<VariantExtension> ResourceManager::allocExtension() {
 
 4733  auto p = variantPools_.allocSlot(allocator_);
 
 4738  return {&p->extension, p.id()};
 
 4740inline void ResourceManager::freeExtension(SlotId 
id) {
 
 4741  auto p = getExtension(
id);
 
 4742  variantPools_.freeSlot({
reinterpret_cast<SlotData*
>(p), 
id});
 
 4744inline VariantExtension* ResourceManager::getExtension(SlotId 
id)
 const {
 
 4745  return &variantPools_.getSlot(
id)->extension;
 
 4748template <
typename TAdaptedString>
 
 4749inline VariantData* ObjectData::getMember(
 
 4750    TAdaptedString key, 
const ResourceManager* resources)
 const {
 
 4751  auto it = findKey(key, resources);
 
 4757template <
typename TAdaptedString>
 
 4758VariantData* ObjectData::getOrAddMember(TAdaptedString key,
 
 4759                                        ResourceManager* resources) {
 
 4760  auto data = getMember(key, resources);
 
 4763  return addMember(key, resources);
 
 4765template <
typename TAdaptedString>
 
 4766inline ObjectData::iterator ObjectData::findKey(
 
 4767    TAdaptedString key, 
const ResourceManager* resources)
 const {
 
 4771  for (
auto it = createIterator(resources); !it.done(); it.next(resources)) {
 
 4772    if (isKey && stringEquals(key, adaptString(it->asString())))
 
 4778template <
typename TAdaptedString>
 
 4779inline void ObjectData::removeMember(TAdaptedString key,
 
 4780                                     ResourceManager* resources) {
 
 4781  remove(findKey(key, resources), resources);
 
 4783template <
typename TAdaptedString>
 
 4784inline VariantData* ObjectData::addMember(TAdaptedString key,
 
 4785                                          ResourceManager* resources) {
 
 4786  auto keySlot = resources->allocVariant();
 
 4789  auto valueSlot = resources->allocVariant();
 
 4792  if (!keySlot->setString(key, resources))
 
 4794  CollectionData::appendPair(keySlot, valueSlot, resources);
 
 4795  return valueSlot.ptr();
 
 4797constexpr size_t sizeofObject(
size_t n) {
 
 4798  return 2 * n * ResourceManager::slotSize;
 
 4800class EscapeSequence {
 
 4802  static char escapeChar(
char c) {
 
 4803    const char* p = escapeTable(
true);
 
 4804    while (p[0] && p[1] != c) {
 
 4809  static char unescapeChar(
char c) {
 
 4810    const char* p = escapeTable(
false);
 
 4820  static const char* escapeTable(
bool isSerializing) {
 
 4821    return &
"//''\"\"\\\\b\bf\fn\nr\rt\t"[isSerializing ? 4 : 0];
 
 4828  int8_t decimalPlaces;
 
 4830template <
typename TFloat>
 
 4831inline int16_t normalize(TFloat& value) {
 
 4832  typedef FloatTraits<TFloat> traits;
 
 4833  int16_t powersOf10 = 0;
 
 4834  int8_t index = 
sizeof(TFloat) == 8 ? 8 : 5;
 
 4835  int bit = 1 << index;
 
 4836  if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
 
 4837    for (; index >= 0; index--) {
 
 4838      if (value >= traits::positiveBinaryPowersOfTen()[index]) {
 
 4839        value *= traits::negativeBinaryPowersOfTen()[index];
 
 4840        powersOf10 = int16_t(powersOf10 + bit);
 
 4845  if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
 
 4846    for (; index >= 0; index--) {
 
 4847      if (value < traits::negativeBinaryPowersOfTen()[index] * 10) {
 
 4848        value *= traits::positiveBinaryPowersOfTen()[index];
 
 4849        powersOf10 = int16_t(powersOf10 - bit);
 
 4856constexpr uint32_t pow10(
int exponent) {
 
 4857  return (exponent == 0) ? 1 : 10 * pow10(exponent - 1);
 
 4859inline FloatParts decomposeFloat(JsonFloat value, int8_t decimalPlaces) {
 
 4860  uint32_t maxDecimalPart = pow10(decimalPlaces);
 
 4861  int16_t exponent = normalize(value);
 
 4862  uint32_t integral = uint32_t(value);
 
 4863  for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) {
 
 4864    maxDecimalPart /= 10;
 
 4867  JsonFloat remainder =
 
 4868      (value - JsonFloat(integral)) * JsonFloat(maxDecimalPart);
 
 4869  uint32_t decimal = uint32_t(remainder);
 
 4870  remainder = remainder - JsonFloat(decimal);
 
 4871  decimal += uint32_t(remainder * 2);
 
 4872  if (decimal >= maxDecimalPart) {
 
 4875    if (exponent && integral >= 10) {
 
 4880  while (decimal % 10 == 0 && decimalPlaces > 0) {
 
 4884  return {integral, decimal, exponent, decimalPlaces};
 
 4886template <
typename TWriter>
 
 4887class CountingDecorator {
 
 4889  explicit CountingDecorator(TWriter& writer) : writer_(writer), count_(0) {}
 
 4890  void write(uint8_t c) {
 
 4891    count_ += writer_.write(c);
 
 4893  void write(
const uint8_t* s, 
size_t n) {
 
 4894    count_ += writer_.write(s, n);
 
 4896  size_t count()
 const {
 
 4903template <
typename TWriter>
 
 4904class TextFormatter {
 
 4906  explicit TextFormatter(TWriter writer) : writer_(writer) {}
 
 4907  TextFormatter& operator=(
const TextFormatter&) = 
delete;
 
 4908  size_t bytesWritten()
 const {
 
 4909    return writer_.count();
 
 4911  void writeBoolean(
bool value) {
 
 4917  void writeString(
const char* value) {
 
 4918    ARDUINOJSON_ASSERT(value != NULL);
 
 4921      writeChar(*value++);
 
 4924  void writeString(
const char* value, 
size_t n) {
 
 4925    ARDUINOJSON_ASSERT(value != NULL);
 
 4928      writeChar(*value++);
 
 4931  void writeChar(
char c) {
 
 4932    char specialChar = EscapeSequence::escapeChar(c);
 
 4935      writeRaw(specialChar);
 
 4939      writeRaw(
"\\u0000");
 
 4942  template <
typename T>
 
 4943  void writeFloat(T value) {
 
 4944    writeFloat(JsonFloat(value), 
sizeof(T) >= 8 ? 9 : 6);
 
 4946  void writeFloat(JsonFloat value, int8_t decimalPlaces) {
 
 4948      return writeRaw(ARDUINOJSON_ENABLE_NAN ? 
"NaN" : 
"null");
 
 4949#if ARDUINOJSON_ENABLE_INFINITY 
 4955      return writeRaw(
"Infinity");
 
 4958      return writeRaw(
"null");
 
 4964    auto parts = decomposeFloat(value, decimalPlaces);
 
 4965    writeInteger(parts.integral);
 
 4966    if (parts.decimalPlaces)
 
 4967      writeDecimals(parts.decimal, parts.decimalPlaces);
 
 4968    if (parts.exponent) {
 
 4970      writeInteger(parts.exponent);
 
 4973  template <
typename T>
 
 4974  enable_if_t<is_signed<T>::value> writeInteger(T value) {
 
 4975    typedef make_unsigned_t<T> unsigned_type;
 
 4976    unsigned_type unsigned_value;
 
 4979      unsigned_value = unsigned_type(unsigned_type(~value) + 1);
 
 4981      unsigned_value = unsigned_type(value);
 
 4983    writeInteger(unsigned_value);
 
 4985  template <
typename T>
 
 4986  enable_if_t<is_unsigned<T>::value> writeInteger(T value) {
 
 4988    char* 
end = buffer + 
sizeof(buffer);
 
 4991      *--
begin = char(value % 10 + 
'0');
 
 4992      value = T(value / 10);
 
 4994    writeRaw(begin, end);
 
 4996  void writeDecimals(uint32_t value, int8_t width) {
 
 4998    char* 
end = buffer + 
sizeof(buffer);
 
 5001      *--
begin = char(value % 10 + 
'0');
 
 5005    writeRaw(begin, end);
 
 5007  void writeRaw(
const char* s) {
 
 5008    writer_.write(
reinterpret_cast<const uint8_t*
>(s), strlen(s));
 
 5010  void writeRaw(
const char* s, 
size_t n) {
 
 5011    writer_.write(
reinterpret_cast<const uint8_t*
>(s), n);
 
 5013  void writeRaw(
const char* begin, 
const char* end) {
 
 5014    writer_.write(
reinterpret_cast<const uint8_t*
>(begin),
 
 5015                  static_cast<size_t>(end - begin));
 
 5018  void writeRaw(
const char (&s)[N]) {
 
 5019    writer_.write(
reinterpret_cast<const uint8_t*
>(s), N - 1);
 
 5021  void writeRaw(
char c) {
 
 5022    writer_.write(
static_cast<uint8_t
>(c));
 
 5025  CountingDecorator<TWriter> writer_;
 
 5029  size_t write(uint8_t) {
 
 5032  size_t write(
const uint8_t*, 
size_t n) {
 
 5036template <
template <
typename> 
class TSerializer>
 
 5037size_t measure(FLArduinoJson::JsonVariantConst source) {
 
 5039  auto data = VariantAttorney::getData(source);
 
 5040  auto resources = VariantAttorney::getResourceManager(source);
 
 5041  TSerializer<DummyWriter> serializer(dp, resources);
 
 5042  return VariantData::accept(data, resources, serializer);
 
 5044template <
typename TDestination, 
typename Enable = 
void>
 
 5047  explicit Writer(TDestination& dest) : dest_(&dest) {}
 
 5048  size_t write(uint8_t c) {
 
 5049    return dest_->write(c);
 
 5051  size_t write(
const uint8_t* s, 
size_t n) {
 
 5052    return dest_->write(s, n);
 
 5055  TDestination* dest_;
 
 5057class StaticStringWriter {
 
 5059  StaticStringWriter(
char* buf, 
size_t size) : 
end(buf + size), p(buf) {}
 
 5060  size_t write(uint8_t c) {
 
 5063    *p++ = 
static_cast<char>(c);
 
 5066  size_t write(
const uint8_t* s, 
size_t n) {
 
 5068    while (p < end && n > 0) {
 
 5069      *p++ = 
static_cast<char>(*s++);
 
 5072    return size_t(p - begin);
 
 5078ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 5079#if ARDUINOJSON_ENABLE_STD_STRING 
 5080ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 5081template <
class T, 
typename = 
void>
 
 5084struct is_std_string<
 
 5085    T, 
enable_if_t<is_same<void, decltype(T().push_back('a'))>::value &&
 
 5086                   is_same<T&, decltype(T().append(""))>::value>> : 
true_type {
 
 5088template <
typename TDestination>
 
 5089class Writer<TDestination, 
enable_if_t<is_std_string<TDestination>::value>> {
 
 5091  Writer(TDestination& str) : str_(&str) {
 
 5094  size_t write(uint8_t c) {
 
 5095    str_->push_back(
static_cast<char>(c));
 
 5098  size_t write(
const uint8_t* s, 
size_t n) {
 
 5099    str_->append(
reinterpret_cast<const char*
>(s), n);
 
 5105ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 5107#if ARDUINOJSON_ENABLE_ARDUINO_STRING 
 5108ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 5110class Writer<::String, void> {
 
 5111  static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
 
 5113  explicit Writer(::String& str) : destination_(&str), size_(0) {
 
 5114    str = 
static_cast<const char*
>(0);
 
 5119  size_t write(uint8_t c) {
 
 5120    if (size_ + 1 >= bufferCapacity)
 
 5123    buffer_[size_++] = 
static_cast<char>(c);
 
 5126  size_t write(
const uint8_t* s, 
size_t n) {
 
 5127    for (
size_t i = 0; i < n; i++) {
 
 5133    ARDUINOJSON_ASSERT(size_ < bufferCapacity);
 
 5135    if (destination_->concat(buffer_))
 
 5140  ::String* destination_;
 
 5141  char buffer_[bufferCapacity];
 
 5144ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 5146#if ARDUINOJSON_ENABLE_STD_STREAM 
 5147ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 5148template <
typename TDestination>
 
 5149class Writer<TDestination,
 
 5150             enable_if_t<is_base_of<std::ostream, TDestination>::value>> {
 
 5152  explicit Writer(std::ostream& os) : os_(&os) {}
 
 5153  size_t write(uint8_t c) {
 
 5154    os_->put(
static_cast<char>(c));
 
 5157  size_t write(
const uint8_t* s, 
size_t n) {
 
 5158    os_->write(
reinterpret_cast<const char*
>(s),
 
 5159               static_cast<std::streamsize
>(n));
 
 5165ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 5167#if ARDUINOJSON_ENABLE_ARDUINO_PRINT 
 5168ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 5169template <
typename TDestination>
 
 5170class Writer<TDestination,
 
 5171             enable_if_t<is_base_of<::Print, TDestination>::value>> {
 
 5173  explicit Writer(::Print& print) : print_(&
print) {}
 
 5174  size_t write(uint8_t c) {
 
 5175    return print_->write(c);
 
 5177  size_t write(
const uint8_t* s, 
size_t n) {
 
 5178    return print_->write(s, n);
 
 5183ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 5185ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 5186template <
template <
typename> 
class TSerializer, 
typename TWriter>
 
 5187size_t doSerialize(FLArduinoJson::JsonVariantConst source, TWriter writer) {
 
 5188  auto data = VariantAttorney::getData(source);
 
 5189  auto resources = VariantAttorney::getResourceManager(source);
 
 5190  TSerializer<TWriter> serializer(writer, resources);
 
 5191  return VariantData::accept(data, resources, serializer);
 
 5193template <
template <
typename> 
class TSerializer, 
typename TDestination>
 
 5194size_t serialize(FLArduinoJson::JsonVariantConst source,
 
 5195                 TDestination& destination) {
 
 5196  Writer<TDestination> writer(destination);
 
 5197  return doSerialize<TSerializer>(source, writer);
 
 5199template <
template <
typename> 
class TSerializer>
 
 5200enable_if_t<!TSerializer<StaticStringWriter>::producesText, 
size_t> serialize(
 
 5201    FLArduinoJson::JsonVariantConst source, 
void* buffer, 
size_t bufferSize) {
 
 5202  StaticStringWriter writer(
reinterpret_cast<char*
>(buffer), bufferSize);
 
 5203  return doSerialize<TSerializer>(source, writer);
 
 5205template <
template <
typename> 
class TSerializer>
 
 5206enable_if_t<TSerializer<StaticStringWriter>::producesText, 
size_t> serialize(
 
 5207    FLArduinoJson::JsonVariantConst source, 
void* buffer, 
size_t bufferSize) {
 
 5208  StaticStringWriter writer(
reinterpret_cast<char*
>(buffer), bufferSize);
 
 5209  size_t n = doSerialize<TSerializer>(source, writer);
 
 5211    reinterpret_cast<char*
>(buffer)[n] = 0;
 
 5214template <
template <
typename> 
class TSerializer, 
typename TChar, 
size_t N>
 
 5215enable_if_t<IsChar<TChar>::value, 
size_t> serialize(
 
 5216    FLArduinoJson::JsonVariantConst source, TChar (&buffer)[N]) {
 
 5217  return serialize<TSerializer>(source, buffer, N);
 
 5219template <
typename TWriter>
 
 5220class JsonSerializer : 
public VariantDataVisitor<size_t> {
 
 5222  static const bool producesText = 
true;
 
 5223  JsonSerializer(TWriter writer, 
const ResourceManager* resources)
 
 5224      : formatter_(writer), resources_(resources) {}
 
 5225  size_t visit(
const ArrayData& array) {
 
 5227    auto slotId = array.head();
 
 5228    while (slotId != NULL_SLOT) {
 
 5229      auto slot = resources_->getVariant(slotId);
 
 5230      slot->accept(*
this, resources_);
 
 5231      slotId = slot->next();
 
 5232      if (slotId != NULL_SLOT)
 
 5236    return bytesWritten();
 
 5238  size_t visit(
const ObjectData& 
object) {
 
 5240    auto slotId = 
object.head();
 
 5242    while (slotId != NULL_SLOT) {
 
 5243      auto slot = resources_->getVariant(slotId);
 
 5244      slot->accept(*
this, resources_);
 
 5245      slotId = slot->next();
 
 5246      if (slotId != NULL_SLOT)
 
 5247        write(isKey ? 
':' : 
',');
 
 5251    return bytesWritten();
 
 5253  template <
typename T>
 
 5254  enable_if_t<is_floating_point<T>::value, 
size_t> visit(T value) {
 
 5255    formatter_.writeFloat(value);
 
 5256    return bytesWritten();
 
 5258  size_t visit(
const char* value) {
 
 5259    formatter_.writeString(value);
 
 5260    return bytesWritten();
 
 5262  size_t visit(JsonString value) {
 
 5263    formatter_.writeString(value.c_str(), value.size());
 
 5264    return bytesWritten();
 
 5266  size_t visit(RawString value) {
 
 5267    formatter_.writeRaw(value.data(), value.size());
 
 5268    return bytesWritten();
 
 5270  size_t visit(JsonInteger value) {
 
 5271    formatter_.writeInteger(value);
 
 5272    return bytesWritten();
 
 5274  size_t visit(JsonUInt value) {
 
 5275    formatter_.writeInteger(value);
 
 5276    return bytesWritten();
 
 5278  size_t visit(
bool value) {
 
 5279    formatter_.writeBoolean(value);
 
 5280    return bytesWritten();
 
 5282  size_t visit(nullptr_t) {
 
 5283    formatter_.writeRaw(
"null");
 
 5284    return bytesWritten();
 
 5287  size_t bytesWritten()
 const {
 
 5288    return formatter_.bytesWritten();
 
 5290  void write(
char c) {
 
 5291    formatter_.writeRaw(c);
 
 5293  void write(
const char* s) {
 
 5294    formatter_.writeRaw(s);
 
 5297  TextFormatter<TWriter> formatter_;
 
 5299  const ResourceManager* resources_;
 
 5301ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 5302ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 5303template <
typename TDestination>
 
 5304detail::enable_if_t<!detail::is_pointer<TDestination>::value, 
size_t>
 
 5305serializeJson(JsonVariantConst source, TDestination& destination) {
 
 5306  using namespace detail;
 
 5307  return serialize<JsonSerializer>(source, destination);
 
 5309inline size_t serializeJson(JsonVariantConst source, 
void* buffer,
 
 5310                            size_t bufferSize) {
 
 5311  using namespace detail;
 
 5312  return serialize<JsonSerializer>(source, buffer, bufferSize);
 
 5314inline size_t measureJson(JsonVariantConst source) {
 
 5315  using namespace detail;
 
 5316  return measure<JsonSerializer>(source);
 
 5318#if ARDUINOJSON_ENABLE_STD_STREAM 
 5319template <
typename T>
 
 5320inline detail::enable_if_t<detail::is_convertible<T, JsonVariantConst>::value,
 
 5322operator<<(std::ostream& os, 
const T& source) {
 
 5323  serializeJson(source, os);
 
 5327ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 5328ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 5329class StringBuilder {
 
 5331  static const size_t initialCapacity = 31;
 
 5332  StringBuilder(ResourceManager* resources) : resources_(resources) {}
 
 5335      resources_->destroyString(node_);
 
 5337  void startString() {
 
 5340      node_ = resources_->createString(initialCapacity);
 
 5342  StringNode* save() {
 
 5343    ARDUINOJSON_ASSERT(node_ != 
nullptr);
 
 5344    node_->data[size_] = 0;
 
 5345    StringNode* node = resources_->getString(adaptString(node_->data, size_));
 
 5347      node = resources_->resizeString(node_, size_);
 
 5348      ARDUINOJSON_ASSERT(node != 
nullptr);  
 
 5349      resources_->saveString(node);
 
 5356  void append(
const char* s) {
 
 5360  void append(
const char* s, 
size_t n) {
 
 5364  void append(
char c) {
 
 5365    if (node_ && size_ == node_->length)
 
 5366      node_ = resources_->resizeString(node_, size_ * 2U + 1);
 
 5368      node_->data[size_++] = c;
 
 5370  bool isValid()
 const {
 
 5371    return node_ != 
nullptr;
 
 5373  size_t size()
 const {
 
 5376  JsonString str()
 const {
 
 5377    ARDUINOJSON_ASSERT(node_ != 
nullptr);
 
 5378    node_->data[size_] = 0;
 
 5379    return JsonString(node_->data, size_, JsonString::Copied);
 
 5382  ResourceManager* resources_;
 
 5383  StringNode* node_ = 
nullptr;
 
 5386ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 5387#if ARDUINOJSON_ENABLE_STD_STRING 
 5390#if ARDUINOJSON_ENABLE_STRING_VIEW 
 5391#include <string_view> 
 5393ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 5394template <
typename T, 
typename Enable>
 
 5396  static_assert(!detail::is_same<T, char>::value,
 
 5397                "type 'char' is not supported, use 'signed char', 'unsigned " 
 5398                "char' or another integer type instead");
 
 5399  static void toJson(
const T& src, JsonVariant dst) {
 
 5400    convertToJson(src, dst); 
 
 5402  static T fromJson(JsonVariantConst src) {
 
 5403    static_assert(!detail::is_same<T, char*>::value,
 
 5404                  "type 'char*' is not supported, use 'const char*' instead");
 
 5406    convertFromJson(src, result);  
 
 5409  static bool checkJson(JsonVariantConst src) {
 
 5410    static_assert(!detail::is_same<T, char*>::value,
 
 5411                  "type 'char*' is not supported, use 'const char*' instead");
 
 5413    return canConvertFromJson(src, dummy);  
 
 5416template <
typename T>
 
 5417struct Converter<T, detail::
enable_if_t<detail::is_integral<T>::value &&
 
 5418                                        !detail::is_same<bool, T>::value &&
 
 5419                                        !detail::is_same<char, T>::value>>
 
 5420    : 
private detail::VariantAttorney {
 
 5421  static bool toJson(T src, JsonVariant dst) {
 
 5422    ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
 
 5423    auto data = getData(dst);
 
 5426    auto resources = getResourceManager(dst);
 
 5427    data->clear(resources);
 
 5428    return data->setInteger(src, resources);
 
 5430  static T fromJson(JsonVariantConst src) {
 
 5431    ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
 
 5432    auto data = getData(src);
 
 5433    auto resources = getResourceManager(src);
 
 5434    return data ? data->template asIntegral<T>(resources) : T();
 
 5436  static bool checkJson(JsonVariantConst src) {
 
 5437    auto data = getData(src);
 
 5438    auto resources = getResourceManager(src);
 
 5439    return data && data->template isInteger<T>(resources);
 
 5442template <
typename T>
 
 5443struct Converter<T, detail::
enable_if_t<detail::is_enum<T>::value>>
 
 5444    : 
private detail::VariantAttorney {
 
 5445  static bool toJson(T src, JsonVariant dst) {
 
 5446    return dst.set(
static_cast<JsonInteger
>(src));
 
 5448  static T fromJson(JsonVariantConst src) {
 
 5449    auto data = getData(src);
 
 5450    auto resources = getResourceManager(src);
 
 5451    return data ? 
static_cast<T
>(data->template asIntegral<int>(resources))
 
 5454  static bool checkJson(JsonVariantConst src) {
 
 5455    auto data = getData(src);
 
 5456    auto resources = getResourceManager(src);
 
 5457    return data && data->template isInteger<int>(resources);
 
 5461struct Converter<bool> : 
private detail::VariantAttorney {
 
 5462  static bool toJson(
bool src, JsonVariant dst) {
 
 5463    auto data = getData(dst);
 
 5466    auto resources = getResourceManager(dst);
 
 5467    data->clear(resources);
 
 5468    data->setBoolean(src);
 
 5471  static bool fromJson(JsonVariantConst src) {
 
 5472    auto data = getData(src);
 
 5473    auto resources = getResourceManager(src);
 
 5474    return data ? data->asBoolean(resources) : 
false;
 
 5476  static bool checkJson(JsonVariantConst src) {
 
 5477    auto data = getData(src);
 
 5478    return data && data->isBoolean();
 
 5481template <
typename T>
 
 5482struct Converter<T, detail::
enable_if_t<detail::is_floating_point<T>::value>>
 
 5483    : 
private detail::VariantAttorney {
 
 5484  static bool toJson(T src, JsonVariant dst) {
 
 5485    auto data = getData(dst);
 
 5488    auto resources = getResourceManager(dst);
 
 5489    data->clear(resources);
 
 5490    return data->setFloat(src, resources);
 
 5492  static T fromJson(JsonVariantConst src) {
 
 5493    auto data = getData(src);
 
 5494    auto resources = getResourceManager(src);
 
 5495    return data ? data->template asFloat<T>(resources) : 0;
 
 5497  static bool checkJson(JsonVariantConst src) {
 
 5498    auto data = getData(src);
 
 5499    return data && data->isFloat();
 
 5503struct Converter<const char*> : 
private detail::VariantAttorney {
 
 5504  static void toJson(
const char* src, JsonVariant dst) {
 
 5505    detail::VariantData::setString(getData(dst), detail::adaptString(src),
 
 5506                                   getResourceManager(dst));
 
 5508  static const char* fromJson(JsonVariantConst src) {
 
 5509    auto data = getData(src);
 
 5510    return data ? data->asString().c_str() : 0;
 
 5512  static bool checkJson(JsonVariantConst src) {
 
 5513    auto data = getData(src);
 
 5514    return data && data->isString();
 
 5518struct Converter<JsonString> : 
private detail::VariantAttorney {
 
 5519  static void toJson(JsonString src, JsonVariant dst) {
 
 5520    detail::VariantData::setString(getData(dst), detail::adaptString(src),
 
 5521                                   getResourceManager(dst));
 
 5523  static JsonString fromJson(JsonVariantConst src) {
 
 5524    auto data = getData(src);
 
 5525    return data ? data->asString() : 0;
 
 5527  static bool checkJson(JsonVariantConst src) {
 
 5528    auto data = getData(src);
 
 5529    return data && data->isString();
 
 5532template <
typename T>
 
 5533inline detail::enable_if_t<detail::IsString<T>::value> convertToJson(
 
 5534    const T& src, JsonVariant dst) {
 
 5535  using namespace detail;
 
 5536  auto data = VariantAttorney::getData(dst);
 
 5537  auto resources = VariantAttorney::getResourceManager(dst);
 
 5538  detail::VariantData::setString(data, adaptString(src), resources);
 
 5540template <
typename T>
 
 5541struct Converter<SerializedValue<T>> : 
private detail::VariantAttorney {
 
 5542  static void toJson(SerializedValue<T> src, JsonVariant dst) {
 
 5543    detail::VariantData::setRawString(getData(dst), src,
 
 5544                                      getResourceManager(dst));
 
 5548struct Converter<detail::
nullptr_t> : 
private detail::VariantAttorney {
 
 5549  static void toJson(detail::nullptr_t, JsonVariant dst) {
 
 5550    detail::VariantData::clear(getData(dst), getResourceManager(dst));
 
 5552  static detail::nullptr_t fromJson(JsonVariantConst) {
 
 5555  static bool checkJson(JsonVariantConst src) {
 
 5556    auto data = getData(src);
 
 5557    return data == 0 || data->isNull();
 
 5560#if ARDUINOJSON_ENABLE_ARDUINO_STREAM 
 5562class StringBuilderPrint : 
public Print {
 
 5564  StringBuilderPrint(ResourceManager* resources) : copier_(resources) {
 
 5565    copier_.startString();
 
 5567  StringNode* save() {
 
 5568    ARDUINOJSON_ASSERT(!overflowed());
 
 5569    return copier_.save();
 
 5571  size_t write(uint8_t c) {
 
 5572    copier_.append(
char(c));
 
 5573    return copier_.isValid() ? 1 : 0;
 
 5575  size_t write(
const uint8_t* buffer, 
size_t size) {
 
 5576    for (
size_t i = 0; i < size; i++) {
 
 5577      copier_.append(
char(buffer[i]));
 
 5578      if (!copier_.isValid())
 
 5583  bool overflowed()
 const {
 
 5584    return !copier_.isValid();
 
 5587  StringBuilder copier_;
 
 5592template<
typename Pr
intable>
 
 5593inline void convertToJson(
const Printable& src, JsonVariant dst) {
 
 5594  auto resources = detail::VariantAttorney::getResourceManager(dst);
 
 5595  auto data = detail::VariantAttorney::getData(dst);
 
 5596  if (!resources || !data)
 
 5598  data->clear(resources);
 
 5599  detail::StringBuilderPrint 
print(resources);
 
 5601  if (
print.overflowed())
 
 5603  data->setOwnedString(
print.save());
 
 5607#if ARDUINOJSON_ENABLE_ARDUINO_STRING 
 5608inline void convertFromJson(JsonVariantConst src, ::String& dst) {
 
 5609  JsonString str = src.as<JsonString>();
 
 5613    serializeJson(src, dst);
 
 5615inline bool canConvertFromJson(JsonVariantConst src, const ::String&) {
 
 5616  return src.is<JsonString>();
 
 5619#if ARDUINOJSON_ENABLE_STD_STRING 
 5620inline void convertFromJson(JsonVariantConst src, std::string& dst) {
 
 5621  JsonString str = src.as<JsonString>();
 
 5623    dst.assign(str.c_str(), str.size());
 
 5625    serializeJson(src, dst);
 
 5627inline bool canConvertFromJson(JsonVariantConst src, 
const std::string&) {
 
 5628  return src.is<JsonString>();
 
 5631#if ARDUINOJSON_ENABLE_STRING_VIEW 
 5632inline void convertFromJson(JsonVariantConst src, std::string_view& dst) {
 
 5633  JsonString str = src.as<JsonString>();
 
 5635    dst = std::string_view(str.c_str(), str.size());
 
 5637inline bool canConvertFromJson(JsonVariantConst src, 
const std::string_view&) {
 
 5638  return src.is<JsonString>();
 
 5642struct Converter<JsonArrayConst> : 
private detail::VariantAttorney {
 
 5643  static void toJson(JsonArrayConst src, JsonVariant dst) {
 
 5649  static JsonArrayConst fromJson(JsonVariantConst src) {
 
 5650    auto data = getData(src);
 
 5651    auto array = data ? data->asArray() : 
nullptr;
 
 5652    return JsonArrayConst(array, getResourceManager(src));
 
 5654  static bool checkJson(JsonVariantConst src) {
 
 5655    auto data = getData(src);
 
 5656    return data && data->isArray();
 
 5660struct Converter<
JsonArray> : 
private detail::VariantAttorney {
 
 5661  static void toJson(JsonVariantConst src, JsonVariant dst) {
 
 5667  static JsonArray fromJson(JsonVariant src) {
 
 5668    auto data = getData(src);
 
 5669    auto resources = getResourceManager(src);
 
 5670    return JsonArray(data != 0 ? data->asArray() : 0, resources);
 
 5672  static bool checkJson(JsonVariant src) {
 
 5673    auto data = getData(src);
 
 5674    return data && data->isArray();
 
 5678struct Converter<JsonObjectConst> : 
private detail::VariantAttorney {
 
 5679  static void toJson(JsonVariantConst src, JsonVariant dst) {
 
 5685  static JsonObjectConst fromJson(JsonVariantConst src) {
 
 5686    auto data = getData(src);
 
 5687    auto object = data != 0 ? data->asObject() : 
nullptr;
 
 5688    return JsonObjectConst(
object, getResourceManager(src));
 
 5690  static bool checkJson(JsonVariantConst src) {
 
 5691    auto data = getData(src);
 
 5692    return data && data->isObject();
 
 5696struct Converter<
JsonObject> : 
private detail::VariantAttorney {
 
 5697  static void toJson(JsonVariantConst src, JsonVariant dst) {
 
 5703  static JsonObject fromJson(JsonVariant src) {
 
 5704    auto data = getData(src);
 
 5705    auto resources = getResourceManager(src);
 
 5706    return JsonObject(data != 0 ? data->asObject() : 0, resources);
 
 5708  static bool checkJson(JsonVariant src) {
 
 5709    auto data = getData(src);
 
 5710    return data && data->isObject();
 
 5713ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 5714ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 5715class JsonVariantCopier {
 
 5717  typedef bool result_type;
 
 5718  JsonVariantCopier(JsonVariant dst) : dst_(dst) {}
 
 5719  template <
typename T>
 
 5721    return dst_.set(src);
 
 5726inline bool copyVariant(JsonVariant dst, JsonVariantConst src) {
 
 5727  if (dst.isUnbound())
 
 5729  JsonVariantCopier copier(dst);
 
 5730  return accept(src, copier);
 
 5732template <
typename T>
 
 5733inline void VariantData::setRawString(SerializedValue<T> value,
 
 5734                                      ResourceManager* resources) {
 
 5735  ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 5736  auto dup = resources->saveString(adaptString(value.data(), value.size()));
 
 5740template <
typename TAdaptedString>
 
 5741inline bool VariantData::setString(TAdaptedString value,
 
 5742                                   ResourceManager* resources) {
 
 5743  ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 5746  if (value.isLinked()) {
 
 5747    setLinkedString(value.data());
 
 5750  auto dup = resources->saveString(value);
 
 5752    setOwnedString(dup);
 
 5757inline void VariantData::clear(ResourceManager* resources) {
 
 5758  if (type_ & VariantTypeBits::OwnedStringBit)
 
 5759    resources->dereferenceString(content_.asOwnedString->data);
 
 5760#if ARDUINOJSON_USE_EXTENSIONS 
 5761  if (type_ & VariantTypeBits::ExtensionBit)
 
 5762    resources->freeExtension(content_.asSlotId);
 
 5764  auto collection = asCollection();
 
 5766    collection->clear(resources);
 
 5767  type_ = VariantType::Null;
 
 5769#if ARDUINOJSON_USE_EXTENSIONS 
 5770inline const VariantExtension* VariantData::getExtension(
 
 5771    const ResourceManager* resources)
 const {
 
 5772  return type_ & VariantTypeBits::ExtensionBit
 
 5773             ? resources->getExtension(content_.asSlotId)
 
 5777template <
typename T>
 
 5778enable_if_t<
sizeof(T) == 8, 
bool> VariantData::setFloat(
 
 5779    T value, ResourceManager* resources) {
 
 5780  ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 5782  float valueAsFloat = 
static_cast<float>(value);
 
 5783#if ARDUINOJSON_USE_DOUBLE 
 5784  if (value == valueAsFloat) {
 
 5785    type_ = VariantType::Float;
 
 5786    content_.asFloat = valueAsFloat;
 
 5788    auto extension = resources->allocExtension();
 
 5791    type_ = VariantType::Double;
 
 5792    content_.asSlotId = extension.id();
 
 5793    extension->asDouble = value;
 
 5796  type_ = VariantType::Float;
 
 5797  content_.asFloat = valueAsFloat;
 
 5801template <
typename T>
 
 5802enable_if_t<is_signed<T>::value, 
bool> VariantData::setInteger(
 
 5803    T value, ResourceManager* resources) {
 
 5804  ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 5806  if (canConvertNumber<int32_t>(value)) {
 
 5807    type_ = VariantType::Int32;
 
 5808    content_.asInt32 = 
static_cast<int32_t
>(value);
 
 5810#if ARDUINOJSON_USE_LONG_LONG 
 5812    auto extension = resources->allocExtension();
 
 5815    type_ = VariantType::Int64;
 
 5816    content_.asSlotId = extension.id();
 
 5817    extension->asInt64 = value;
 
 5822template <
typename T>
 
 5823enable_if_t<is_unsigned<T>::value, 
bool> VariantData::setInteger(
 
 5824    T value, ResourceManager* resources) {
 
 5825  ARDUINOJSON_ASSERT(type_ == VariantType::Null);  
 
 5827  if (canConvertNumber<uint32_t>(value)) {
 
 5828    type_ = VariantType::Uint32;
 
 5829    content_.asUint32 = 
static_cast<uint32_t
>(value);
 
 5831#if ARDUINOJSON_USE_LONG_LONG 
 5833    auto extension = resources->allocExtension();
 
 5836    type_ = VariantType::Uint64;
 
 5837    content_.asSlotId = extension.id();
 
 5838    extension->asUint64 = value;
 
 5843template <
typename TDerived>
 
 5844inline JsonVariant VariantRefBase<TDerived>::add()
 const {
 
 5845  return add<JsonVariant>();
 
 5847template <
typename TDerived>
 
 5848template <
typename T>
 
 5849inline T VariantRefBase<TDerived>::as()
 const {
 
 5850  using variant_type =  
 
 5851      typename function_traits<
decltype(&Converter<T>::fromJson)>::arg1_type;
 
 5852  return Converter<T>::fromJson(getVariant<variant_type>());
 
 5854template <
typename TDerived>
 
 5855inline JsonArray VariantRefBase<TDerived>::createNestedArray()
 const {
 
 5856  return add<JsonArray>();
 
 5858template <
typename TDerived>
 
 5859template <
typename TChar>
 
 5860inline JsonArray VariantRefBase<TDerived>::createNestedArray(TChar* key)
 const {
 
 5861  return operator[](key).template to<JsonArray>();
 
 5863template <
typename TDerived>
 
 5864template <
typename TString>
 
 5865inline JsonArray VariantRefBase<TDerived>::createNestedArray(
 
 5866    const TString& key)
 const {
 
 5867  return operator[](key).template to<JsonArray>();
 
 5869template <
typename TDerived>
 
 5870inline JsonObject VariantRefBase<TDerived>::createNestedObject()
 const {
 
 5871  return add<JsonObject>();
 
 5873template <
typename TDerived>
 
 5874template <
typename TChar>
 
 5875inline JsonObject VariantRefBase<TDerived>::createNestedObject(
 
 5877  return operator[](key).template to<JsonObject>();
 
 5879template <
typename TDerived>
 
 5880template <
typename TString>
 
 5881inline JsonObject VariantRefBase<TDerived>::createNestedObject(
 
 5882    const TString& key)
 const {
 
 5883  return operator[](key).template to<JsonObject>();
 
 5885template <
typename TDerived>
 
 5886inline void convertToJson(
const VariantRefBase<TDerived>& src,
 
 5888  dst.set(src.template as<JsonVariantConst>());
 
 5890template <
typename TDerived>
 
 5891template <
typename T>
 
 5892inline enable_if_t<is_same<T, JsonVariant>::value, T>
 
 5893VariantRefBase<TDerived>::add()
 const {
 
 5895      detail::VariantData::addElement(getOrCreateData(), getResourceManager()),
 
 5896      getResourceManager());
 
 5898template <
typename TDerived>
 
 5899template <
typename TString>
 
 5900inline enable_if_t<IsString<TString>::value, 
bool>
 
 5901VariantRefBase<TDerived>::containsKey(
const TString& key)
 const {
 
 5902  return VariantData::getMember(getData(), adaptString(key),
 
 5903                                getResourceManager()) != 0;
 
 5905template <
typename TDerived>
 
 5906template <
typename TChar>
 
 5907inline enable_if_t<IsString<TChar*>::value, 
bool>
 
 5908VariantRefBase<TDerived>::containsKey(TChar* key)
 const {
 
 5909  return VariantData::getMember(getData(), adaptString(key),
 
 5910                                getResourceManager()) != 0;
 
 5912template <
typename TDerived>
 
 5913template <
typename TVariant>
 
 5914inline enable_if_t<IsVariant<TVariant>::value, 
bool>
 
 5915VariantRefBase<TDerived>::containsKey(
const TVariant& key)
 const {
 
 5916  return containsKey(key.template as<const char*>());
 
 5918template <
typename TDerived>
 
 5919inline JsonVariant VariantRefBase<TDerived>::getVariant()
 const {
 
 5920  return JsonVariant(getData(), getResourceManager());
 
 5922template <
typename TDerived>
 
 5923inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant()
 const {
 
 5924  return JsonVariant(getOrCreateData(), getResourceManager());
 
 5926template <
typename TDerived>
 
 5927template <
typename T>
 
 5928inline bool VariantRefBase<TDerived>::is()
 const {
 
 5929  using variant_type =  
 
 5930      typename function_traits<
decltype(&Converter<T>::checkJson)>::arg1_type;
 
 5931  return Converter<T>::checkJson(getVariant<variant_type>());
 
 5933template <
typename TDerived>
 
 5934inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
 
 5935    size_t index)
 const {
 
 5936  return ElementProxy<TDerived>(derived(), index);
 
 5938template <
typename TDerived>
 
 5939template <
typename TString>
 
 5940inline enable_if_t<IsString<TString*>::value, MemberProxy<TDerived, TString*>>
 
 5941VariantRefBase<TDerived>::operator[](TString* key)
 const {
 
 5942  return MemberProxy<TDerived, TString*>(derived(), key);
 
 5944template <
typename TDerived>
 
 5945template <
typename TString>
 
 5946inline enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>>
 
 5947VariantRefBase<TDerived>::operator[](
const TString& key)
 const {
 
 5948  return MemberProxy<TDerived, TString>(derived(), key);
 
 5950template <
typename TDerived>
 
 5951template <
typename TConverter, 
typename T>
 
 5952inline bool VariantRefBase<TDerived>::doSet(T&& value, false_type)
 const {
 
 5953  TConverter::toJson(value, getOrCreateVariant());
 
 5954  auto resources = getResourceManager();
 
 5955  return resources && !resources->overflowed();
 
 5957template <
typename TDerived>
 
 5958template <
typename TConverter, 
typename T>
 
 5959inline bool VariantRefBase<TDerived>::doSet(T&& value, true_type)
 const {
 
 5960  return TConverter::toJson(value, getOrCreateVariant());
 
 5962template <
typename TDerived>
 
 5963template <
typename T>
 
 5964inline enable_if_t<is_same<T, JsonArray>::value, 
JsonArray>
 
 5965VariantRefBase<TDerived>::to()
 const {
 
 5967      VariantData::toArray(getOrCreateData(), getResourceManager()),
 
 5968      getResourceManager());
 
 5970template <
typename TDerived>
 
 5971template <
typename T>
 
 5972enable_if_t<is_same<T, JsonObject>::value, 
JsonObject>
 
 5973VariantRefBase<TDerived>::to()
 const {
 
 5975      VariantData::toObject(getOrCreateData(), getResourceManager()),
 
 5976      getResourceManager());
 
 5978template <
typename TDerived>
 
 5979template <
typename T>
 
 5980enable_if_t<is_same<T, JsonVariant>::value, JsonVariant>
 
 5981VariantRefBase<TDerived>::to()
 const {
 
 5982  auto data = getOrCreateData();
 
 5983  auto resources = getResourceManager();
 
 5984  detail::VariantData::clear(data, resources);
 
 5985  return JsonVariant(data, resources);
 
 5987ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 5988#if ARDUINOJSON_ENABLE_STD_STREAM 
 5990ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 5991class DeserializationError {
 
 6001  DeserializationError() {}
 
 6002  DeserializationError(Code c) : code_(c) {}
 
 6003  friend bool operator==(
const DeserializationError& lhs,
 
 6004                         const DeserializationError& rhs) {
 
 6005    return lhs.code_ == rhs.code_;
 
 6007  friend bool operator!=(
const DeserializationError& lhs,
 
 6008                         const DeserializationError& rhs) {
 
 6009    return lhs.code_ != rhs.code_;
 
 6011  friend bool operator==(
const DeserializationError& lhs, Code rhs) {
 
 6012    return lhs.code_ == rhs;
 
 6014  friend bool operator==(Code lhs, 
const DeserializationError& rhs) {
 
 6015    return lhs == rhs.code_;
 
 6017  friend bool operator!=(
const DeserializationError& lhs, Code rhs) {
 
 6018    return lhs.code_ != rhs;
 
 6020  friend bool operator!=(Code lhs, 
const DeserializationError& rhs) {
 
 6021    return lhs != rhs.code_;
 
 6023  explicit operator bool()
 const {
 
 6029  const char* c_str()
 const {
 
 6030    static const char* messages[] = {
 
 6031        "Ok",           
"EmptyInput", 
"IncompleteInput",
 
 6032        "InvalidInput", 
"NoMemory",   
"TooDeep"};
 
 6033    ARDUINOJSON_ASSERT(
static_cast<size_t>(code_) <
 
 6034                       sizeof(messages) / 
sizeof(messages[0]));
 
 6035    return messages[code_];
 
 6037#if ARDUINOJSON_ENABLE_PROGMEM 
 6038  const __FlashStringHelper* f_str()
 const {
 
 6039    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(
char, s0, 
"Ok");
 
 6040    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(
char, s1, 
"EmptyInput");
 
 6041    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(
char, s2, 
"IncompleteInput");
 
 6042    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(
char, s3, 
"InvalidInput");
 
 6043    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(
char, s4, 
"NoMemory");
 
 6044    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(
char, s5, 
"TooDeep");
 
 6045    ARDUINOJSON_DEFINE_PROGMEM_ARRAY(
const char*, messages,
 
 6046                                     {s0, s1, s2, s3, s4, s5});
 
 6047    return reinterpret_cast<const __FlashStringHelper*
>(
 
 6048        detail::pgm_read(messages + code_));
 
 6054#if ARDUINOJSON_ENABLE_STD_STREAM 
 6055inline std::ostream& 
operator<<(std::ostream& s,
 
 6056                                const DeserializationError& e) {
 
 6060inline std::ostream& 
operator<<(std::ostream& s, DeserializationError::Code c) {
 
 6061  s << DeserializationError(c).c_str();
 
 6065namespace DeserializationOption {
 
 6068#if ARDUINOJSON_AUTO_SHRINK 
 6069  explicit Filter(JsonDocument& doc) : variant_(doc) {
 
 6073  explicit Filter(JsonVariantConst variant) : variant_(variant) {}
 
 6074  bool allow()
 const {
 
 6077  bool allowArray()
 const {
 
 6078    return variant_ == 
true || variant_.is<JsonArrayConst>();
 
 6080  bool allowObject()
 const {
 
 6081    return variant_ == 
true || variant_.is<JsonObjectConst>();
 
 6083  bool allowValue()
 const {
 
 6084    return variant_ == 
true;
 
 6086  template <
typename TKey>
 
 6087  Filter operator[](
const TKey& key)
 const {
 
 6088    if (variant_ == 
true)  
 
 6090    JsonVariantConst member = variant_[key];
 
 6091    return Filter(member.isNull() ? variant_[
"*"] : member);
 
 6094  JsonVariantConst variant_;
 
 6098struct AllowAllFilter {
 
 6099  bool allow()
 const {
 
 6102  bool allowArray()
 const {
 
 6105  bool allowObject()
 const {
 
 6108  bool allowValue()
 const {
 
 6111  template <
typename TKey>
 
 6112  AllowAllFilter operator[](
const TKey&)
 const {
 
 6113    return AllowAllFilter();
 
 6117namespace DeserializationOption {
 
 6120  NestingLimit() : value_(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
 
 6121  explicit NestingLimit(uint8_t n) : value_(n) {}
 
 6122  NestingLimit decrement()
 const {
 
 6123    ARDUINOJSON_ASSERT(value_ > 0);
 
 6124    return NestingLimit(
static_cast<uint8_t
>(value_ - 1));
 
 6126  bool reached()
 const {
 
 6133ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 6134ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 6135template <
typename TFilter>
 
 6136struct DeserializationOptions {
 
 6138  DeserializationOption::NestingLimit nestingLimit;
 
 6140template <
typename TFilter>
 
 6141inline DeserializationOptions<TFilter> makeDeserializationOptions(
 
 6142    TFilter filter, DeserializationOption::NestingLimit nestingLimit = {}) {
 
 6143  return {filter, nestingLimit};
 
 6145template <
typename TFilter>
 
 6146inline DeserializationOptions<TFilter> makeDeserializationOptions(
 
 6147    DeserializationOption::NestingLimit nestingLimit, TFilter filter) {
 
 6148  return {filter, nestingLimit};
 
 6150inline DeserializationOptions<AllowAllFilter> makeDeserializationOptions(
 
 6151    DeserializationOption::NestingLimit nestingLimit = {}) {
 
 6152  return {{}, nestingLimit};
 
 6154template <
typename TSource, 
typename Enable = 
void>
 
 6157  Reader(TSource& source) : source_(&source) {}
 
 6159    return source_->read();  
 
 6161  size_t readBytes(
char* buffer, 
size_t length) {
 
 6162    return source_->readBytes(buffer, 
length);
 
 6167template <
typename TSource, 
typename Enable = 
void>
 
 6168struct BoundedReader {
 
 6170template <
typename TIterator>
 
 6171class IteratorReader {
 
 6172  TIterator ptr_, end_;
 
 6174  explicit IteratorReader(TIterator begin, TIterator end)
 
 6178      return static_cast<unsigned char>(*ptr_++);
 
 6182  size_t readBytes(
char* buffer, 
size_t length) {
 
 6184    while (i < 
length && ptr_ < end_)
 
 6185      buffer[i++] = *ptr_++;
 
 6189template <
typename TSource>
 
 6190struct Reader<TSource, void_t<typename TSource::const_iterator>>
 
 6191    : IteratorReader<typename TSource::const_iterator> {
 
 6192  explicit Reader(
const TSource& source)
 
 6193      : IteratorReader<typename TSource::const_iterator>(source.
begin(),
 
 6196template <
typename T>
 
 6197struct IsCharOrVoid {
 
 6198  static const bool value =
 
 6199      is_same<T, void>::value || is_same<T, char>::value ||
 
 6200      is_same<T, unsigned char>::value || is_same<T, signed char>::value;
 
 6202template <
typename T>
 
 6203struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
 
 6204template <
typename TSource>
 
 6205struct Reader<TSource*, enable_if_t<IsCharOrVoid<TSource>::value>> {
 
 6208  explicit Reader(
const void* ptr)
 
 6209      : ptr_(ptr ? reinterpret_cast<const char*>(ptr) : 
"") {}
 
 6211    return static_cast<unsigned char>(*ptr_++);
 
 6213  size_t readBytes(
char* buffer, 
size_t length) {
 
 6214    for (
size_t i = 0; i < 
length; i++)
 
 6215      buffer[i] = *ptr_++;
 
 6219template <
typename TSource>
 
 6220struct BoundedReader<TSource*, enable_if_t<IsCharOrVoid<TSource>::value>>
 
 6221    : 
public IteratorReader<const char*> {
 
 6223  explicit BoundedReader(
const void* ptr, 
size_t len)
 
 6224      : IteratorReader<const char*>(reinterpret_cast<const char*>(ptr),
 
 6225                                    reinterpret_cast<const char*>(ptr) + len) {}
 
 6227template <
typename TVariant>
 
 6228struct Reader<TVariant, 
enable_if_t<IsVariant<TVariant>::value>>
 
 6229    : Reader<char*, void> {
 
 6230  explicit Reader(
const TVariant& 
x)
 
 6231      : Reader<char*, void>(
x.template as<const char*>()) {}
 
 6233ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 6234#if ARDUINOJSON_ENABLE_ARDUINO_STREAM 
 6235ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 6236template <
typename TSource>
 
 6237struct Reader<TSource, 
enable_if_t<is_base_of<Stream, TSource>::value>> {
 
 6239  explicit Reader(Stream& stream) : stream_(&stream) {}
 
 6242    return stream_->readBytes(&c, 1) ? 
static_cast<unsigned char>(c) : -1;
 
 6244  size_t readBytes(
char* buffer, 
size_t length) {
 
 6245    return stream_->readBytes(buffer, 
length);
 
 6250ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 6252#if ARDUINOJSON_ENABLE_ARDUINO_STRING 
 6253ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 6254template <
typename TSource>
 
 6255struct Reader<TSource, 
enable_if_t<is_base_of<::String, TSource>::value>>
 
 6256    : BoundedReader<const char*> {
 
 6257  explicit Reader(const ::String& s)
 
 6258      : BoundedReader<const char*>(s.c_str(), s.
length()) {}
 
 6260ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 6262#if ARDUINOJSON_ENABLE_PROGMEM 
 6263ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 6265struct Reader<const __FlashStringHelper*, 
void> {
 
 6268  explicit Reader(
const __FlashStringHelper* ptr)
 
 6269      : ptr_(reinterpret_cast<const char*>(ptr)) {}
 
 6271    return pgm_read_byte(ptr_++);
 
 6273  size_t readBytes(
char* buffer, 
size_t length) {
 
 6274    memcpy_P(buffer, ptr_, 
length);
 
 6280struct BoundedReader<const __FlashStringHelper*, 
void> {
 
 6284  explicit BoundedReader(
const __FlashStringHelper* ptr, 
size_t size)
 
 6285      : ptr_(reinterpret_cast<const char*>(ptr)), end_(ptr_ + size) {}
 
 6288      return pgm_read_byte(ptr_++);
 
 6292  size_t readBytes(
char* buffer, 
size_t length) {
 
 6293    size_t available = 
static_cast<size_t>(end_ - ptr_);
 
 6296    memcpy_P(buffer, ptr_, 
length);
 
 6301ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 6303#if ARDUINOJSON_ENABLE_STD_STREAM 
 6305ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 6306template <
typename TSource>
 
 6307struct Reader<TSource, 
enable_if_t<is_base_of<std::istream, TSource>::value>> {
 
 6309  explicit Reader(std::istream& stream) : stream_(&stream) {}
 
 6311    return stream_->get();
 
 6313  size_t readBytes(
char* buffer, 
size_t length) {
 
 6314    stream_->read(buffer, 
static_cast<std::streamsize
>(
length));
 
 6315    return static_cast<size_t>(stream_->gcount());
 
 6318  std::istream* stream_;
 
 6320ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 6322ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 6323template <
typename TInput>
 
 6324Reader<remove_reference_t<TInput>> makeReader(TInput&& input) {
 
 6325  return Reader<remove_reference_t<TInput>>{detail::forward<TInput>(input)};
 
 6327template <
typename TChar>
 
 6328BoundedReader<TChar*> makeReader(TChar* input, 
size_t inputSize) {
 
 6329  return BoundedReader<TChar*>{input, inputSize};
 
 6331template <
typename...>
 
 6332struct first_or_void {
 
 6335template <
typename T, 
typename... Rest>
 
 6336struct first_or_void<T, Rest...> {
 
 6339template <
class T, 
class = 
void>
 
 6340struct is_deserialize_destination : 
false_type {};
 
 6342struct is_deserialize_destination<
 
 6343    T, 
enable_if_t<is_same<decltype(VariantAttorney::getResourceManager(
 
 6344                               detail::declval<T&>())),
 
 6345                           ResourceManager*>::value>> : 
true_type {};
 
 6346template <
typename TDestination>
 
 6347inline void shrinkJsonDocument(TDestination&) {
 
 6349#if ARDUINOJSON_AUTO_SHRINK 
 6350inline void shrinkJsonDocument(JsonDocument& doc) {
 
 6354template <
template <
typename> 
class TDeserializer, 
typename TDestination,
 
 6355          typename TReader, 
typename TOptions>
 
 6356DeserializationError doDeserialize(TDestination&& dst, TReader reader,
 
 6358  auto data = VariantAttorney::getOrCreateData(dst);
 
 6360    return DeserializationError::NoMemory;
 
 6361  auto resources = VariantAttorney::getResourceManager(dst);
 
 6363  auto err = TDeserializer<TReader>(resources, reader)
 
 6364                 .parse(*data, options.filter, options.nestingLimit);
 
 6365  shrinkJsonDocument(dst);
 
 6368template <
template <
typename> 
class TDeserializer, 
typename TDestination,
 
 6369          typename TStream, 
typename... Args,
 
 6371              !is_integral<
typename first_or_void<Args...>::type>::value>>
 
 6372DeserializationError deserialize(TDestination&& dst, TStream&& input,
 
 6374  return doDeserialize<TDeserializer>(
 
 6375      dst, makeReader(detail::forward<TStream>(input)),
 
 6376      makeDeserializationOptions(
args...));
 
 6378template <
template <
typename> 
class TDeserializer, 
typename TDestination,
 
 6379          typename TChar, 
typename Size, 
typename... Args,
 
 6380          typename = enable_if_t<is_integral<Size>::value>>
 
 6381DeserializationError deserialize(TDestination&& dst, TChar* input,
 
 6382                                 Size inputSize, Args... 
args) {
 
 6383  return doDeserialize<TDeserializer>(dst, makeReader(input, 
size_t(inputSize)),
 
 6384                                      makeDeserializationOptions(
args...));
 
 6386template <
typename TReader>
 
 6389  Latch(TReader reader) : reader_(reader), loaded_(false) {
 
 6390#if ARDUINOJSON_DEBUG 
 6400  FORCE_INLINE 
char current() {
 
 6408    ARDUINOJSON_ASSERT(!ended_);
 
 6409    int c = reader_.read();
 
 6410#if ARDUINOJSON_DEBUG 
 6414    current_ = 
static_cast<char>(c > 0 ? c : 0);
 
 6420#if ARDUINOJSON_DEBUG 
 6424ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 6425#if defined(__GNUC__) 
 6427#    pragma GCC diagnostic push 
 6428#    pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 
 6431ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 6433inline bool isHighSurrogate(uint16_t codeunit) {
 
 6434  return codeunit >= 0xD800 && codeunit < 0xDC00;
 
 6436inline bool isLowSurrogate(uint16_t codeunit) {
 
 6437  return codeunit >= 0xDC00 && codeunit < 0xE000;
 
 6441  Codepoint() : highSurrogate_(0), codepoint_(0) {}
 
 6442  bool append(uint16_t codeunit) {
 
 6443    if (isHighSurrogate(codeunit)) {
 
 6444      highSurrogate_ = codeunit & 0x3FF;
 
 6447    if (isLowSurrogate(codeunit)) {
 
 6449          uint32_t(0x10000 + ((highSurrogate_ << 10) | (codeunit & 0x3FF)));
 
 6452    codepoint_ = codeunit;
 
 6455  uint32_t value()
 const {
 
 6459  uint16_t highSurrogate_;
 
 6460  uint32_t codepoint_;
 
 6463ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 6464#if defined(__GNUC__) 
 6466#    pragma GCC diagnostic pop 
 6469ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 6471template <
typename TStringBuilder>
 
 6472inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) {
 
 6473  if (codepoint32 < 0x80) {
 
 6474    str.append(
char(codepoint32));
 
 6479    *(p++) = 
char((codepoint32 | 0x80) & 0xBF);
 
 6480    uint16_t codepoint16 = uint16_t(codepoint32 >> 6);
 
 6481    if (codepoint16 < 0x20) {  
 
 6482      *(p++) = 
char(codepoint16 | 0xC0);
 
 6484      *(p++) = 
char((codepoint16 | 0x80) & 0xBF);
 
 6485      codepoint16 = uint16_t(codepoint16 >> 6);
 
 6486      if (codepoint16 < 0x10) {  
 
 6487        *(p++) = 
char(codepoint16 | 0xE0);
 
 6489        *(p++) = 
char((codepoint16 | 0x80) & 0xBF);
 
 6490        codepoint16 = uint16_t(codepoint16 >> 6);
 
 6491        *(p++) = 
char(codepoint16 | 0xF0);
 
 6501inline bool isdigit(
char c) {
 
 6502  return '0' <= c && c <= 
'9';
 
 6505inline bool issign(
char c) {
 
 6506  return '-' == c || c == 
'+';
 
 6508template <
typename A, 
typename B>
 
 6509using largest_type = 
conditional_t<(
sizeof(A) > 
sizeof(B)), A, B>;
 
 6510enum class NumberType : uint8_t {
 
 6515#if ARDUINOJSON_USE_DOUBLE 
 6521  NumberValue(
float x) : asFloat(
x) {}
 
 6522  NumberValue(JsonInteger 
x) : asSignedInteger(
x) {}
 
 6523  NumberValue(JsonUInt 
x) : asUnsignedInteger(
x) {}
 
 6524#if ARDUINOJSON_USE_DOUBLE 
 6525  NumberValue(
double x) : asDouble(
x) {}
 
 6527  JsonInteger asSignedInteger;
 
 6528  JsonUInt asUnsignedInteger;
 
 6530#if ARDUINOJSON_USE_DOUBLE 
 6538  Number() : type_(NumberType::Invalid) {}
 
 6539  Number(
float value) : type_(NumberType::Float), value_(value) {}
 
 6540  Number(JsonInteger value) : type_(NumberType::SignedInteger), value_(value) {}
 
 6541  Number(JsonUInt value) : type_(NumberType::UnsignedInteger), value_(value) {}
 
 6542#if ARDUINOJSON_USE_DOUBLE 
 6543  Number(
double value) : type_(NumberType::Double), value_(value) {}
 
 6545  template <
typename T>
 
 6546  T convertTo()
 const {
 
 6548      case NumberType::Float:
 
 6549        return convertNumber<T>(value_.asFloat);
 
 6550      case NumberType::SignedInteger:
 
 6551        return convertNumber<T>(value_.asSignedInteger);
 
 6552      case NumberType::UnsignedInteger:
 
 6553        return convertNumber<T>(value_.asUnsignedInteger);
 
 6554#if ARDUINOJSON_USE_DOUBLE 
 6555      case NumberType::Double:
 
 6556        return convertNumber<T>(value_.asDouble);
 
 6562  NumberType type()
 const {
 
 6565  JsonInteger asSignedInteger()
 const {
 
 6566    ARDUINOJSON_ASSERT(type_ == NumberType::SignedInteger);
 
 6567    return value_.asSignedInteger;
 
 6569  JsonUInt asUnsignedInteger()
 const {
 
 6570    ARDUINOJSON_ASSERT(type_ == NumberType::UnsignedInteger);
 
 6571    return value_.asUnsignedInteger;
 
 6573  float asFloat()
 const {
 
 6574    ARDUINOJSON_ASSERT(type_ == NumberType::Float);
 
 6575    return value_.asFloat;
 
 6577#if ARDUINOJSON_USE_DOUBLE 
 6578  double asDouble()
 const {
 
 6579    ARDUINOJSON_ASSERT(type_ == NumberType::Double);
 
 6580    return value_.asDouble;
 
 6584inline Number parseNumber(
const char* s) {
 
 6585  typedef FloatTraits<JsonFloat> traits;
 
 6586  typedef largest_type<traits::mantissa_type, JsonUInt> mantissa_t;
 
 6587  typedef traits::exponent_type exponent_t;
 
 6588  ARDUINOJSON_ASSERT(s != 0);
 
 6589  bool is_negative = 
false;
 
 6599#if ARDUINOJSON_ENABLE_NAN 
 6600  if (*s == 
'n' || *s == 
'N') {
 
 6601    return Number(traits::nan());
 
 6604#if ARDUINOJSON_ENABLE_INFINITY 
 6605  if (*s == 
'i' || *s == 
'I') {
 
 6606    return Number(is_negative ? -traits::inf() : traits::inf());
 
 6609  if (!isdigit(*s) && *s != 
'.')
 
 6611  mantissa_t mantissa = 0;
 
 6612  exponent_t exponent_offset = 0;
 
 6613  const mantissa_t maxUint = JsonUInt(-1);
 
 6614  while (isdigit(*s)) {
 
 6615    uint8_t digit = uint8_t(*s - 
'0');
 
 6616    if (mantissa > maxUint / 10)
 
 6619    if (mantissa > maxUint - digit)
 
 6626      const mantissa_t sintMantissaMax = mantissa_t(1)
 
 6627                                         << (
sizeof(JsonInteger) * 8 - 1);
 
 6628      if (mantissa <= sintMantissaMax) {
 
 6629        return Number(JsonInteger(~mantissa + 1));
 
 6632      return Number(JsonUInt(mantissa));
 
 6635  while (mantissa > traits::mantissa_max) {
 
 6639  while (isdigit(*s)) {
 
 6645    while (isdigit(*s)) {
 
 6646      if (mantissa < traits::mantissa_max / 10) {
 
 6647        mantissa = mantissa * 10 + uint8_t(*s - 
'0');
 
 6654  if (*s == 
'e' || *s == 
'E') {
 
 6656    bool negative_exponent = 
false;
 
 6658      negative_exponent = 
true;
 
 6660    } 
else if (*s == 
'+') {
 
 6663    while (isdigit(*s)) {
 
 6664      exponent = exponent * 10 + (*s - 
'0');
 
 6665      if (exponent + exponent_offset > traits::exponent_max) {
 
 6666        if (negative_exponent)
 
 6667          return Number(is_negative ? -0.0f : 0.0f);
 
 6669          return Number(is_negative ? -traits::inf() : traits::inf());
 
 6673    if (negative_exponent)
 
 6674      exponent = -exponent;
 
 6676  exponent += exponent_offset;
 
 6679#if ARDUINOJSON_USE_DOUBLE 
 6680  bool isDouble = exponent < -FloatTraits<float>::exponent_max ||
 
 6681                  exponent > FloatTraits<float>::exponent_max ||
 
 6682                  mantissa > FloatTraits<float>::mantissa_max;
 
 6684    auto final_result = make_float(
double(mantissa), exponent);
 
 6685    return Number(is_negative ? -final_result : final_result);
 
 6689    auto final_result = make_float(
float(mantissa), exponent);
 
 6690    return Number(is_negative ? -final_result : final_result);
 
 6693template <
typename T>
 
 6694inline T parseNumber(
const char* s) {
 
 6695  return parseNumber(s).convertTo<T>();
 
 6697template <
typename TReader>
 
 6698class JsonDeserializer {
 
 6700  JsonDeserializer(ResourceManager* resources, TReader reader)
 
 6701      : stringBuilder_(resources),
 
 6702        foundSomething_(false),
 
 6704        resources_(resources) {}
 
 6705  template <
typename TFilter>
 
 6706  DeserializationError parse(VariantData& variant, TFilter filter,
 
 6707                             DeserializationOption::NestingLimit nestingLimit) {
 
 6708    DeserializationError::Code err;
 
 6709    err = parseVariant(variant, filter, nestingLimit);
 
 6710    if (!err && latch_.last() != 0 && variant.isFloat()) {
 
 6711      return DeserializationError::InvalidInput;
 
 6717    return latch_.current();
 
 6722  bool eat(
char charToSkip) {
 
 6723    if (current() != charToSkip)
 
 6728  template <
typename TFilter>
 
 6729  DeserializationError::Code parseVariant(
 
 6730      VariantData& variant, TFilter filter,
 
 6731      DeserializationOption::NestingLimit nestingLimit) {
 
 6732    DeserializationError::Code err;
 
 6733    err = skipSpacesAndComments();
 
 6736    switch (current()) {
 
 6738        if (filter.allowArray())
 
 6739          return parseArray(variant.toArray(), filter, nestingLimit);
 
 6741          return skipArray(nestingLimit);
 
 6743        if (filter.allowObject())
 
 6744          return parseObject(variant.toObject(), filter, nestingLimit);
 
 6746          return skipObject(nestingLimit);
 
 6749        if (filter.allowValue())
 
 6750          return parseStringValue(variant);
 
 6752          return skipQuotedString();
 
 6754        if (filter.allowValue())
 
 6755          variant.setBoolean(
true);
 
 6756        return skipKeyword(
"true");
 
 6758        if (filter.allowValue())
 
 6759          variant.setBoolean(
false);
 
 6760        return skipKeyword(
"false");
 
 6762        return skipKeyword(
"null");
 
 6764        if (filter.allowValue())
 
 6765          return parseNumericValue(variant);
 
 6767          return skipNumericValue();
 
 6770  DeserializationError::Code skipVariant(
 
 6771      DeserializationOption::NestingLimit nestingLimit) {
 
 6772    DeserializationError::Code err;
 
 6773    err = skipSpacesAndComments();
 
 6776    switch (current()) {
 
 6778        return skipArray(nestingLimit);
 
 6780        return skipObject(nestingLimit);
 
 6783        return skipQuotedString();
 
 6785        return skipKeyword(
"true");
 
 6787        return skipKeyword(
"false");
 
 6789        return skipKeyword(
"null");
 
 6791        return skipNumericValue();
 
 6794  template <
typename TFilter>
 
 6795  DeserializationError::Code parseArray(
 
 6796      ArrayData& array, TFilter filter,
 
 6797      DeserializationOption::NestingLimit nestingLimit) {
 
 6798    DeserializationError::Code err;
 
 6799    if (nestingLimit.reached())
 
 6800      return DeserializationError::TooDeep;
 
 6801    ARDUINOJSON_ASSERT(current() == 
'[');
 
 6803    err = skipSpacesAndComments();
 
 6807      return DeserializationError::Ok;
 
 6808    TFilter elementFilter = filter[0UL];
 
 6810      if (elementFilter.allow()) {
 
 6811        VariantData* value = array.addElement(resources_);
 
 6813          return DeserializationError::NoMemory;
 
 6814        err = parseVariant(*value, elementFilter, nestingLimit.decrement());
 
 6818        err = skipVariant(nestingLimit.decrement());
 
 6822      err = skipSpacesAndComments();
 
 6826        return DeserializationError::Ok;
 
 6828        return DeserializationError::InvalidInput;
 
 6831  DeserializationError::Code skipArray(
 
 6832      DeserializationOption::NestingLimit nestingLimit) {
 
 6833    DeserializationError::Code err;
 
 6834    if (nestingLimit.reached())
 
 6835      return DeserializationError::TooDeep;
 
 6836    ARDUINOJSON_ASSERT(current() == 
'[');
 
 6839      err = skipVariant(nestingLimit.decrement());
 
 6842      err = skipSpacesAndComments();
 
 6846        return DeserializationError::Ok;
 
 6848        return DeserializationError::InvalidInput;
 
 6851  template <
typename TFilter>
 
 6852  DeserializationError::Code parseObject(
 
 6853      ObjectData& 
object, TFilter filter,
 
 6854      DeserializationOption::NestingLimit nestingLimit) {
 
 6855    DeserializationError::Code err;
 
 6856    if (nestingLimit.reached())
 
 6857      return DeserializationError::TooDeep;
 
 6858    ARDUINOJSON_ASSERT(current() == 
'{');
 
 6860    err = skipSpacesAndComments();
 
 6864      return DeserializationError::Ok;
 
 6869      err = skipSpacesAndComments();
 
 6873        return DeserializationError::InvalidInput;
 
 6874      JsonString key = stringBuilder_.str();
 
 6875      TFilter memberFilter = filter[key.c_str()];
 
 6876      if (memberFilter.allow()) {
 
 6877        auto member = 
object.getMember(adaptString(key.c_str()), resources_);
 
 6879          auto savedKey = stringBuilder_.save();
 
 6880          member = 
object.addMember(savedKey, resources_);
 
 6882            return DeserializationError::NoMemory;
 
 6884          member->clear(resources_);
 
 6886        err = parseVariant(*member, memberFilter, nestingLimit.decrement());
 
 6890        err = skipVariant(nestingLimit.decrement());
 
 6894      err = skipSpacesAndComments();
 
 6898        return DeserializationError::Ok;
 
 6900        return DeserializationError::InvalidInput;
 
 6901      err = skipSpacesAndComments();
 
 6906  DeserializationError::Code skipObject(
 
 6907      DeserializationOption::NestingLimit nestingLimit) {
 
 6908    DeserializationError::Code err;
 
 6909    if (nestingLimit.reached())
 
 6910      return DeserializationError::TooDeep;
 
 6911    ARDUINOJSON_ASSERT(current() == 
'{');
 
 6913    err = skipSpacesAndComments();
 
 6917      return DeserializationError::Ok;
 
 6922      err = skipSpacesAndComments();
 
 6926        return DeserializationError::InvalidInput;
 
 6927      err = skipVariant(nestingLimit.decrement());
 
 6930      err = skipSpacesAndComments();
 
 6934        return DeserializationError::Ok;
 
 6936        return DeserializationError::InvalidInput;
 
 6937      err = skipSpacesAndComments();
 
 6942  DeserializationError::Code parseKey() {
 
 6943    stringBuilder_.startString();
 
 6944    if (isQuote(current())) {
 
 6945      return parseQuotedString();
 
 6947      return parseNonQuotedString();
 
 6950  DeserializationError::Code parseStringValue(VariantData& variant) {
 
 6951    DeserializationError::Code err;
 
 6952    stringBuilder_.startString();
 
 6953    err = parseQuotedString();
 
 6956    variant.setOwnedString(stringBuilder_.save());
 
 6957    return DeserializationError::Ok;
 
 6959  DeserializationError::Code parseQuotedString() {
 
 6960#if ARDUINOJSON_DECODE_UNICODE 
 6961    Utf16::Codepoint codepoint;
 
 6962    DeserializationError::Code err;
 
 6964    const char stopChar = current();
 
 6972        return DeserializationError::IncompleteInput;
 
 6976          return DeserializationError::IncompleteInput;
 
 6978#if ARDUINOJSON_DECODE_UNICODE 
 6981          err = parseHex4(codeunit);
 
 6984          if (codepoint.append(codeunit))
 
 6985            Utf8::encodeCodepoint(codepoint.value(), stringBuilder_);
 
 6987          stringBuilder_.append(
'\\');
 
 6991        c = EscapeSequence::unescapeChar(c);
 
 6993          return DeserializationError::InvalidInput;
 
 6996      stringBuilder_.append(c);
 
 6998    if (!stringBuilder_.isValid())
 
 6999      return DeserializationError::NoMemory;
 
 7000    return DeserializationError::Ok;
 
 7002  DeserializationError::Code parseNonQuotedString() {
 
 7004    ARDUINOJSON_ASSERT(c);
 
 7005    if (canBeInNonQuotedString(c)) {  
 
 7008        stringBuilder_.append(c);
 
 7010      } 
while (canBeInNonQuotedString(c));
 
 7012      return DeserializationError::InvalidInput;
 
 7014    if (!stringBuilder_.isValid())
 
 7015      return DeserializationError::NoMemory;
 
 7016    return DeserializationError::Ok;
 
 7018  DeserializationError::Code skipKey() {
 
 7019    if (isQuote(current())) {
 
 7020      return skipQuotedString();
 
 7022      return skipNonQuotedString();
 
 7025  DeserializationError::Code skipQuotedString() {
 
 7026    const char stopChar = current();
 
 7034        return DeserializationError::IncompleteInput;
 
 7036        if (current() != 
'\0')
 
 7040    return DeserializationError::Ok;
 
 7042  DeserializationError::Code skipNonQuotedString() {
 
 7044    while (canBeInNonQuotedString(c)) {
 
 7048    return DeserializationError::Ok;
 
 7050  DeserializationError::Code parseNumericValue(VariantData& result) {
 
 7053    while (canBeInNumber(c) && n < 63) {
 
 7059    auto number = parseNumber(buffer_);
 
 7060    switch (number.type()) {
 
 7061      case NumberType::UnsignedInteger:
 
 7062        if (result.setInteger(number.asUnsignedInteger(), resources_))
 
 7063          return DeserializationError::Ok;
 
 7065          return DeserializationError::NoMemory;
 
 7066      case NumberType::SignedInteger:
 
 7067        if (result.setInteger(number.asSignedInteger(), resources_))
 
 7068          return DeserializationError::Ok;
 
 7070          return DeserializationError::NoMemory;
 
 7071      case NumberType::Float:
 
 7072        if (result.setFloat(number.asFloat(), resources_))
 
 7073          return DeserializationError::Ok;
 
 7075          return DeserializationError::NoMemory;
 
 7076#if ARDUINOJSON_USE_DOUBLE 
 7077      case NumberType::Double:
 
 7078        if (result.setFloat(number.asDouble(), resources_))
 
 7079          return DeserializationError::Ok;
 
 7081          return DeserializationError::NoMemory;
 
 7084        return DeserializationError::InvalidInput;
 
 7087  DeserializationError::Code skipNumericValue() {
 
 7089    while (canBeInNumber(c)) {
 
 7093    return DeserializationError::Ok;
 
 7095  DeserializationError::Code parseHex4(uint16_t& result) {
 
 7097    for (uint8_t i = 0; i < 4; ++i) {
 
 7098      char digit = current();
 
 7100        return DeserializationError::IncompleteInput;
 
 7101      uint8_t value = decodeHex(digit);
 
 7103        return DeserializationError::InvalidInput;
 
 7104      result = uint16_t((result << 4) | value);
 
 7107    return DeserializationError::Ok;
 
 7109  static inline bool isBetween(
char c, 
char min, 
char max) {
 
 7110    return min <= c && c <= max;
 
 7112  static inline bool canBeInNumber(
char c) {
 
 7113    return isBetween(c, 
'0', 
'9') || c == 
'+' || c == 
'-' || c == 
'.' ||
 
 7114#if ARDUINOJSON_ENABLE_NAN || ARDUINOJSON_ENABLE_INFINITY 
 7115           isBetween(c, 
'A', 
'Z') || isBetween(c, 
'a', 
'z');
 
 7117           c == 
'e' || c == 
'E';
 
 7120  static inline bool canBeInNonQuotedString(
char c) {
 
 7121    return isBetween(c, 
'0', 
'9') || isBetween(c, 
'_', 
'z') ||
 
 7122           isBetween(c, 
'A', 
'Z');
 
 7124  static inline bool isQuote(
char c) {
 
 7125    return c == 
'\'' || c == 
'\"';
 
 7127  static inline uint8_t decodeHex(
char c) {
 
 7129      return uint8_t(c - 
'0');
 
 7130    c = char(c & ~0x20);  
 
 7131    return uint8_t(c - 
'A' + 10);
 
 7133  DeserializationError::Code skipSpacesAndComments() {
 
 7135      switch (current()) {
 
 7137          return foundSomething_ ? DeserializationError::IncompleteInput
 
 7138                                 : DeserializationError::EmptyInput;
 
 7145#if ARDUINOJSON_ENABLE_COMMENTS 
 7148          switch (current()) {
 
 7151              bool wasStar = 
false;
 
 7155                  return DeserializationError::IncompleteInput;
 
 7156                if (c == 
'/' && wasStar) {
 
 7170                  return DeserializationError::IncompleteInput;
 
 7176              return DeserializationError::InvalidInput;
 
 7181          foundSomething_ = 
true;
 
 7182          return DeserializationError::Ok;
 
 7186  DeserializationError::Code skipKeyword(
const char* s) {
 
 7190        return DeserializationError::IncompleteInput;
 
 7192        return DeserializationError::InvalidInput;
 
 7196    return DeserializationError::Ok;
 
 7198  StringBuilder stringBuilder_;
 
 7199  bool foundSomething_;
 
 7200  Latch<TReader> latch_;
 
 7201  ResourceManager* resources_;
 
 7204ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 7205ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 7206template <
typename TDestination, 
typename... Args>
 
 7207detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
 
 7208                    DeserializationError>
 
 7209deserializeJson(TDestination&& dst, Args&&... 
args) {
 
 7210  using namespace detail;
 
 7211  return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
 
 7212                                       detail::forward<Args>(
args)...);
 
 7214template <
typename TDestination, 
typename TChar, 
typename... Args>
 
 7215detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
 
 7216                    DeserializationError>
 
 7217deserializeJson(TDestination&& dst, TChar* input, Args&&... 
args) {
 
 7218  using namespace detail;
 
 7219  return deserialize<JsonDeserializer>(detail::forward<TDestination>(dst),
 
 7220                                       input, detail::forward<Args>(
args)...);
 
 7222ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 7223ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 7224template <
typename TWriter>
 
 7225class PrettyJsonSerializer : 
public JsonSerializer<TWriter> {
 
 7226  typedef JsonSerializer<TWriter> base;
 
 7228  PrettyJsonSerializer(TWriter writer, 
const ResourceManager* resources)
 
 7229      : base(writer, resources), nesting_(0) {}
 
 7230  size_t visit(
const ArrayData& array) {
 
 7231    auto it = array.createIterator(base::resources_);
 
 7233      base::write(
"[\r\n");
 
 7235      while (!it.done()) {
 
 7237        it->accept(*
this, base::resources_);
 
 7238        it.next(base::resources_);
 
 7239        base::write(it.done() ? 
"\r\n" : 
",\r\n");
 
 7247    return this->bytesWritten();
 
 7249  size_t visit(
const ObjectData& 
object) {
 
 7250    auto it = 
object.createIterator(base::resources_);
 
 7252      base::write(
"{\r\n");
 
 7255      while (!it.done()) {
 
 7258        it->accept(*
this, base::resources_);
 
 7259        it.next(base::resources_);
 
 7263          base::write(it.done() ? 
"\r\n" : 
",\r\n");
 
 7272    return this->bytesWritten();
 
 7277    for (uint8_t i = 0; i < nesting_; i++)
 
 7278      base::write(ARDUINOJSON_TAB);
 
 7282ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 7283ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 7284template <
typename TDestination>
 
 7285detail::enable_if_t<!detail::is_pointer<TDestination>::value, 
size_t>
 
 7286serializeJsonPretty(JsonVariantConst source, TDestination& destination) {
 
 7287  using namespace FLArduinoJson::detail;
 
 7288  return serialize<PrettyJsonSerializer>(source, destination);
 
 7290inline size_t serializeJsonPretty(JsonVariantConst source, 
void* buffer,
 
 7291                                  size_t bufferSize) {
 
 7292  using namespace FLArduinoJson::detail;
 
 7293  return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
 
 7295inline size_t measureJsonPretty(JsonVariantConst source) {
 
 7296  using namespace FLArduinoJson::detail;
 
 7297  return measure<PrettyJsonSerializer>(source);
 
 7299class MsgPackBinary {
 
 7301  MsgPackBinary() : data_(nullptr), size_(0) {}
 
 7302  explicit MsgPackBinary(
const void* c, 
size_t size) : data_(c), size_(size) {}
 
 7303  const void* data()
 const {
 
 7306  size_t size()
 const {
 
 7314struct Converter<MsgPackBinary> : 
private detail::VariantAttorney {
 
 7315  static void toJson(MsgPackBinary src, JsonVariant dst) {
 
 7316    auto data = VariantAttorney::getData(dst);
 
 7319    auto resources = getResourceManager(dst);
 
 7320    data->clear(resources);
 
 7322      size_t headerSize = src.size() >= 0x10000 ? 5
 
 7323                          : src.size() >= 0x100 ? 3
 
 7325      auto str = resources->createString(src.size() + headerSize);
 
 7327        resources->saveString(str);
 
 7328        auto ptr = 
reinterpret_cast<uint8_t*
>(str->data);
 
 7329        switch (headerSize) {
 
 7331            ptr[0] = uint8_t(0xc4);
 
 7332            ptr[1] = uint8_t(src.size() & 0xff);
 
 7335            ptr[0] = uint8_t(0xc5);
 
 7336            ptr[1] = uint8_t(src.size() >> 8 & 0xff);
 
 7337            ptr[2] = uint8_t(src.size() & 0xff);
 
 7340            ptr[0] = uint8_t(0xc6);
 
 7341            ptr[1] = uint8_t(src.size() >> 24 & 0xff);
 
 7342            ptr[2] = uint8_t(src.size() >> 16 & 0xff);
 
 7343            ptr[3] = uint8_t(src.size() >> 8 & 0xff);
 
 7344            ptr[4] = uint8_t(src.size() & 0xff);
 
 7347            ARDUINOJSON_ASSERT(
false);
 
 7349        memcpy(ptr + headerSize, src.data(), src.size());
 
 7350        data->setRawString(str);
 
 7355  static MsgPackBinary fromJson(JsonVariantConst src) {
 
 7356    auto data = getData(src);
 
 7359    auto rawstr = data->asRawString();
 
 7360    auto p = 
reinterpret_cast<const uint8_t*
>(rawstr.c_str());
 
 7361    auto n = rawstr.size();
 
 7362    if (n >= 2 && p[0] == 0xc4) {  
 
 7365        return MsgPackBinary(p + 2, size);
 
 7366    } 
else if (n >= 3 && p[0] == 0xc5) {  
 
 7367      size_t size = 
size_t(p[1] << 8) | p[2];
 
 7369        return MsgPackBinary(p + 3, size);
 
 7370    } 
else if (n >= 5 && p[0] == 0xc6) {  
 
 7374        return MsgPackBinary(p + 5, size);
 
 7378  static bool checkJson(JsonVariantConst src) {
 
 7379    return fromJson(src).data() != 
nullptr;
 
 7382ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 7383ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 7386  StringBuffer(ResourceManager* resources) : resources_(resources) {}
 
 7389      resources_->destroyString(node_);
 
 7391  char* reserve(
size_t capacity) {
 
 7392    if (node_ && capacity > node_->length) {
 
 7393      resources_->destroyString(node_);
 
 7397      node_ = resources_->createString(capacity);
 
 7401    node_->data[capacity] = 0;  
 
 7404  StringNode* save() {
 
 7405    ARDUINOJSON_ASSERT(node_ != 
nullptr);
 
 7406    node_->data[size_] = 0;
 
 7407    auto node = resources_->getString(adaptString(node_->data, size_));
 
 7412    if (node_->length != size_) {
 
 7413      node = resources_->resizeString(node_, size_);
 
 7414      ARDUINOJSON_ASSERT(node != 
nullptr);  
 
 7419    resources_->saveString(node);
 
 7422  JsonString str()
 const {
 
 7423    ARDUINOJSON_ASSERT(node_ != 
nullptr);
 
 7424    return JsonString(node_->data, node_->length, JsonString::Copied);
 
 7427  ResourceManager* resources_;
 
 7428  StringNode* node_ = 
nullptr;
 
 7431#if ARDUINOJSON_LITTLE_ENDIAN 
 7432inline void swapBytes(uint8_t& a, uint8_t& b) {
 
 7437inline void fixEndianness(uint8_t* p, integral_constant<size_t, 8>) {
 
 7438  swapBytes(p[0], p[7]);
 
 7439  swapBytes(p[1], p[6]);
 
 7440  swapBytes(p[2], p[5]);
 
 7441  swapBytes(p[3], p[4]);
 
 7443inline void fixEndianness(uint8_t* p, integral_constant<size_t, 4>) {
 
 7444  swapBytes(p[0], p[3]);
 
 7445  swapBytes(p[1], p[2]);
 
 7447inline void fixEndianness(uint8_t* p, integral_constant<size_t, 2>) {
 
 7448  swapBytes(p[0], p[1]);
 
 7450inline void fixEndianness(uint8_t*, integral_constant<size_t, 1>) {}
 
 7451template <
typename T>
 
 7452inline void fixEndianness(T& value) {
 
 7453  fixEndianness(
reinterpret_cast<uint8_t*
>(&value),
 
 7454                integral_constant<
size_t, 
sizeof(T)>());
 
 7457template <
typename T>
 
 7458inline void fixEndianness(T&) {}
 
 7460inline void doubleToFloat(
const uint8_t d[8], uint8_t f[4]) {
 
 7461  f[0] = uint8_t((d[0] & 0xC0) | (d[0] << 3 & 0x3f) | (d[1] >> 5));
 
 7462  f[1] = uint8_t((d[1] << 3) | (d[2] >> 5));
 
 7463  f[2] = uint8_t((d[2] << 3) | (d[3] >> 5));
 
 7464  f[3] = uint8_t((d[3] << 3) | (d[4] >> 5));
 
 7466template <
typename TReader>
 
 7467class MsgPackDeserializer {
 
 7469  MsgPackDeserializer(ResourceManager* resources, TReader reader)
 
 7470      : resources_(resources),
 
 7472        stringBuffer_(resources),
 
 7473        foundSomething_(false) {}
 
 7474  template <
typename TFilter>
 
 7475  DeserializationError parse(VariantData& variant, TFilter filter,
 
 7476                             DeserializationOption::NestingLimit nestingLimit) {
 
 7477    DeserializationError::Code err;
 
 7478    err = parseVariant(&variant, filter, nestingLimit);
 
 7479    return foundSomething_ ? err : DeserializationError::EmptyInput;
 
 7482  template <
typename TFilter>
 
 7483  DeserializationError::Code parseVariant(
 
 7484      VariantData* variant, TFilter filter,
 
 7485      DeserializationOption::NestingLimit nestingLimit) {
 
 7486    DeserializationError::Code err;
 
 7488    err = readBytes(header, 1);
 
 7491    const uint8_t& code = header[0];
 
 7492    foundSomething_ = 
true;
 
 7493    bool allowValue = filter.allowValue();
 
 7495      ARDUINOJSON_ASSERT(variant != 0);
 
 7497    if (code >= 0xcc && code <= 0xd3) {
 
 7498      auto width = uint8_t(1U << ((code - 0xcc) % 4));
 
 7500        return readInteger(variant, width, code >= 0xd0);
 
 7502        return skipBytes(width);
 
 7506        return DeserializationError::Ok;
 
 7508        return DeserializationError::InvalidInput;
 
 7512          variant->setBoolean(code == 0xc3);
 
 7513        return DeserializationError::Ok;
 
 7516          return readFloat<float>(variant);
 
 7518          return skipBytes(4);
 
 7521          return readDouble<double>(variant);
 
 7523          return skipBytes(8);
 
 7525    if (code <= 0x7f || code >= 0xe0) {  
 
 7527        variant->setInteger(
static_cast<int8_t
>(code), resources_);
 
 7528      return DeserializationError::Ok;
 
 7530    uint8_t sizeBytes = 0;
 
 7532    bool isExtension = code >= 0xc7 && code <= 0xc9;
 
 7554    if (code >= 0xd4 && code <= 0xd8) {  
 
 7555      size = 
size_t(1) << (code - 0xd4);
 
 7558    switch (code & 0xf0) {
 
 7564    switch (code & 0xe0) {
 
 7570      err = readBytes(header + 1, sizeBytes);
 
 7573      uint32_t size32 = 0;
 
 7574      for (uint8_t i = 0; i < sizeBytes; i++)
 
 7575        size32 = (size32 << 8) | header[i + 1];
 
 7578        return DeserializationError::NoMemory;  
 
 7580    if (code == 0xdc || code == 0xdd || (code & 0xf0) == 0x90)
 
 7581      return readArray(variant, size, filter, nestingLimit);
 
 7582    if (code == 0xde || code == 0xdf || (code & 0xf0) == 0x80)
 
 7583      return readObject(variant, size, filter, nestingLimit);
 
 7584    if (code == 0xd9 || code == 0xda || code == 0xdb || (code & 0xe0) == 0xa0) {
 
 7586        return readString(variant, size);
 
 7588        return skipBytes(size);
 
 7593      return readRawString(variant, header, uint8_t(1 + sizeBytes), size);
 
 7595      return skipBytes(size);
 
 7597  DeserializationError::Code readByte(uint8_t& value) {
 
 7598    int c = reader_.read();
 
 7600      return DeserializationError::IncompleteInput;
 
 7601    value = 
static_cast<uint8_t
>(c);
 
 7602    return DeserializationError::Ok;
 
 7604  DeserializationError::Code readBytes(
void* p, 
size_t n) {
 
 7605    if (reader_.readBytes(
reinterpret_cast<char*
>(p), n) == n)
 
 7606      return DeserializationError::Ok;
 
 7607    return DeserializationError::IncompleteInput;
 
 7609  template <
typename T>
 
 7610  DeserializationError::Code readBytes(T& value) {
 
 7611    return readBytes(&value, 
sizeof(value));
 
 7613  DeserializationError::Code skipBytes(
size_t n) {
 
 7615      if (reader_.read() < 0)
 
 7616        return DeserializationError::IncompleteInput;
 
 7618    return DeserializationError::Ok;
 
 7620  DeserializationError::Code readInteger(VariantData* variant, uint8_t width,
 
 7623    auto err = readBytes(buffer, width);
 
 7627      int64_t signedValue;
 
 7628      uint64_t unsignedValue;
 
 7631      signedValue = 
static_cast<int8_t
>(buffer[0]);  
 
 7633      unsignedValue = 
static_cast<uint8_t
>(buffer[0]);
 
 7634    for (uint8_t i = 1; i < width; i++)
 
 7635      unsignedValue = (unsignedValue << 8) | buffer[i];
 
 7637      auto truncatedValue = 
static_cast<JsonInteger
>(signedValue);
 
 7638      if (truncatedValue == signedValue) {
 
 7639        if (!variant->setInteger(truncatedValue, resources_))
 
 7640          return DeserializationError::NoMemory;
 
 7643      auto truncatedValue = 
static_cast<JsonUInt
>(unsignedValue);
 
 7644      if (truncatedValue == unsignedValue)
 
 7645        if (!variant->setInteger(truncatedValue, resources_))
 
 7646          return DeserializationError::NoMemory;
 
 7648    return DeserializationError::Ok;
 
 7650  template <
typename T>
 
 7651  enable_if_t<
sizeof(T) == 4, DeserializationError::Code> readFloat(
 
 7652      VariantData* variant) {
 
 7653    DeserializationError::Code err;
 
 7655    err = readBytes(value);
 
 7658    fixEndianness(value);
 
 7659    variant->setFloat(value, resources_);
 
 7660    return DeserializationError::Ok;
 
 7662  template <
typename T>
 
 7663  enable_if_t<
sizeof(T) == 8, DeserializationError::Code> readDouble(
 
 7664      VariantData* variant) {
 
 7665    DeserializationError::Code err;
 
 7667    err = readBytes(value);
 
 7670    fixEndianness(value);
 
 7671    if (variant->setFloat(value, resources_))
 
 7672      return DeserializationError::Ok;
 
 7674      return DeserializationError::NoMemory;
 
 7676  template <
typename T>
 
 7677  enable_if_t<
sizeof(T) == 4, DeserializationError::Code> readDouble(
 
 7678      VariantData* variant) {
 
 7679    DeserializationError::Code err;
 
 7682    uint8_t* o = 
reinterpret_cast<uint8_t*
>(&value);
 
 7683    err = readBytes(i, 8);
 
 7686    doubleToFloat(i, o);
 
 7687    fixEndianness(value);
 
 7688    variant->setFloat(value, resources_);
 
 7689    return DeserializationError::Ok;
 
 7691  DeserializationError::Code readString(VariantData* variant, 
size_t n) {
 
 7692    DeserializationError::Code err;
 
 7693    err = readString(n);
 
 7696    variant->setOwnedString(stringBuffer_.save());
 
 7697    return DeserializationError::Ok;
 
 7699  DeserializationError::Code readString(
size_t n) {
 
 7700    char* p = stringBuffer_.reserve(n);
 
 7702      return DeserializationError::NoMemory;
 
 7703    return readBytes(p, n);
 
 7705  DeserializationError::Code readRawString(VariantData* variant,
 
 7707                                           uint8_t headerSize, 
size_t n) {
 
 7708    auto totalSize = 
size_t(headerSize + n);
 
 7710      return DeserializationError::NoMemory;  
 
 7711    char* p = stringBuffer_.reserve(totalSize);
 
 7713      return DeserializationError::NoMemory;
 
 7714    memcpy(p, header, headerSize);
 
 7715    auto err = readBytes(p + headerSize, n);
 
 7718    variant->setRawString(stringBuffer_.save());
 
 7719    return DeserializationError::Ok;
 
 7721  template <
typename TFilter>
 
 7722  DeserializationError::Code readArray(
 
 7723      VariantData* variant, 
size_t n, TFilter filter,
 
 7724      DeserializationOption::NestingLimit nestingLimit) {
 
 7725    DeserializationError::Code err;
 
 7726    if (nestingLimit.reached())
 
 7727      return DeserializationError::TooDeep;
 
 7728    bool allowArray = filter.allowArray();
 
 7731      ARDUINOJSON_ASSERT(variant != 0);
 
 7732      array = &variant->toArray();
 
 7736    TFilter elementFilter = filter[0U];
 
 7739      if (elementFilter.allow()) {
 
 7740        ARDUINOJSON_ASSERT(array != 0);
 
 7741        value = array->addElement(resources_);
 
 7743          return DeserializationError::NoMemory;
 
 7747      err = parseVariant(value, elementFilter, nestingLimit.decrement());
 
 7751    return DeserializationError::Ok;
 
 7753  template <
typename TFilter>
 
 7754  DeserializationError::Code readObject(
 
 7755      VariantData* variant, 
size_t n, TFilter filter,
 
 7756      DeserializationOption::NestingLimit nestingLimit) {
 
 7757    DeserializationError::Code err;
 
 7758    if (nestingLimit.reached())
 
 7759      return DeserializationError::TooDeep;
 
 7761    if (filter.allowObject()) {
 
 7762      ARDUINOJSON_ASSERT(variant != 0);
 
 7763      object = &variant->toObject();
 
 7771      JsonString key = stringBuffer_.str();
 
 7772      TFilter memberFilter = filter[key.c_str()];
 
 7773      VariantData* member;
 
 7774      if (memberFilter.allow()) {
 
 7775        ARDUINOJSON_ASSERT(
object != 0);
 
 7776        auto savedKey = stringBuffer_.save();
 
 7777        member = 
object->addMember(savedKey, resources_);
 
 7779          return DeserializationError::NoMemory;
 
 7783      err = parseVariant(member, memberFilter, nestingLimit.decrement());
 
 7787    return DeserializationError::Ok;
 
 7789  DeserializationError::Code readKey() {
 
 7790    DeserializationError::Code err;
 
 7792    err = readByte(code);
 
 7795    if ((code & 0xe0) == 0xa0)
 
 7796      return readString(code & 0x1f);
 
 7797    if (code >= 0xd9 && code <= 0xdb) {
 
 7798      uint8_t sizeBytes = uint8_t(1U << (code - 0xd9));
 
 7800      for (uint8_t i = 0; i < sizeBytes; i++) {
 
 7801        err = readByte(code);
 
 7804        size = (size << 8) | code;
 
 7806      return readString(size);
 
 7808    return DeserializationError::InvalidInput;
 
 7810  ResourceManager* resources_;
 
 7812  StringBuffer stringBuffer_;
 
 7813  bool foundSomething_;
 
 7815ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 7816ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 7817template <
typename TDestination, 
typename... Args>
 
 7818detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
 
 7819                    DeserializationError>
 
 7820deserializeMsgPack(TDestination&& dst, Args&&... 
args) {
 
 7821  using namespace detail;
 
 7822  return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
 
 7823                                          detail::forward<Args>(
args)...);
 
 7825template <
typename TDestination, 
typename TChar, 
typename... Args>
 
 7826detail::enable_if_t<detail::is_deserialize_destination<TDestination>::value,
 
 7827                    DeserializationError>
 
 7828deserializeMsgPack(TDestination&& dst, TChar* input, Args&&... 
args) {
 
 7829  using namespace detail;
 
 7830  return deserialize<MsgPackDeserializer>(detail::forward<TDestination>(dst),
 
 7832                                          detail::forward<Args>(
args)...);
 
 7834class MsgPackExtension {
 
 7836  MsgPackExtension() : data_(nullptr), size_(0), type_(0) {}
 
 7837  explicit MsgPackExtension(int8_t type, 
const void* data, 
size_t size)
 
 7838      : data_(data), size_(size), type_(type) {}
 
 7839  int8_t type()
 const {
 
 7842  const void* data()
 const {
 
 7845  size_t size()
 const {
 
 7854struct Converter<MsgPackExtension> : 
private detail::VariantAttorney {
 
 7855  static void toJson(MsgPackExtension src, JsonVariant dst) {
 
 7856    auto data = VariantAttorney::getData(dst);
 
 7859    auto resources = getResourceManager(dst);
 
 7860    data->clear(resources);
 
 7862      uint8_t format, sizeBytes;
 
 7863      if (src.size() >= 0x10000) {
 
 7866      } 
else if (src.size() >= 0x100) {
 
 7869      } 
else if (src.size() == 16) {
 
 7872      } 
else if (src.size() == 8) {
 
 7875      } 
else if (src.size() == 4) {
 
 7878      } 
else if (src.size() == 2) {
 
 7881      } 
else if (src.size() == 1) {
 
 7888      auto str = resources->createString(src.size() + 2 + sizeBytes);
 
 7890        resources->saveString(str);
 
 7891        auto ptr = 
reinterpret_cast<uint8_t*
>(str->data);
 
 7892        *ptr++ = uint8_t(format);
 
 7893        for (uint8_t i = 0; i < sizeBytes; i++)
 
 7894          *ptr++ = uint8_t(src.size() >> (sizeBytes - i - 1) * 8 & 0xff);
 
 7895        *ptr++ = uint8_t(src.type());
 
 7896        memcpy(ptr, src.data(), src.size());
 
 7897        data->setRawString(str);
 
 7902  static MsgPackExtension fromJson(JsonVariantConst src) {
 
 7903    auto data = getData(src);
 
 7906    auto rawstr = data->asRawString();
 
 7907    if (rawstr.size() == 0)
 
 7909    auto p = 
reinterpret_cast<const uint8_t*
>(rawstr.c_str());
 
 7910    size_t payloadSize = 0;
 
 7911    uint8_t headerSize = 0;
 
 7912    const uint8_t& code = p[0];
 
 7913    if (code >= 0xd4 && code <= 0xd8) {  
 
 7915      payloadSize = 
size_t(1) << (code - 0xd4);
 
 7917    if (code >= 0xc7 && code <= 0xc9) {
 
 7918      uint8_t sizeBytes = uint8_t(1 << (code - 0xc7));
 
 7919      for (uint8_t i = 0; i < sizeBytes; i++)
 
 7920        payloadSize = (payloadSize << 8) | p[1 + i];
 
 7921      headerSize = uint8_t(2 + sizeBytes);
 
 7923    if (rawstr.size() == headerSize + payloadSize)
 
 7924      return MsgPackExtension(int8_t(p[headerSize - 1]), p + headerSize,
 
 7928  static bool checkJson(JsonVariantConst src) {
 
 7929    return fromJson(src).data() != 
nullptr;
 
 7932ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 7933ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
 
 7934template <
typename TWriter>
 
 7935class MsgPackSerializer : 
public VariantDataVisitor<size_t> {
 
 7937  static const bool producesText = 
false;
 
 7938  MsgPackSerializer(TWriter writer, 
const ResourceManager* resources)
 
 7939      : writer_(writer), resources_(resources) {}
 
 7940  template <
typename T>
 
 7941  enable_if_t<is_floating_point<T>::value && 
sizeof(T) == 4, 
size_t> visit(
 
 7943    if (canConvertNumber<JsonInteger>(value32)) {
 
 7944      JsonInteger truncatedValue = JsonInteger(value32);
 
 7945      if (value32 == T(truncatedValue))
 
 7946        return visit(truncatedValue);
 
 7949    writeInteger(value32);
 
 7950    return bytesWritten();
 
 7952  template <
typename T>
 
 7953  ARDUINOJSON_NO_SANITIZE(
"float-cast-overflow")
 
 7954  enable_if_t<is_floating_point<T>::value && sizeof(T) == 8, 
size_t> visit(
 
 7956    float value32 = float(value64);
 
 7957    if (value32 == value64)
 
 7958      return visit(value32);
 
 7960    writeInteger(value64);
 
 7961    return bytesWritten();
 
 7963  size_t visit(
const ArrayData& array) {
 
 7964    size_t n = array.size(resources_);
 
 7966      writeByte(uint8_t(0x90 + n));
 
 7967    } 
else if (n < 0x10000) {
 
 7969      writeInteger(uint16_t(n));
 
 7972      writeInteger(uint32_t(n));
 
 7974    auto slotId = array.head();
 
 7975    while (slotId != NULL_SLOT) {
 
 7976      auto slot = resources_->getVariant(slotId);
 
 7977      slot->accept(*
this, resources_);
 
 7978      slotId = slot->next();
 
 7980    return bytesWritten();
 
 7982  size_t visit(
const ObjectData& 
object) {
 
 7983    size_t n = 
object.size(resources_);
 
 7985      writeByte(uint8_t(0x80 + n));
 
 7986    } 
else if (n < 0x10000) {
 
 7988      writeInteger(uint16_t(n));
 
 7991      writeInteger(uint32_t(n));
 
 7993    auto slotId = 
object.head();
 
 7994    while (slotId != NULL_SLOT) {
 
 7995      auto slot = resources_->getVariant(slotId);
 
 7996      slot->accept(*
this, resources_);
 
 7997      slotId = slot->next();
 
 7999    return bytesWritten();
 
 8001  size_t visit(
const char* value) {
 
 8002    return visit(JsonString(value));
 
 8004  size_t visit(JsonString value) {
 
 8005    ARDUINOJSON_ASSERT(value != NULL);
 
 8006    auto n = value.size();
 
 8008      writeByte(uint8_t(0xA0 + n));
 
 8009    } 
else if (n < 0x100) {
 
 8011      writeInteger(uint8_t(n));
 
 8012    } 
else if (n < 0x10000) {
 
 8014      writeInteger(uint16_t(n));
 
 8017      writeInteger(uint32_t(n));
 
 8019    writeBytes(
reinterpret_cast<const uint8_t*
>(value.c_str()), n);
 
 8020    return bytesWritten();
 
 8022  size_t visit(RawString value) {
 
 8023    writeBytes(
reinterpret_cast<const uint8_t*
>(value.data()), value.size());
 
 8024    return bytesWritten();
 
 8026  size_t visit(JsonInteger value) {
 
 8028      visit(
static_cast<JsonUInt
>(value));
 
 8029    } 
else if (value >= -0x20) {
 
 8030      writeInteger(int8_t(value));
 
 8031    } 
else if (value >= -0x80) {
 
 8033      writeInteger(int8_t(value));
 
 8034    } 
else if (value >= -0x8000) {
 
 8036      writeInteger(int16_t(value));
 
 8038#if ARDUINOJSON_USE_LONG_LONG 
 8039    else if (value >= -0x80000000LL)
 
 8045      writeInteger(int32_t(value));
 
 8047#if ARDUINOJSON_USE_LONG_LONG 
 8050      writeInteger(int64_t(value));
 
 8053    return bytesWritten();
 
 8055  size_t visit(JsonUInt value) {
 
 8056    if (value <= 0x7F) {
 
 8057      writeInteger(uint8_t(value));
 
 8058    } 
else if (value <= 0xFF) {
 
 8060      writeInteger(uint8_t(value));
 
 8061    } 
else if (value <= 0xFFFF) {
 
 8063      writeInteger(uint16_t(value));
 
 8065#if ARDUINOJSON_USE_LONG_LONG 
 8066    else if (value <= 0xFFFFFFFF)
 
 8072      writeInteger(uint32_t(value));
 
 8074#if ARDUINOJSON_USE_LONG_LONG 
 8077      writeInteger(uint64_t(value));
 
 8080    return bytesWritten();
 
 8082  size_t visit(
bool value) {
 
 8083    writeByte(value ? 0xC3 : 0xC2);
 
 8084    return bytesWritten();
 
 8086  size_t visit(nullptr_t) {
 
 8088    return bytesWritten();
 
 8091  size_t bytesWritten()
 const {
 
 8092    return writer_.count();
 
 8094  void writeByte(uint8_t c) {
 
 8097  void writeBytes(
const uint8_t* p, 
size_t n) {
 
 8098    writer_.write(p, n);
 
 8100  template <
typename T>
 
 8101  void writeInteger(T value) {
 
 8102    fixEndianness(value);
 
 8103    writeBytes(
reinterpret_cast<uint8_t*
>(&value), 
sizeof(value));
 
 8105  CountingDecorator<TWriter> writer_;
 
 8106  const ResourceManager* resources_;
 
 8108ARDUINOJSON_END_PRIVATE_NAMESPACE
 
 8109ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 8110template <
typename TDestination>
 
 8111detail::enable_if_t<!detail::is_pointer<TDestination>::value, 
size_t>
 
 8112serializeMsgPack(JsonVariantConst source, TDestination& output) {
 
 8113  using namespace FLArduinoJson::detail;
 
 8114  return serialize<MsgPackSerializer>(source, output);
 
 8116inline size_t serializeMsgPack(JsonVariantConst source, 
void* output,
 
 8118  using namespace FLArduinoJson::detail;
 
 8119  return serialize<MsgPackSerializer>(source, output, size);
 
 8121inline size_t measureMsgPack(JsonVariantConst source) {
 
 8122  using namespace FLArduinoJson::detail;
 
 8123  return measure<MsgPackSerializer>(source);
 
 8125ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 8126#ifdef ARDUINOJSON_SLOT_OFFSET_SIZE 
 8127#error ARDUINOJSON_SLOT_OFFSET_SIZE has been removed, use ARDUINOJSON_SLOT_ID_SIZE instead 
 8129#ifdef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 
 8130#warning "ARDUINOJSON_ENABLE_STRING_DEDUPLICATION has been removed, string deduplication is now always enabled" 
 8133#define ARDUINOJSON_PRAGMA(x) _Pragma(#x) 
 8134#define ARDUINOJSON_COMPILE_ERROR(msg) ARDUINOJSON_PRAGMA(GCC error msg) 
 8135#define ARDUINOJSON_STRINGIFY(S) #S 
 8136#define ARDUINOJSON_DEPRECATION_ERROR(X, Y) \ 
 8137  ARDUINOJSON_COMPILE_ERROR(ARDUINOJSON_STRINGIFY(X is a Y from FLArduinoJson 5. Please see https:/\/arduinojson.org/v7/upgrade-from-v5/ to learn how to upgrade to FLArduinoJson 7)) 
 8138#define StaticJsonBuffer ARDUINOJSON_DEPRECATION_ERROR(StaticJsonBuffer, class) 
 8139#define DynamicJsonBuffer ARDUINOJSON_DEPRECATION_ERROR(DynamicJsonBuffer, class) 
 8140#define JsonBuffer ARDUINOJSON_DEPRECATION_ERROR(JsonBuffer, class) 
 8141#define RawJson ARDUINOJSON_DEPRECATION_ERROR(RawJson, function) 
 8142#define ARDUINOJSON_NAMESPACE _Pragma ("GCC warning \"ARDUINOJSON_NAMESPACE is deprecated, use ArduinoJson instead\"") FLArduinoJson 
 8143#define JSON_ARRAY_SIZE(N) _Pragma ("GCC warning \"JSON_ARRAY_SIZE is deprecated, you don't need to compute the size anymore\"") (FLArduinoJson::detail::sizeofArray(N)) 
 8144#define JSON_OBJECT_SIZE(N) _Pragma ("GCC warning \"JSON_OBJECT_SIZE is deprecated, you don't need to compute the size anymore\"") (FLArduinoJson::detail::sizeofObject(N)) 
 8145#define JSON_STRING_SIZE(N) _Pragma ("GCC warning \"JSON_STRING_SIZE is deprecated, you don't need to compute the size anymore\"") (N+1) 
 8147#define JSON_ARRAY_SIZE(N) (FLArduinoJson::detail::sizeofArray(N)) 
 8148#define JSON_OBJECT_SIZE(N) (FLArduinoJson::detail::sizeofObject(N)) 
 8149#define JSON_STRING_SIZE(N) (N+1) 
 8151ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
 
 8153class ARDUINOJSON_DEPRECATED(
"use JsonDocument instead") StaticJsonDocument
 
 8154    : 
public JsonDocument {
 
 8156  using JsonDocument::JsonDocument;
 
 8157  size_t capacity()
 const {
 
 8162template <
typename TAllocator>
 
 8163class AllocatorAdapter : 
public Allocator {
 
 8165  AllocatorAdapter(
const AllocatorAdapter&) = 
delete;
 
 8166  AllocatorAdapter& operator=(
const AllocatorAdapter&) = 
delete;
 
 8167  void* allocate(
size_t size)
 override {
 
 8168    return _allocator.allocate(size);
 
 8170  void deallocate(
void* ptr)
 override {
 
 8171    _allocator.deallocate(ptr);
 
 8173  void* reallocate(
void* ptr, 
size_t new_size)
 override {
 
 8174    return _allocator.reallocate(ptr, new_size);
 
 8176  static Allocator* instance() {
 
 8177    static AllocatorAdapter instance;
 
 8181  AllocatorAdapter() = 
default;
 
 8182  ~AllocatorAdapter() = 
default;
 
 8183  TAllocator _allocator;
 
 8186template <
typename TAllocator>
 
 8187class ARDUINOJSON_DEPRECATED(
"use JsonDocument instead") BasicJsonDocument
 
 8188    : 
public JsonDocument {
 
 8190  BasicJsonDocument(
size_t capacity)
 
 8191      : JsonDocument(detail::AllocatorAdapter<TAllocator>::instance()),
 
 8192        _capacity(capacity) {}
 
 8193  size_t capacity()
 const {
 
 8196  void garbageCollect() {}
 
 8200class ARDUINOJSON_DEPRECATED(
"use JsonDocument instead") DynamicJsonDocument
 
 8201    : 
public JsonDocument {
 
 8203  DynamicJsonDocument(
size_t capacity) : _capacity(capacity) {}
 
 8204  size_t capacity()
 const {
 
 8207  void garbageCollect() {}
 
 8211inline JsonObject JsonArray::createNestedObject()
 const {
 
 8212  return add<JsonObject>();
 
 8214ARDUINOJSON_END_PUBLIC_NAMESPACE
 
 8220#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp 
FASTLED_FORCE_INLINE bool operator!=(const CRGB &lhs, const CRGB &rhs)
Check if two CRGB objects do not have the same color data.
FASTLED_FORCE_INLINE bool operator<=(const CRGB &lhs, const CRGB &rhs)
Check if the sum of the color channels in one CRGB object is less than or equal to another.
FASTLED_FORCE_INLINE bool operator==(const CRGB &lhs, const CRGB &rhs)
Check if two CRGB objects have the same color data.
FASTLED_FORCE_INLINE CRGB operator*(const CRGB &p1, fl::u8 d)
Multiply each of the channels by a constant, saturating each channel at 0xFF.
FASTLED_FORCE_INLINE bool operator<(const CRGB &lhs, const CRGB &rhs)
Check if the sum of the color channels in one CRGB object is less than another.
FASTLED_FORCE_INLINE CRGB operator|(const CRGB &p1, const CRGB &p2)
Combine two CRGB objects, taking the largest value of each channel.
FASTLED_FORCE_INLINE CRGB operator&(const CRGB &p1, const CRGB &p2)
Combine two CRGB objects, taking the smallest value of each channel.
FASTLED_FORCE_INLINE bool operator>(const CRGB &lhs, const CRGB &rhs)
Check if the sum of the color channels in one CRGB object is greater than another.
FASTLED_FORCE_INLINE bool operator>=(const CRGB &lhs, const CRGB &rhs)
Check if the sum of the color channels in one CRGB object is greater than or equal to another.
UISlider length("Length", 1.0f, 0.0f, 1.0f, 0.01f)
constexpr remove_reference< T >::type && move(T &&t) noexcept
typename conditional< B, T, F >::type conditional_t
void swap(array< T, N > &lhs, array< T, N > &rhs) noexcept(noexcept(lhs.swap(rhs)))
typename remove_cv< T >::type remove_cv_t
void print(const char *str)
void clear(CRGB(&arr)[N])
constexpr T * begin(T(&array)[N]) noexcept
integral_constant< bool, false > false_type
constexpr T * end(T(&array)[N]) noexcept
decltype(nullptr) nullptr_t
add_rvalue_reference< T >::type declval() noexcept
Iterator remove(Iterator first, Iterator last, const T &value)
fl::HashMap< fl::string, fl::shared_ptr< JsonValue > > JsonObject
fl::vector< fl::shared_ptr< JsonValue > > JsonArray
pair_element< I, T1, T2 >::type & get(pair< T1, T2 > &p) noexcept
ostream & operator<<(ostream &os, const endl_t &)
typename enable_if< Condition, T >::type enable_if_t
integral_constant< bool, true > true_type
constexpr T && forward(typename remove_reference< T >::type &t) noexcept
typename remove_reference< T >::type remove_reference_t