FastLED 3.9.7
Loading...
Searching...
No Matches
json.hpp
1// ArduinoJson - https://arduinojson.org
2// Copyright © 2014-2024, Benoit BLANCHON
3// MIT License
4
5#pragma once
6
7
8#ifndef FASTLED_JSON_GUARD
9#error "You must include json.h instead of json.hpp"
10#endif
11
12
13
14#ifdef __cplusplus
15
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.
18#endif
19#ifndef ARDUINOJSON_ENABLE_STD_STREAM
20# ifdef __has_include
21# if __has_include(<istream>) && \
22 __has_include(<ostream>) && \
23 !defined(min) && \
24 !defined(max)
25# define ARDUINOJSON_ENABLE_STD_STREAM 1
26# else
27# define ARDUINOJSON_ENABLE_STD_STREAM 0
28# endif
29# else
30# ifdef ARDUINO
31# define ARDUINOJSON_ENABLE_STD_STREAM 0
32# else
33# define ARDUINOJSON_ENABLE_STD_STREAM 1
34# endif
35# endif
36#endif
37#ifndef ARDUINOJSON_ENABLE_STD_STRING
38# ifdef __has_include
39# if __has_include(<string>) && !defined(min) && !defined(max)
40# define ARDUINOJSON_ENABLE_STD_STRING 1
41# else
42# define ARDUINOJSON_ENABLE_STD_STRING 0
43# endif
44# else
45# ifdef ARDUINO
46# define ARDUINOJSON_ENABLE_STD_STRING 0
47# else
48# define ARDUINOJSON_ENABLE_STD_STRING 1
49# endif
50# endif
51#endif
52#ifndef ARDUINOJSON_ENABLE_STRING_VIEW
53# ifdef __has_include
54# if __has_include(<string_view>) && __cplusplus >= 201703L
55# define ARDUINOJSON_ENABLE_STRING_VIEW 1
56# else
57# define ARDUINOJSON_ENABLE_STRING_VIEW 0
58# endif
59# else
60# define ARDUINOJSON_ENABLE_STRING_VIEW 0
61# endif
62#endif
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 // 64 bits
68# else
69# define ARDUINOJSON_SIZEOF_POINTER 4 // assume 32 bits otherwise
70# endif
71#endif
72#ifndef ARDUINOJSON_USE_DOUBLE
73# if ARDUINOJSON_SIZEOF_POINTER >= 4 // 32 & 64 bits systems
74# define ARDUINOJSON_USE_DOUBLE 1
75# else
76# define ARDUINOJSON_USE_DOUBLE 0
77# endif
78#endif
79#ifndef ARDUINOJSON_USE_LONG_LONG
80# if ARDUINOJSON_SIZEOF_POINTER >= 4 // 32 & 64 bits systems
81# define ARDUINOJSON_USE_LONG_LONG 1
82# else
83# define ARDUINOJSON_USE_LONG_LONG 0
84# endif
85#endif
86#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
87# define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
88#endif
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
94# else
95# define ARDUINOJSON_SLOT_ID_SIZE 4
96# endif
97#endif
98#ifndef ARDUINOJSON_POOL_CAPACITY
99# if ARDUINOJSON_SLOT_ID_SIZE == 1
100# define ARDUINOJSON_POOL_CAPACITY 16 // 96 bytes
101# elif ARDUINOJSON_SLOT_ID_SIZE == 2
102# define ARDUINOJSON_POOL_CAPACITY 128 // 1024 bytes
103# else
104# define ARDUINOJSON_POOL_CAPACITY 256 // 4096 bytes
105# endif
106#endif
107#ifndef ARDUINOJSON_INITIAL_POOL_COUNT
108# define ARDUINOJSON_INITIAL_POOL_COUNT 4
109#endif
110#ifndef ARDUINOJSON_AUTO_SHRINK
111# if ARDUINOJSON_SIZEOF_POINTER <= 2
112# define ARDUINOJSON_AUTO_SHRINK 0
113# else
114# define ARDUINOJSON_AUTO_SHRINK 1
115# endif
116#endif
117#ifndef ARDUINOJSON_STRING_LENGTH_SIZE
118# if ARDUINOJSON_SIZEOF_POINTER <= 2
119# define ARDUINOJSON_STRING_LENGTH_SIZE 1 // up to 255 characters
120# else
121# define ARDUINOJSON_STRING_LENGTH_SIZE 2 // up to 65535 characters
122# endif
123#endif
124#ifdef ARDUINO
125# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
126# define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
127# endif
128# ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
129# define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
130# endif
131# ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
132# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1
133# endif
134# ifndef ARDUINOJSON_ENABLE_PROGMEM
135# define ARDUINOJSON_ENABLE_PROGMEM 1
136# endif
137#else // ARDUINO
138# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
139# define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
140# endif
141# ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
142# define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
143# endif
144# ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
145# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
146# endif
147# ifndef ARDUINOJSON_ENABLE_PROGMEM
148# ifdef __AVR__
149# define ARDUINOJSON_ENABLE_PROGMEM 1
150# else
151# define ARDUINOJSON_ENABLE_PROGMEM 0
152# endif
153# endif
154#endif // ARDUINO
155#ifndef ARDUINOJSON_DECODE_UNICODE
156# define ARDUINOJSON_DECODE_UNICODE 1
157#endif
158#ifndef ARDUINOJSON_ENABLE_COMMENTS
159# define ARDUINOJSON_ENABLE_COMMENTS 0
160#endif
161#ifndef ARDUINOJSON_ENABLE_NAN
162# define ARDUINOJSON_ENABLE_NAN 0
163#endif
164#ifndef ARDUINOJSON_ENABLE_INFINITY
165# define ARDUINOJSON_ENABLE_INFINITY 0
166#endif
167#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
168# define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
169#endif
170#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
171# define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
172#endif
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
179# else
180# define ARDUINOJSON_LITTLE_ENDIAN 0
181# endif
182#endif
183#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
184# if defined(__AVR)
185# define ARDUINOJSON_ENABLE_ALIGNMENT 0
186# else
187# define ARDUINOJSON_ENABLE_ALIGNMENT 1
188# endif
189#endif
190#ifndef ARDUINOJSON_TAB
191# define ARDUINOJSON_TAB " "
192#endif
193#ifndef ARDUINOJSON_STRING_BUFFER_SIZE
194# define ARDUINOJSON_STRING_BUFFER_SIZE 32
195#endif
196#ifndef ARDUINOJSON_DEBUG
197# ifdef __PLATFORMIO_BUILD_DEBUG__
198# define ARDUINOJSON_DEBUG 1
199# else
200# define ARDUINOJSON_DEBUG 0
201# endif
202#endif
203#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_DOUBLE
204# define ARDUINOJSON_USE_EXTENSIONS 1
205#else
206# define ARDUINOJSON_USE_EXTENSIONS 0
207#endif
208#if defined(nullptr)
209# error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
210#endif
211#if ARDUINOJSON_ENABLE_ARDUINO_STRING || ARDUINOJSON_ENABLE_ARDUINO_STREAM || \
212 ARDUINOJSON_ENABLE_ARDUINO_PRINT || \
213 (ARDUINOJSON_ENABLE_PROGMEM && defined(ARDUINO))
214#include <Arduino.h> // ok include
215#endif
216#if !ARDUINOJSON_DEBUG
217# ifdef __clang__
218# pragma clang system_header
219# elif defined __GNUC__
220# pragma GCC system_header
221# endif
222#endif
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)
265#endif
266#define ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE \
267 namespace FLArduinoJson { \
268 inline namespace ARDUINOJSON_VERSION_NAMESPACE {
269#define ARDUINOJSON_END_PUBLIC_NAMESPACE \
270 } \
271 }
272#define ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE \
273 namespace FLArduinoJson { \
274 inline namespace ARDUINOJSON_VERSION_NAMESPACE { \
275 namespace detail {
276#define ARDUINOJSON_END_PRIVATE_NAMESPACE \
277 } \
278 } \
279 }
280ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
281template <typename T, typename Enable = void>
282struct Converter;
283ARDUINOJSON_END_PUBLIC_NAMESPACE
284ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
285template <typename T1, typename T2>
286class InvalidConversion; // Error here? See https://arduinojson.org/v7/invalid-conversion/
287ARDUINOJSON_END_PRIVATE_NAMESPACE
288#include <stddef.h>
289#include <stdint.h>
290#include <stdlib.h>
291ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
292class Allocator {
293 public:
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;
297 protected:
298 ~Allocator() = default;
299};
300namespace detail {
301class DefaultAllocator : public Allocator {
302 public:
303 void* allocate(size_t size) override {
304 return malloc(size);
305 }
306 void deallocate(void* ptr) override {
307 free(ptr);
308 }
309 void* reallocate(void* ptr, size_t new_size) override {
310 return realloc(ptr, new_size);
311 }
312 static Allocator* instance() {
313 static DefaultAllocator allocator;
314 return &allocator;
315 }
316 private:
317 DefaultAllocator() = default;
318 ~DefaultAllocator() = default;
319};
320} // namespace detail
321ARDUINOJSON_END_PUBLIC_NAMESPACE
322#if ARDUINOJSON_DEBUG
323#include <assert.h> // ok include
324# define ARDUINOJSON_ASSERT(X) assert(X)
325#else
326# define ARDUINOJSON_ASSERT(X) ((void)0)
327#endif
328ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
329template <int Bits>
330struct uint_;
331template <>
332struct uint_<8> {
333 typedef uint8_t type;
334};
335template <>
336struct uint_<16> {
337 typedef uint16_t type;
338};
339template <>
340struct uint_<32> {
341 typedef uint32_t type;
342};
343template <int Bits>
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);
348template <typename T>
349class Slot {
350 public:
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));
354 }
355 explicit operator bool() const {
356 return ptr_ != nullptr;
357 }
358 SlotId id() const {
359 return id_;
360 }
361 T* ptr() const {
362 return ptr_;
363 }
364 T* operator->() const {
365 ARDUINOJSON_ASSERT(ptr_ != nullptr);
366 return ptr_;
367 }
368 private:
369 T* ptr_;
370 SlotId id_;
371};
372template <typename T>
373class MemoryPool {
374 public:
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;
379 usage_ = 0;
380 }
381 void destroy(Allocator* allocator) {
382 if (slots_)
383 allocator->deallocate(slots_);
384 slots_ = nullptr;
385 capacity_ = 0;
386 usage_ = 0;
387 }
388 Slot<T> allocSlot() {
389 if (!slots_)
390 return {};
391 if (usage_ >= capacity_)
392 return {};
393 auto index = usage_++;
394 return {slots_ + index, SlotId(index)};
395 }
396 T* getSlot(SlotId id) const {
397 ARDUINOJSON_ASSERT(id < usage_);
398 return slots_ + id;
399 }
400 void clear() {
401 usage_ = 0;
402 }
403 void shrinkToFit(Allocator* allocator) {
404 auto newSlots = reinterpret_cast<T*>(
405 allocator->reallocate(slots_, slotsToBytes(usage_)));
406 if (newSlots) {
407 slots_ = newSlots;
408 capacity_ = usage_;
409 }
410 }
411 SlotCount usage() const {
412 return usage_;
413 }
414 static SlotCount bytesToSlots(size_t n) {
415 return static_cast<SlotCount>(n / sizeof(T));
416 }
417 static size_t slotsToBytes(SlotCount n) {
418 return n * sizeof(T);
419 }
420 private:
421 SlotCount capacity_;
422 SlotCount usage_;
423 T* slots_;
424};
425template <bool Condition, class TrueType, class FalseType>
426struct conditional {
427 typedef TrueType type;
428};
429template <class TrueType, class FalseType>
430struct conditional<false, TrueType, FalseType> {
431 typedef FalseType type;
432};
433template <bool Condition, class TrueType, class FalseType>
434using conditional_t =
435 typename conditional<Condition, TrueType, FalseType>::type;
436template <bool Condition, typename T = void>
437struct enable_if {};
438template <typename T>
439struct enable_if<true, T> {
440 typedef T type;
441};
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;
450};
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;
456};
457template <typename T, T v>
458struct integral_constant {
459 static const T value = v;
460};
461typedef integral_constant<bool, true> true_type;
462typedef integral_constant<bool, false> false_type;
463template <typename T>
464struct is_array : false_type {};
465template <typename T>
466struct is_array<T[]> : true_type {};
467template <typename T, size_t N>
468struct is_array<T[N]> : true_type {};
469template <typename T>
470struct remove_reference {
471 typedef T type;
472};
473template <typename T>
474struct remove_reference<T&> {
475 typedef T type;
476};
477template <typename T>
478using remove_reference_t = typename remove_reference<T>::type;
479template <typename TBase, typename TDerived>
480class is_base_of {
481 protected: // <- to avoid GCC's "all member functions in class are private"
482 static int probe(const TBase*);
483 static char probe(...);
484 public:
485 static const bool value =
486 sizeof(probe(reinterpret_cast<remove_reference_t<TDerived>*>(0))) ==
487 sizeof(int);
488};
489template <typename T>
490T&& declval();
491template <typename T>
492struct is_class {
493 protected: // <- to avoid GCC's "all member functions in class are private"
494 template <typename U>
495 static int probe(void (U::*)(void));
496 template <typename>
497 static char probe(...);
498 public:
499 static const bool value = sizeof(probe<T>(0)) == sizeof(int);
500};
501template <typename T>
502struct is_const : false_type {};
503template <typename T>
504struct is_const<const T> : true_type {};
505ARDUINOJSON_END_PRIVATE_NAMESPACE
506#ifdef _MSC_VER
507# pragma warning(push)
508# pragma warning(disable : 4244)
509#endif
510#ifdef __ICCARM__
511#pragma diag_suppress=Pa093
512#endif
513ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
514template <typename From, typename To>
515struct is_convertible {
516 protected: // <- to avoid GCC's "all member functions in class are private"
517 static int probe(To);
518 static char probe(...);
519 static From& from_;
520 public:
521 static const bool value = sizeof(probe(from_)) == sizeof(int);
522};
523ARDUINOJSON_END_PRIVATE_NAMESPACE
524#ifdef _MSC_VER
525# pragma warning(pop)
526#endif
527#ifdef __ICCARM__
528#pragma diag_default=Pa093
529#endif
530ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
531template <typename T, typename U>
532struct is_same : false_type {};
533template <typename T>
534struct is_same<T, T> : true_type {};
535template <typename T>
536struct remove_cv {
537 typedef T type;
538};
539template <typename T>
540struct remove_cv<const T> {
541 typedef T type;
542};
543template <typename T>
544struct remove_cv<volatile T> {
545 typedef T type;
546};
547template <typename T>
548struct remove_cv<const volatile T> {
549 typedef T type;
550};
551template <typename T>
552using remove_cv_t = typename remove_cv<T>::type;
553template <class 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> {};
558template <typename T>
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> {};
572template <typename T>
573struct is_enum {
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;
577};
578template <typename T>
579struct is_pointer : false_type {};
580template <typename T>
581struct is_pointer<T*> : true_type {};
582template <typename T>
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> {};
592template <typename T>
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> {};
600template <typename T>
601struct type_identity {
602 typedef T type;
603};
604template <typename T>
605struct make_unsigned;
606template <>
607struct make_unsigned<char> : type_identity<unsigned char> {};
608template <>
609struct make_unsigned<signed char> : type_identity<unsigned char> {};
610template <>
611struct make_unsigned<unsigned char> : type_identity<unsigned char> {};
612template <>
613struct make_unsigned<signed short> : type_identity<unsigned short> {};
614template <>
615struct make_unsigned<unsigned short> : type_identity<unsigned short> {};
616template <>
617struct make_unsigned<signed int> : type_identity<unsigned int> {};
618template <>
619struct make_unsigned<unsigned int> : type_identity<unsigned int> {};
620template <>
621struct make_unsigned<signed long> : type_identity<unsigned long> {};
622template <>
623struct make_unsigned<unsigned long> : type_identity<unsigned long> {};
624template <>
625struct make_unsigned<signed long long> : type_identity<unsigned long long> {};
626template <>
627struct make_unsigned<unsigned long long> : type_identity<unsigned long long> {};
628template <typename T>
629using make_unsigned_t = typename make_unsigned<T>::type;
630template <typename T>
631struct remove_const {
632 typedef T type;
633};
634template <typename T>
635struct remove_const<const T> {
636 typedef T type;
637};
638template <typename T>
639using remove_const_t = typename remove_const<T>::type;
640template <typename...>
641struct make_void {
642 using type = void;
643};
644template <typename... Args>
645using void_t = typename make_void<Args...>::type;
646using nullptr_t = decltype(nullptr);
647template <class T>
648T&& forward(remove_reference_t<T>& t) noexcept {
649 return static_cast<T&&>(t);
650}
651template <class T>
652remove_reference_t<T>&& move(T&& t) {
653 return static_cast<remove_reference_t<T>&&>(t);
654}
655template <class T>
656void swap_(T& a, T& b) {
657 T tmp = move(a);
658 a = move(b);
659 b = move(tmp);
660}
661ARDUINOJSON_END_PRIVATE_NAMESPACE
662#include <string.h>
663ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
664using PoolCount = SlotId;
665template <typename T>
666class MemoryPoolList {
667 struct FreeSlot {
668 SlotId next;
669 };
670 static_assert(sizeof(FreeSlot) <= sizeof(T), "T is too small");
671 public:
672 using Pool = MemoryPool<T>;
673 MemoryPoolList() = default;
674 ~MemoryPoolList() {
675 ARDUINOJSON_ASSERT(count_ == 0);
676 }
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];
686 b.pools_ = a.pools_;
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];
691 a.pools_ = b.pools_;
692 b.pools_ = b.preallocatedPools_;
693 } else {
694 swap_(a.pools_, b.pools_);
695 }
696 swap_(a.count_, b.count_);
697 swap_(a.capacity_, b.capacity_);
698 swap_(a.freeList_, b.freeList_);
699 }
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_;
706 } else {
707 pools_ = src.pools_;
708 src.pools_ = nullptr;
709 }
710 count_ = src.count_;
711 capacity_ = src.capacity_;
712 src.count_ = 0;
713 src.capacity_ = 0;
714 return *this;
715 }
716 Slot<T> allocSlot(Allocator* allocator) {
717 if (freeList_ != NULL_SLOT) {
718 return allocFromFreeList();
719 }
720 if (count_) {
721 auto slot = allocFromLastPool();
722 if (slot)
723 return slot;
724 }
725 auto pool = addPool(allocator);
726 if (!pool)
727 return {};
728 return allocFromLastPool();
729 }
730 void freeSlot(Slot<T> slot) {
731 reinterpret_cast<FreeSlot*>(slot.ptr())->next = freeList_;
732 freeList_ = slot.id();
733 }
734 T* getSlot(SlotId id) const {
735 if (id == NULL_SLOT)
736 return nullptr;
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);
741 }
742 void clear(Allocator* allocator) {
743 for (PoolCount i = 0; i < count_; i++)
744 pools_[i].destroy(allocator);
745 count_ = 0;
746 freeList_ = NULL_SLOT;
747 if (pools_ != preallocatedPools_) {
748 allocator->deallocate(pools_);
749 pools_ = preallocatedPools_;
750 capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
751 }
752 }
753 SlotCount usage() const {
754 SlotCount total = 0;
755 for (PoolCount i = 0; i < count_; i++)
756 total = SlotCount(total + pools_[i].usage());
757 return total;
758 }
759 size_t size() const {
760 return Pool::slotsToBytes(usage());
761 }
762 void shrinkToFit(Allocator* allocator) {
763 if (count_ > 0)
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); // realloc to smaller can't fail
769 capacity_ = count_;
770 }
771 }
772 private:
773 Slot<T> allocFromFreeList() {
774 ARDUINOJSON_ASSERT(freeList_ != NULL_SLOT);
775 auto id = freeList_;
776 auto slot = getSlot(freeList_);
777 freeList_ = reinterpret_cast<FreeSlot*>(slot)->next;
778 return {slot, id};
779 }
780 Slot<T> allocFromLastPool() {
781 ARDUINOJSON_ASSERT(count_ > 0);
782 auto poolIndex = SlotId(count_ - 1);
783 auto slot = pools_[poolIndex].allocSlot();
784 if (!slot)
785 return {};
786 return {slot.ptr(),
787 SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
788 }
789 Pool* addPool(Allocator* allocator) {
790 if (count_ == capacity_ && !increaseCapacity(allocator))
791 return nullptr;
792 auto pool = &pools_[count_++];
793 SlotCount poolCapacity = ARDUINOJSON_POOL_CAPACITY;
794 if (count_ == maxPools) // last pool is smaller because of NULL_SLOT
795 poolCapacity--;
796 pool->create(poolCapacity, allocator);
797 return pool;
798 }
799 bool increaseCapacity(Allocator* allocator) {
800 if (capacity_ == maxPools)
801 return false;
802 void* newPools;
803 auto newCapacity = PoolCount(capacity_ * 2);
804 if (pools_ == preallocatedPools_) {
805 newPools = allocator->allocate(newCapacity * sizeof(Pool));
806 if (!newPools)
807 return false;
808 memcpy(newPools, preallocatedPools_, sizeof(preallocatedPools_));
809 } else {
810 newPools = allocator->reallocate(pools_, newCapacity * sizeof(Pool));
811 if (!newPools)
812 return false;
813 }
814 pools_ = static_cast<Pool*>(newPools);
815 capacity_ = newCapacity;
816 return true;
817 }
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;
823 public:
824 static const PoolCount maxPools =
825 PoolCount(NULL_SLOT / ARDUINOJSON_POOL_CAPACITY + 1);
826};
827ARDUINOJSON_END_PRIVATE_NAMESPACE
828#ifdef _MSC_VER
829# pragma warning(push)
830# pragma warning(disable : 4310)
831#endif
832ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
833template <typename T, typename Enable = void>
834struct numeric_limits;
835template <typename T>
836struct numeric_limits<T, enable_if_t<is_unsigned<T>::value>> {
837 static constexpr T lowest() {
838 return 0;
839 }
840 static constexpr T highest() {
841 return T(-1);
842 }
843};
844template <typename T>
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));
849 }
850 static constexpr T highest() {
851 return T(~lowest());
852 }
853};
854ARDUINOJSON_END_PRIVATE_NAMESPACE
855#ifdef _MSC_VER
856# pragma warning(pop)
857#endif
858ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
859struct StringNode {
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;
864 length_type length;
865 char data[1];
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);
869 }
870 static StringNode* create(size_t length, Allocator* allocator) {
871 if (length > maxLength)
872 return nullptr;
873 auto size = sizeForLength(length);
874 if (size < length) // integer overflow
875 return nullptr; // (not testable on 64-bit)
876 auto node = reinterpret_cast<StringNode*>(allocator->allocate(size));
877 if (node) {
878 node->length = length_type(length);
879 node->references = 1;
880 }
881 return node;
882 }
883 static StringNode* resize(StringNode* node, size_t length,
884 Allocator* allocator) {
885 ARDUINOJSON_ASSERT(node != nullptr);
886 StringNode* newNode;
887 if (length <= maxLength)
888 newNode = reinterpret_cast<StringNode*>(
889 allocator->reallocate(node, sizeForLength(length)));
890 else
891 newNode = nullptr;
892 if (newNode)
893 newNode->length = length_type(length);
894 else
895 allocator->deallocate(node);
896 return newNode;
897 }
898 static void destroy(StringNode* node, Allocator* allocator) {
899 allocator->deallocate(node);
900 }
901};
902constexpr size_t sizeofString(size_t n) {
903 return StringNode::sizeForLength(n);
904}
905ARDUINOJSON_END_PRIVATE_NAMESPACE
906#ifdef _MSC_VER // Visual Studio
907# define FORCE_INLINE // __forceinline causes C4714 when returning std::string
908# ifndef ARDUINOJSON_DEPRECATED
909# define ARDUINOJSON_DEPRECATED(msg) __declspec(deprecated(msg))
910# endif
911#elif defined(__GNUC__) // GCC or Clang
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)))
916# else
917# define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated))
918# endif
919# endif
920#else // Other compilers
921# define FORCE_INLINE
922# ifndef ARDUINOJSON_DEPRECATED
923# define ARDUINOJSON_DEPRECATED(msg)
924# endif
925#endif
926#if defined(__has_attribute)
927# if __has_attribute(no_sanitize)
928# define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check)))
929# else
930# define ARDUINOJSON_NO_SANITIZE(check)
931# endif
932#else
933# define ARDUINOJSON_NO_SANITIZE(check)
934#endif
935ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
936template <typename TString, typename Enable = void>
937struct StringAdapter;
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);
943}
944template <typename TChar>
945typename StringAdapter<TChar*>::AdaptedString adaptString(TChar* p) {
946 return StringAdapter<TChar*>::adapt(p);
947}
948template <typename TChar>
949typename SizedStringAdapter<TChar*>::AdaptedString adaptString(TChar* p,
950 size_t n) {
951 return SizedStringAdapter<TChar*>::adapt(p, n);
952}
953template <typename T>
954struct IsChar
955 : integral_constant<bool, is_integral<T>::value && sizeof(T) == 1> {};
956class ZeroTerminatedRamString {
957 public:
958 static const size_t typeSortKey = 3;
959 ZeroTerminatedRamString(const char* str) : str_(str) {}
960 bool isNull() const {
961 return !str_;
962 }
963 FORCE_INLINE size_t size() const {
964 return str_ ? ::strlen(str_) : 0;
965 }
966 char operator[](size_t i) const {
967 ARDUINOJSON_ASSERT(str_ != 0);
968 ARDUINOJSON_ASSERT(i <= size());
969 return str_[i];
970 }
971 const char* data() const {
972 return str_;
973 }
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_);
979 }
980 friend bool stringEquals(ZeroTerminatedRamString a,
981 ZeroTerminatedRamString b) {
982 return stringCompare(a, b) == 0;
983 }
984 bool isLinked() const {
985 return false;
986 }
987 protected:
988 const char* str_;
989};
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));
995 }
996};
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));
1002 }
1003};
1004class StaticStringAdapter : public ZeroTerminatedRamString {
1005 public:
1006 StaticStringAdapter(const char* str) : ZeroTerminatedRamString(str) {}
1007 bool isLinked() const {
1008 return true;
1009 }
1010};
1011template <>
1012struct StringAdapter<const char*, void> {
1013 typedef StaticStringAdapter AdaptedString;
1014 static AdaptedString adapt(const char* p) {
1015 return AdaptedString(p);
1016 }
1017};
1018class SizedRamString {
1019 public:
1020 static const size_t typeSortKey = 2;
1021 SizedRamString(const char* str, size_t sz) : str_(str), size_(sz) {}
1022 bool isNull() const {
1023 return !str_;
1024 }
1025 size_t size() const {
1026 return size_;
1027 }
1028 char operator[](size_t i) const {
1029 ARDUINOJSON_ASSERT(str_ != 0);
1030 ARDUINOJSON_ASSERT(i <= size());
1031 return str_[i];
1032 }
1033 const char* data() const {
1034 return str_;
1035 }
1036 bool isLinked() const {
1037 return false;
1038 }
1039 protected:
1040 const char* str_;
1041 size_t size_;
1042};
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);
1048 }
1049};
1050ARDUINOJSON_END_PRIVATE_NAMESPACE
1051#if ARDUINOJSON_ENABLE_STD_STREAM
1052#include <ostream>
1053#endif
1054ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
1055class JsonString {
1056 public:
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 sz, Ownership ownership = Linked)
1062 : data_(data), size_(sz), ownership_(ownership) {}
1063 const char* c_str() const {
1064 return data_;
1065 }
1066 bool isNull() const {
1067 return !data_;
1068 }
1069 bool isLinked() const {
1070 return ownership_ == Linked;
1071 }
1072 size_t size() const {
1073 return size_;
1074 }
1075 explicit operator bool() const {
1076 return data_ != 0;
1077 }
1078 friend bool operator==(JsonString lhs, JsonString rhs) {
1079 if (lhs.size_ != rhs.size_)
1080 return false;
1081 if (lhs.data_ == rhs.data_)
1082 return true;
1083 if (!lhs.data_)
1084 return false;
1085 if (!rhs.data_)
1086 return false;
1087 return memcmp(lhs.data_, rhs.data_, lhs.size_) == 0;
1088 }
1089 friend bool operator!=(JsonString lhs, JsonString rhs) {
1090 return !(lhs == rhs);
1091 }
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()));
1095 return lhs;
1096 }
1097#endif
1098 private:
1099 const char* data_;
1100 size_t size_;
1101 Ownership ownership_;
1102};
1103ARDUINOJSON_END_PUBLIC_NAMESPACE
1104ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1105class JsonStringAdapter : public SizedRamString {
1106 public:
1107 JsonStringAdapter(const JsonString& s)
1108 : SizedRamString(s.c_str(), s.size()), linked_(s.isLinked()) {}
1109 bool isLinked() const {
1110 return linked_;
1111 }
1112 private:
1113 bool linked_;
1114};
1115template <>
1116struct StringAdapter<JsonString> {
1117 typedef JsonStringAdapter AdaptedString;
1118 static AdaptedString adapt(const JsonString& s) {
1119 return AdaptedString(s);
1120 }
1121};
1122namespace string_traits_impl {
1123template <class T, class = void>
1124struct has_cstr : false_type {};
1125template <class T>
1126struct has_cstr<T, enable_if_t<is_same<decltype(declval<const T>().c_str()),
1127 const char*>::value>> : true_type {};
1128template <class T, class = void>
1129struct has_data : false_type {};
1130template <class T>
1131struct has_data<T, enable_if_t<is_same<decltype(declval<const T>().data()),
1132 const char*>::value>> : true_type {};
1133template <class T, class = void>
1134struct has_length : false_type {};
1135template <class T>
1136struct has_length<
1137 T, enable_if_t<is_unsigned<decltype(declval<const T>().length())>::value>>
1138 : true_type {};
1139template <class T, class = void>
1140struct has_size : false_type {};
1141template <class T>
1142struct has_size<
1143 T, enable_if_t<is_same<decltype(declval<const T>().size()), size_t>::value>>
1144 : true_type {};
1145} // namespace string_traits_impl
1146template <typename T>
1147struct string_traits {
1148 enum {
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
1153 };
1154};
1155template <typename T>
1156struct StringAdapter<
1157 T,
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));
1163 }
1164 private:
1165 template <typename U>
1166 static enable_if_t<string_traits<U>::has_size, size_t> get_size(const U& s) {
1167 return s.size();
1168 }
1169 template <typename U>
1170 static enable_if_t<!string_traits<U>::has_size, size_t> get_size(const U& s) {
1171 return s.length();
1172 }
1173 template <typename U>
1174 static enable_if_t<string_traits<U>::has_data, const char*> get_data(
1175 const U& s) {
1176 return s.data();
1177 }
1178 template <typename U>
1179 static enable_if_t<!string_traits<U>::has_data, const char*> get_data(
1180 const U& s) {
1181 return s.c_str();
1182 }
1183};
1184ARDUINOJSON_END_PRIVATE_NAMESPACE
1185#if ARDUINOJSON_ENABLE_PROGMEM
1186#ifdef ARDUINO
1187#else
1188class __FlashStringHelper;
1189#include <avr/pgmspace.h>
1190#endif
1191ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1192struct pgm_p {
1193 pgm_p(const void* p) : address(reinterpret_cast<const char*>(p)) {}
1194 const char* address;
1195};
1196ARDUINOJSON_END_PRIVATE_NAMESPACE
1197#ifndef strlen_P
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))
1202 p++;
1203 return size_t(p - s.address);
1204}
1205#endif
1206#ifndef strncmp_P
1207inline int strncmp_P(const char* a, FLArduinoJson::detail::pgm_p b, size_t n) {
1208 const char* s1 = a;
1209 const char* s2 = b.address;
1210 ARDUINOJSON_ASSERT(s1 != NULL);
1211 ARDUINOJSON_ASSERT(s2 != NULL);
1212 while (n-- > 0) {
1213 char c1 = *s1++;
1214 char c2 = static_cast<char>(pgm_read_byte(s2++));
1215 if (c1 < c2)
1216 return -1;
1217 if (c1 > c2)
1218 return 1;
1219 if (c1 == 0 /* and c2 as well */)
1220 return 0;
1221 }
1222 return 0;
1223}
1224#endif
1225#ifndef strcmp_P
1226inline int strcmp_P(const char* a, FLArduinoJson::detail::pgm_p b) {
1227 const char* s1 = a;
1228 const char* s2 = b.address;
1229 ARDUINOJSON_ASSERT(s1 != NULL);
1230 ARDUINOJSON_ASSERT(s2 != NULL);
1231 for (;;) {
1232 char c1 = *s1++;
1233 char c2 = static_cast<char>(pgm_read_byte(s2++));
1234 if (c1 < c2)
1235 return -1;
1236 if (c1 > c2)
1237 return 1;
1238 if (c1 == 0 /* and c2 as well */)
1239 return 0;
1240 }
1241}
1242#endif
1243#ifndef memcmp_P
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);
1249 while (n-- > 0) {
1250 uint8_t v1 = *p1++;
1251 uint8_t v2 = pgm_read_byte(p2++);
1252 if (v1 != v2)
1253 return v1 - v2;
1254 }
1255 return 0;
1256}
1257#endif
1258#ifndef memcpy_P
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);
1264 while (n-- > 0) {
1265 *d++ = pgm_read_byte(s++);
1266 }
1267 return dst;
1268}
1269#endif
1270#ifndef pgm_read_dword
1271inline uint32_t pgm_read_dword(FLArduinoJson::detail::pgm_p p) {
1272 uint32_t result;
1273 memcpy_P(&result, p.address, 4);
1274 return result;
1275}
1276#endif
1277#ifndef pgm_read_float
1278inline float pgm_read_float(FLArduinoJson::detail::pgm_p p) {
1279 float result;
1280 memcpy_P(&result, p.address, sizeof(float));
1281 return result;
1282}
1283#endif
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);
1289}
1290# else
1291inline double pgm_read_double(FLArduinoJson::detail::pgm_p p) {
1292 double result;
1293 memcpy_P(&result, p.address, sizeof(double));
1294 return result;
1295}
1296# endif
1297#endif
1298#ifndef pgm_read_ptr
1299inline void* pgm_read_ptr(FLArduinoJson::detail::pgm_p p) {
1300 void* result;
1301 memcpy_P(&result, p.address, sizeof(result));
1302 return result;
1303}
1304#endif
1305ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1306class FlashString {
1307 public:
1308 static const size_t typeSortKey = 1;
1309 FlashString(const __FlashStringHelper* str, size_t sz)
1310 : str_(reinterpret_cast<const char*>(str)), size_(sz) {}
1311 bool isNull() const {
1312 return !str_;
1313 }
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));
1318 }
1319 const char* data() const {
1320 return nullptr;
1321 }
1322 size_t size() const {
1323 return size_;
1324 }
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())
1330 return false;
1331 return ::memcmp_P(b.data(), a.str_, a.size_) == 0;
1332 }
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);
1339 if (res)
1340 return -res;
1341 if (a.size() < b.size())
1342 return -1;
1343 if (a.size() > b.size())
1344 return 1;
1345 return 0;
1346 }
1347 friend void stringGetChars(FlashString s, char* p, size_t n) {
1348 ARDUINOJSON_ASSERT(s.size() <= n);
1349 ::memcpy_P(p, s.str_, n);
1350 }
1351 bool isLinked() const {
1352 return false;
1353 }
1354 private:
1355 const char* str_;
1356 size_t size_;
1357};
1358template <>
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);
1363 }
1364};
1365template <>
1366struct SizedStringAdapter<const __FlashStringHelper*, void> {
1367 typedef FlashString AdaptedString;
1368 static AdaptedString adapt(const __FlashStringHelper* s, size_t n) {
1369 return AdaptedString(s, n);
1370 }
1371};
1372ARDUINOJSON_END_PRIVATE_NAMESPACE
1373#endif
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++) {
1384 if (s1[i] != s2[i])
1385 return s1[i] - s2[i];
1386 }
1387 if (size1 < size2)
1388 return -1;
1389 if (size1 > size2)
1390 return 1;
1391 return 0;
1392}
1393template <typename TAdaptedString1, typename TAdaptedString2>
1394enable_if_t<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), int>
1395stringCompare(TAdaptedString1 s1, TAdaptedString2 s2) {
1396 return -stringCompare(s2, s1);
1397}
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();
1405 if (size1 != size2)
1406 return false;
1407 for (size_t i = 0; i < size1; i++) {
1408 if (s1[i] != s2[i])
1409 return false;
1410 }
1411 return true;
1412}
1413template <typename TAdaptedString1, typename TAdaptedString2>
1414enable_if_t<(TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), bool>
1415stringEquals(TAdaptedString1 s1, TAdaptedString2 s2) {
1416 return stringEquals(s2, s1);
1417}
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++) {
1422 p[i] = s[i];
1423 }
1424}
1425class StringPool {
1426 public:
1427 StringPool() = default;
1428 StringPool(const StringPool&) = delete;
1429 void operator=(StringPool&& src) = delete;
1430 ~StringPool() {
1431 ARDUINOJSON_ASSERT(strings_ == nullptr);
1432 }
1433 friend void swap(StringPool& a, StringPool& b) {
1434 swap_(a.strings_, b.strings_);
1435 }
1436 void clear(Allocator* allocator) {
1437 while (strings_) {
1438 auto node = strings_;
1439 strings_ = node->next;
1440 StringNode::destroy(node, allocator);
1441 }
1442 }
1443 size_t size() const {
1444 size_t total = 0;
1445 for (auto node = strings_; node; node = node->next)
1446 total += sizeofString(node->length);
1447 return total;
1448 }
1449 template <typename TAdaptedString>
1450 StringNode* add(TAdaptedString str, Allocator* allocator) {
1451 ARDUINOJSON_ASSERT(str.isNull() == false);
1452 auto node = get(str);
1453 if (node) {
1454 node->references++;
1455 return node;
1456 }
1457 size_t n = str.size();
1458 node = StringNode::create(n, allocator);
1459 if (!node)
1460 return nullptr;
1461 stringGetChars(str, node->data, n);
1462 node->data[n] = 0; // force NUL terminator
1463 add(node);
1464 return node;
1465 }
1466 void add(StringNode* node) {
1467 ARDUINOJSON_ASSERT(node != nullptr);
1468 node->next = strings_;
1469 strings_ = node;
1470 }
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)))
1475 return node;
1476 }
1477 return nullptr;
1478 }
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) {
1484 if (prev)
1485 prev->next = node->next;
1486 else
1487 strings_ = node->next;
1488 StringNode::destroy(node, allocator);
1489 }
1490 return;
1491 }
1492 prev = node;
1493 }
1494 }
1495 private:
1496 StringNode* strings_ = nullptr;
1497};
1498ARDUINOJSON_END_PRIVATE_NAMESPACE
1499ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
1500template <typename T>
1501class SerializedValue {
1502 public:
1503 explicit SerializedValue(T str) : str_(str) {}
1504 operator T() const {
1505 return str_;
1506 }
1507 const char* data() const {
1508 return str_.c_str();
1509 }
1510 size_t size() const {
1511 return str_.length();
1512 }
1513 private:
1514 T str_;
1515};
1516template <typename TChar>
1517class SerializedValue<TChar*> {
1518 public:
1519 explicit SerializedValue(TChar* p, size_t n) : data_(p), size_(n) {}
1520 operator TChar*() const {
1521 return data_;
1522 }
1523 TChar* data() const {
1524 return data_;
1525 }
1526 size_t size() const {
1527 return size_;
1528 }
1529 private:
1530 TChar* data_;
1531 size_t size_;
1532};
1533using RawString = SerializedValue<const char*>;
1534template <typename T>
1535inline SerializedValue<T> serialized(T str) {
1536 return SerializedValue<T>(str);
1537}
1538template <typename TChar>
1539inline SerializedValue<TChar*> serialized(TChar* p) {
1540 return SerializedValue<TChar*>(p, detail::adaptString(p).size());
1541}
1542template <typename TChar>
1543inline SerializedValue<TChar*> serialized(TChar* p, size_t n) {
1544 return SerializedValue<TChar*>(p, n);
1545}
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"
1553#endif
1554ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1555#ifndef isnan
1556template <typename T>
1557bool isnan(T x) {
1558 return x != x;
1559}
1560#endif
1561#ifndef isinf
1562template <typename T>
1563bool isinf(T x) {
1564 return x != 0.0 && x * 2 == x;
1565}
1566#endif
1567template <typename T, typename F>
1568struct alias_cast_t {
1569 union {
1570 F raw;
1571 T data;
1572 };
1573};
1574template <typename T, typename F>
1575T alias_cast(F raw_data) {
1576 alias_cast_t<T, F> ac;
1577 ac.raw = raw_data;
1578 return ac.data;
1579}
1580ARDUINOJSON_END_PRIVATE_NAMESPACE
1581#if ARDUINOJSON_ENABLE_PROGMEM
1582#endif
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__;
1588# endif
1589template <typename T>
1590inline const T* pgm_read(const T* const* p) {
1591 return reinterpret_cast<const T*>(pgm_read_ptr(p));
1592}
1593inline uint32_t pgm_read(const uint32_t* p) {
1594 return pgm_read_dword(p);
1595}
1596inline double pgm_read(const double* p) {
1597 return pgm_read_double(p);
1598}
1599inline float pgm_read(const float* p) {
1600 return pgm_read_float(p);
1601}
1602#else
1603# ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY
1604# define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, ...) \
1605 static type const name[] = __VA_ARGS__;
1606# endif
1607template <typename T>
1608inline T pgm_read(const T* p) {
1609 return *p;
1610}
1611#endif
1612template <typename T>
1613class pgm_ptr {
1614 public:
1615 explicit pgm_ptr(const T* ptr) : ptr_(ptr) {}
1616 T operator[](intptr_t index) const {
1617 return pgm_read(ptr_ + index);
1618 }
1619 private:
1620 const T* ptr_;
1621};
1622template <typename T, size_t = sizeof(T)>
1623struct FloatTraits {};
1624template <typename T>
1625struct FloatTraits<T, 8 /*64bits*/> {
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( //
1634 uint64_t, factors,
1635 {
1636 0x4024000000000000, // 1e1
1637 0x4059000000000000, // 1e2
1638 0x40C3880000000000, // 1e4
1639 0x4197D78400000000, // 1e8
1640 0x4341C37937E08000, // 1e16
1641 0x4693B8B5B5056E17, // 1e32
1642 0x4D384F03E93FF9F5, // 1e64
1643 0x5A827748F9301D32, // 1e128
1644 0x75154FDD7F73BF3C, // 1e256
1645 });
1646 return pgm_ptr<T>(reinterpret_cast<const T*>(factors));
1647 }
1648 static pgm_ptr<T> negativeBinaryPowersOfTen() {
1649 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( //
1650 uint64_t, factors,
1651 {
1652 0x3FB999999999999A, // 1e-1
1653 0x3F847AE147AE147B, // 1e-2
1654 0x3F1A36E2EB1C432D, // 1e-4
1655 0x3E45798EE2308C3A, // 1e-8
1656 0x3C9CD2B297D889BC, // 1e-16
1657 0x3949F623D5A8A733, // 1e-32
1658 0x32A50FFD44F4A73D, // 1e-64
1659 0x255BBA08CF8C979D, // 1e-128
1660 0x0AC8062864AC6F43 // 1e-256
1661 });
1662 return pgm_ptr<T>(reinterpret_cast<const T*>(factors));
1663 }
1664 static T nan() {
1665 return forge(0x7ff8000000000000);
1666 }
1667 static T inf() {
1668 return forge(0x7ff0000000000000);
1669 }
1670 static T highest() {
1671 return forge(0x7FEFFFFFFFFFFFFF);
1672 }
1673 template <typename TOut> // int64_t
1674 static T highest_for(
1675 enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
1676 sizeof(TOut) == 8,
1677 signed>* = 0) {
1678 return forge(0x43DFFFFFFFFFFFFF); // 9.2233720368547748e+18
1679 }
1680 template <typename TOut> // uint64_t
1681 static T highest_for(
1682 enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
1683 sizeof(TOut) == 8,
1684 unsigned>* = 0) {
1685 return forge(0x43EFFFFFFFFFFFFF); // 1.8446744073709549568e+19
1686 }
1687 static T lowest() {
1688 return forge(0xFFEFFFFFFFFFFFFF);
1689 }
1690 static T forge(uint64_t bits) {
1691 return alias_cast<T>(bits);
1692 }
1693};
1694template <typename T>
1695struct FloatTraits<T, 4 /*32bits*/> {
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,
1704 {
1705 0x41200000, // 1e1f
1706 0x42c80000, // 1e2f
1707 0x461c4000, // 1e4f
1708 0x4cbebc20, // 1e8f
1709 0x5a0e1bca, // 1e16f
1710 0x749dc5ae // 1e32f
1711 });
1712 return pgm_ptr<T>(reinterpret_cast<const T*>(factors));
1713 }
1714 static pgm_ptr<T> negativeBinaryPowersOfTen() {
1715 ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors,
1716 {
1717 0x3dcccccd, // 1e-1f
1718 0x3c23d70a, // 1e-2f
1719 0x38d1b717, // 1e-4f
1720 0x322bcc77, // 1e-8f
1721 0x24e69595, // 1e-16f
1722 0x0a4fb11f // 1e-32f
1723 });
1724 return pgm_ptr<T>(reinterpret_cast<const T*>(factors));
1725 }
1726 static T forge(uint32_t bits) {
1727 return alias_cast<T>(bits);
1728 }
1729 static T nan() {
1730 return forge(0x7fc00000);
1731 }
1732 static T inf() {
1733 return forge(0x7f800000);
1734 }
1735 static T highest() {
1736 return forge(0x7f7fffff);
1737 }
1738 template <typename TOut> // int32_t
1739 static T highest_for(
1740 enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
1741 sizeof(TOut) == 4,
1742 signed>* = 0) {
1743 return forge(0x4EFFFFFF); // 2.14748352E9
1744 }
1745 template <typename TOut> // uint32_t
1746 static T highest_for(
1747 enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
1748 sizeof(TOut) == 4,
1749 unsigned>* = 0) {
1750 return forge(0x4F7FFFFF); // 4.29496704E9
1751 }
1752 template <typename TOut> // int64_t
1753 static T highest_for(
1754 enable_if_t<is_integral<TOut>::value && is_signed<TOut>::value &&
1755 sizeof(TOut) == 8,
1756 signed>* = 0) {
1757 return forge(0x5EFFFFFF); // 9.22337148709896192E18
1758 }
1759 template <typename TOut> // uint64_t
1760 static T highest_for(
1761 enable_if_t<is_integral<TOut>::value && is_unsigned<TOut>::value &&
1762 sizeof(TOut) == 8,
1763 unsigned>* = 0) {
1764 return forge(0x5F7FFFFF); // 1.844674297419792384E19
1765 }
1766 static T lowest() {
1767 return forge(0xFf7fffff);
1768 }
1769};
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();
1775 if (e <= 0)
1776 e = TExponent(-e);
1777 for (uint8_t index = 0; e != 0; index++) {
1778 if (e & 1)
1779 m *= powersOfTen[index];
1780 e >>= 1;
1781 }
1782 return m;
1783}
1784ARDUINOJSON_END_PRIVATE_NAMESPACE
1785ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
1786#if ARDUINOJSON_USE_DOUBLE
1787typedef double JsonFloat;
1788#else
1789typedef float JsonFloat;
1790#endif
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),
1796 bool>
1797canConvertNumber(TIn value) {
1798 return value <= TIn(numeric_limits<TOut>::highest());
1799}
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),
1803 bool>
1804canConvertNumber(TIn) {
1805 return true;
1806}
1807template <typename TOut, typename TIn>
1808enable_if_t<is_integral<TIn>::value && is_floating_point<TOut>::value, bool>
1809canConvertNumber(TIn) {
1810 return true;
1811}
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),
1816 bool>
1817canConvertNumber(TIn value) {
1818 return value >= TIn(numeric_limits<TOut>::lowest()) &&
1819 value <= TIn(numeric_limits<TOut>::highest());
1820}
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),
1825 bool>
1826canConvertNumber(TIn) {
1827 return true;
1828}
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),
1833 bool>
1834canConvertNumber(TIn value) {
1835 if (value < 0)
1836 return false;
1837 return TOut(value) <= numeric_limits<TOut>::highest();
1838}
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),
1843 bool>
1844canConvertNumber(TIn value) {
1845 if (value < 0)
1846 return false;
1847 return value <= TIn(numeric_limits<TOut>::highest());
1848}
1849template <typename TOut, typename TIn>
1850enable_if_t<is_floating_point<TIn>::value && is_integral<TOut>::value &&
1851 sizeof(TOut) < sizeof(TIn),
1852 bool>
1853canConvertNumber(TIn value) {
1854 return value >= numeric_limits<TOut>::lowest() &&
1855 value <= numeric_limits<TOut>::highest();
1856}
1857template <typename TOut, typename TIn>
1858enable_if_t<is_floating_point<TIn>::value && is_integral<TOut>::value &&
1859 sizeof(TOut) >= sizeof(TIn),
1860 bool>
1861canConvertNumber(TIn value) {
1862 return value >= numeric_limits<TOut>::lowest() &&
1863 value <= FloatTraits<TIn>::template highest_for<TOut>();
1864}
1865template <typename TOut, typename TIn>
1866enable_if_t<is_floating_point<TIn>::value && is_floating_point<TOut>::value,
1867 bool>
1868canConvertNumber(TIn) {
1869 return true;
1870}
1871template <typename TOut, typename TIn>
1872TOut convertNumber(TIn value) {
1873 return canConvertNumber<TOut>(value) ? TOut(value) : 0;
1874}
1875ARDUINOJSON_END_PRIVATE_NAMESPACE
1876#if defined(__clang__)
1877# pragma clang diagnostic pop
1878#elif defined(__GNUC__)
1879# pragma GCC diagnostic pop
1880#endif
1881ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1882class VariantData;
1883class ResourceManager;
1884class CollectionIterator {
1885 friend class CollectionData;
1886 public:
1887 CollectionIterator() : slot_(nullptr), currentId_(NULL_SLOT) {}
1888 void next(const ResourceManager* resources);
1889 bool done() const {
1890 return slot_ == nullptr;
1891 }
1892 bool operator==(const CollectionIterator& other) const {
1893 return slot_ == other.slot_;
1894 }
1895 bool operator!=(const CollectionIterator& other) const {
1896 return slot_ != other.slot_;
1897 }
1898 VariantData* operator->() {
1899 ARDUINOJSON_ASSERT(slot_ != nullptr);
1900 return data();
1901 }
1902 VariantData& operator*() {
1903 ARDUINOJSON_ASSERT(slot_ != nullptr);
1904 return *data();
1905 }
1906 const VariantData& operator*() const {
1907 ARDUINOJSON_ASSERT(slot_ != nullptr);
1908 return *data();
1909 }
1910 VariantData* data() {
1911 return reinterpret_cast<VariantData*>(slot_);
1912 }
1913 const VariantData* data() const {
1914 return reinterpret_cast<const VariantData*>(slot_);
1915 }
1916 private:
1917 CollectionIterator(VariantData* slot, SlotId slotId);
1918 VariantData* slot_;
1919 SlotId currentId_, nextId_;
1920};
1921class CollectionData {
1922 SlotId head_ = NULL_SLOT;
1923 SlotId tail_ = NULL_SLOT;
1924 public:
1925 static void* operator new(size_t, void* p) noexcept {
1926 return p;
1927 }
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) {
1935 if (!collection)
1936 return;
1937 collection->clear(resources);
1938 }
1939 SlotId head() const {
1940 return head_;
1941 }
1942 protected:
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);
1948 private:
1949 Slot<VariantData> getPreviousSlot(VariantData*, const ResourceManager*) const;
1950};
1951inline const VariantData* collectionToVariant(
1952 const CollectionData* collection) {
1953 const void* data = collection; // prevent warning cast-align
1954 return reinterpret_cast<const VariantData*>(data);
1955}
1956inline VariantData* collectionToVariant(CollectionData* collection) {
1957 void* data = collection; // prevent warning cast-align
1958 return reinterpret_cast<VariantData*>(data);
1959}
1960class ArrayData : public CollectionData {
1961 public:
1962 VariantData* addElement(ResourceManager* resources);
1963 static VariantData* addElement(ArrayData* array, ResourceManager* resources) {
1964 if (!array)
1965 return nullptr;
1966 return array->addElement(resources);
1967 }
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) {
1973 if (!array)
1974 return false;
1975 return array->addValue(value, resources);
1976 }
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) {
1981 if (!array)
1982 return nullptr;
1983 return array->getElement(index, resources);
1984 }
1985 void removeElement(size_t index, ResourceManager* resources);
1986 static void removeElement(ArrayData* array, size_t index,
1987 ResourceManager* resources) {
1988 if (!array)
1989 return;
1990 array->removeElement(index, resources);
1991 }
1992 void remove(iterator it, ResourceManager* resources) {
1993 CollectionData::removeOne(it, resources);
1994 }
1995 static void remove(ArrayData* array, iterator it,
1996 ResourceManager* resources) {
1997 if (array)
1998 return array->remove(it, resources);
1999 }
2000 private:
2001 iterator at(size_t index, const ResourceManager* resources) const;
2002};
2003ARDUINOJSON_END_PRIVATE_NAMESPACE
2004ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2005#if ARDUINOJSON_USE_LONG_LONG
2006typedef int64_t JsonInteger;
2007typedef uint64_t JsonUInt;
2008#else
2009typedef long JsonInteger;
2010typedef unsigned long JsonUInt;
2011#endif
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 {
2020 public:
2021 template <typename TAdaptedString> // also works with StringNode*
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) {
2031 if (!object)
2032 return nullptr;
2033 return object->getMember(key, resources);
2034 }
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) {
2040 if (!obj)
2041 return;
2042 obj->removeMember(key, resources);
2043 }
2044 void remove(iterator it, ResourceManager* resources) {
2045 CollectionData::removePair(it, resources);
2046 }
2047 static void remove(ObjectData* obj, ObjectData::iterator it,
2048 ResourceManager* resources) {
2049 if (!obj)
2050 return;
2051 obj->remove(it, resources);
2052 }
2053 size_t size(const ResourceManager* resources) const {
2054 return CollectionData::size(resources) / 2;
2055 }
2056 static size_t size(const ObjectData* obj, const ResourceManager* resources) {
2057 if (!obj)
2058 return 0;
2059 return obj->size(resources);
2060 }
2061 private:
2062 template <typename TAdaptedString>
2063 iterator findKey(TAdaptedString key, const ResourceManager* resources) const;
2064};
2065enum class VariantTypeBits : uint8_t {
2066 OwnedStringBit = 0x01, // 0000 0001
2067 NumberBit = 0x08, // 0000 1000
2068#if ARDUINOJSON_USE_EXTENSIONS
2069 ExtensionBit = 0x10, // 0001 0000
2070#endif
2071 CollectionMask = 0x60,
2072};
2073enum class VariantType : uint8_t {
2074 Null = 0, // 0000 0000
2075 RawString = 0x03, // 0000 0011
2076 LinkedString = 0x04, // 0000 0100
2077 OwnedString = 0x05, // 0000 0101
2078 Boolean = 0x06, // 0000 0110
2079 Uint32 = 0x0A, // 0000 1010
2080 Int32 = 0x0C, // 0000 1100
2081 Float = 0x0E, // 0000 1110
2082#if ARDUINOJSON_USE_LONG_LONG
2083 Uint64 = 0x1A, // 0001 1010
2084 Int64 = 0x1C, // 0001 1100
2085#endif
2086#if ARDUINOJSON_USE_DOUBLE
2087 Double = 0x1E, // 0001 1110
2088#endif
2089 Object = 0x20,
2090 Array = 0x40,
2091};
2092inline bool operator&(VariantType type, VariantTypeBits bit) {
2093 return (uint8_t(type) & uint8_t(bit)) != 0;
2094}
2095union VariantContent {
2096 VariantContent() {}
2097 float asFloat;
2098 bool asBoolean;
2099 uint32_t asUint32;
2100 int32_t asInt32;
2101#if ARDUINOJSON_USE_EXTENSIONS
2102 SlotId asSlotId;
2103#endif
2104 ArrayData asArray;
2105 ObjectData asObject;
2106 CollectionData asCollection;
2107 const char* asLinkedString;
2108 struct StringNode* asOwnedString;
2109};
2110#if ARDUINOJSON_USE_EXTENSIONS
2111union VariantExtension {
2112# if ARDUINOJSON_USE_LONG_LONG
2113 uint64_t asUint64;
2114 int64_t asInt64;
2115# endif
2116# if ARDUINOJSON_USE_DOUBLE
2117 double asDouble;
2118# endif
2119};
2120#endif
2121template <typename T>
2122T parseNumber(const char* s);
2123class VariantData {
2124 VariantContent content_; // must be first to allow cast from array to variant
2125 VariantType type_;
2126 SlotId next_;
2127 public:
2128 static void* operator new(size_t, void* p) noexcept {
2129 return p;
2130 }
2131 static void operator delete(void*, void*) noexcept {}
2132 VariantData() : type_(VariantType::Null), next_(NULL_SLOT) {}
2133 SlotId next() const {
2134 return next_;
2135 }
2136 void setNext(SlotId slot) {
2137 next_ = slot;
2138 }
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);
2144#else
2145 (void)resources; // silence warning
2146#endif
2147 switch (type_) {
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);
2153#endif
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);
2176#endif
2177 case VariantType::Boolean:
2178 return visit.visit(content_.asBoolean != 0);
2179 default:
2180 return visit.visit(nullptr);
2181 }
2182 }
2183 template <typename TVisitor>
2184 static typename TVisitor::result_type accept(const VariantData* var,
2185 const ResourceManager* resources,
2186 TVisitor& visit) {
2187 if (var != 0)
2188 return var->accept(visit, resources);
2189 else
2190 return visit.visit(nullptr);
2191 }
2192 VariantData* addElement(ResourceManager* resources) {
2193 auto array = isNull() ? &toArray() : asArray();
2194 return detail::ArrayData::addElement(array, resources);
2195 }
2196 static VariantData* addElement(VariantData* var, ResourceManager* resources) {
2197 if (!var)
2198 return nullptr;
2199 return var->addElement(resources);
2200 }
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),
2205 resources);
2206 }
2207 template <typename T>
2208 static bool addValue(VariantData* var, T&& value,
2209 ResourceManager* resources) {
2210 if (!var)
2211 return false;
2212 return var->addValue(value, resources);
2213 }
2214 bool asBoolean(const ResourceManager* resources) const {
2215#if ARDUINOJSON_USE_EXTENSIONS
2216 auto extension = getExtension(resources);
2217#else
2218 (void)resources; // silence warning
2219#endif
2220 switch (type_) {
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;
2231#endif
2232 case VariantType::Null:
2233 return false;
2234#if ARDUINOJSON_USE_LONG_LONG
2235 case VariantType::Uint64:
2236 case VariantType::Int64:
2237 return extension->asUint64 != 0;
2238#endif
2239 default:
2240 return true;
2241 }
2242 }
2243 ArrayData* asArray() {
2244 return isArray() ? &content_.asArray : 0;
2245 }
2246 const ArrayData* asArray() const {
2247 return const_cast<VariantData*>(this)->asArray();
2248 }
2249 CollectionData* asCollection() {
2250 return isCollection() ? &content_.asCollection : 0;
2251 }
2252 const CollectionData* asCollection() const {
2253 return const_cast<VariantData*>(this)->asCollection();
2254 }
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);
2260#else
2261 (void)resources; // silence warning
2262#endif
2263 switch (type_) {
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);
2275#endif
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);
2284#endif
2285 default:
2286 return 0;
2287 }
2288 }
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);
2294#else
2295 (void)resources; // silence warning
2296#endif
2297 switch (type_) {
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);
2309#endif
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);
2319#endif
2320 default:
2321 return 0;
2322 }
2323 }
2324 ObjectData* asObject() {
2325 return isObject() ? &content_.asObject : 0;
2326 }
2327 const ObjectData* asObject() const {
2328 return const_cast<VariantData*>(this)->asObject();
2329 }
2330 JsonString asRawString() const {
2331 switch (type_) {
2332 case VariantType::RawString:
2333 return JsonString(content_.asOwnedString->data,
2334 content_.asOwnedString->length, JsonString::Copied);
2335 default:
2336 return JsonString();
2337 }
2338 }
2339 JsonString asString() const {
2340 switch (type_) {
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);
2346 default:
2347 return JsonString();
2348 }
2349 }
2350#if ARDUINOJSON_USE_EXTENSIONS
2351 const VariantExtension* getExtension(const ResourceManager* resources) const;
2352#endif
2353 VariantData* getElement(size_t index,
2354 const ResourceManager* resources) const {
2355 return ArrayData::getElement(asArray(), index, resources);
2356 }
2357 static VariantData* getElement(const VariantData* var, size_t index,
2358 const ResourceManager* resources) {
2359 return var != 0 ? var->getElement(index, resources) : 0;
2360 }
2361 template <typename TAdaptedString>
2362 VariantData* getMember(TAdaptedString key,
2363 const ResourceManager* resources) const {
2364 return ObjectData::getMember(asObject(), key, resources);
2365 }
2366 template <typename TAdaptedString>
2367 static VariantData* getMember(const VariantData* var, TAdaptedString key,
2368 const ResourceManager* resources) {
2369 if (!var)
2370 return 0;
2371 return var->getMember(key, resources);
2372 }
2373 VariantData* getOrAddElement(size_t index, ResourceManager* resources) {
2374 auto array = isNull() ? &toArray() : asArray();
2375 if (!array)
2376 return nullptr;
2377 return array->getOrAddElement(index, resources);
2378 }
2379 template <typename TAdaptedString>
2380 VariantData* getOrAddMember(TAdaptedString key, ResourceManager* resources) {
2381 if (key.isNull())
2382 return nullptr;
2383 auto obj = isNull() ? &toObject() : asObject();
2384 if (!obj)
2385 return nullptr;
2386 return obj->getOrAddMember(key, resources);
2387 }
2388 bool isArray() const {
2389 return type_ == VariantType::Array;
2390 }
2391 bool isBoolean() const {
2392 return type_ == VariantType::Boolean;
2393 }
2394 bool isCollection() const {
2395 return type_ & VariantTypeBits::CollectionMask;
2396 }
2397 bool isFloat() const {
2398 return type_ & VariantTypeBits::NumberBit;
2399 }
2400 template <typename T>
2401 bool isInteger(const ResourceManager* resources) const {
2402#if ARDUINOJSON_USE_LONG_LONG
2403 auto extension = getExtension(resources);
2404#else
2405 (void)resources; // silence warning
2406#endif
2407 switch (type_) {
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);
2417#endif
2418 default:
2419 return false;
2420 }
2421 }
2422 bool isNull() const {
2423 return type_ == VariantType::Null;
2424 }
2425 static bool isNull(const VariantData* var) {
2426 if (!var)
2427 return true;
2428 return var->isNull();
2429 }
2430 bool isObject() const {
2431 return type_ == VariantType::Object;
2432 }
2433 bool isString() const {
2434 return type_ == VariantType::LinkedString ||
2435 type_ == VariantType::OwnedString;
2436 }
2437 size_t nesting(const ResourceManager* resources) const {
2438 auto collection = asCollection();
2439 if (collection)
2440 return collection->nesting(resources);
2441 else
2442 return 0;
2443 }
2444 static size_t nesting(const VariantData* var,
2445 const ResourceManager* resources) {
2446 if (!var)
2447 return 0;
2448 return var->nesting(resources);
2449 }
2450 void removeElement(size_t index, ResourceManager* resources) {
2451 ArrayData::removeElement(asArray(), index, resources);
2452 }
2453 static void removeElement(VariantData* var, size_t index,
2454 ResourceManager* resources) {
2455 if (!var)
2456 return;
2457 var->removeElement(index, resources);
2458 }
2459 template <typename TAdaptedString>
2460 void removeMember(TAdaptedString key, ResourceManager* resources) {
2461 ObjectData::removeMember(asObject(), key, resources);
2462 }
2463 template <typename TAdaptedString>
2464 static void removeMember(VariantData* var, TAdaptedString key,
2465 ResourceManager* resources) {
2466 if (!var)
2467 return;
2468 var->removeMember(key, resources);
2469 }
2470 void reset() { // TODO: remove
2471 type_ = VariantType::Null;
2472 }
2473 void setBoolean(bool value) {
2474 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
2475 type_ = VariantType::Boolean;
2476 content_.asBoolean = value;
2477 }
2478 template <typename T>
2479 enable_if_t<sizeof(T) == 4, bool> setFloat(T value, ResourceManager*) {
2480 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
2481 type_ = VariantType::Float;
2482 content_.asFloat = value;
2483 return true;
2484 }
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); // must call clear() first
2495 ARDUINOJSON_ASSERT(s);
2496 type_ = VariantType::RawString;
2497 content_.asOwnedString = s;
2498 }
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) {
2504 if (!var)
2505 return;
2506 var->clear(resources);
2507 var->setRawString(value, resources);
2508 }
2509 template <typename TAdaptedString>
2510 bool setString(TAdaptedString value, ResourceManager* resources);
2511 bool setString(StringNode* s, ResourceManager*) {
2512 setOwnedString(s);
2513 return true;
2514 }
2515 template <typename TAdaptedString>
2516 static void setString(VariantData* var, TAdaptedString value,
2517 ResourceManager* resources) {
2518 if (!var)
2519 return;
2520 var->clear(resources);
2521 var->setString(value, resources);
2522 }
2523 void setLinkedString(const char* s) {
2524 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
2525 ARDUINOJSON_ASSERT(s);
2526 type_ = VariantType::LinkedString;
2527 content_.asLinkedString = s;
2528 }
2529 void setOwnedString(StringNode* s) {
2530 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
2531 ARDUINOJSON_ASSERT(s);
2532 type_ = VariantType::OwnedString;
2533 content_.asOwnedString = s;
2534 }
2535 size_t size(const ResourceManager* resources) const {
2536 if (isObject())
2537 return content_.asObject.size(resources);
2538 if (isArray())
2539 return content_.asArray.size(resources);
2540 return 0;
2541 }
2542 static size_t size(const VariantData* var, const ResourceManager* resources) {
2543 return var != 0 ? var->size(resources) : 0;
2544 }
2545 ArrayData& toArray() {
2546 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
2547 type_ = VariantType::Array;
2548 new (&content_.asArray) ArrayData();
2549 return content_.asArray;
2550 }
2551 static ArrayData* toArray(VariantData* var, ResourceManager* resources) {
2552 if (!var)
2553 return 0;
2554 var->clear(resources);
2555 return &var->toArray();
2556 }
2557 ObjectData& toObject() {
2558 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
2559 type_ = VariantType::Object;
2560 new (&content_.asObject) ObjectData();
2561 return content_.asObject;
2562 }
2563 static ObjectData* toObject(VariantData* var, ResourceManager* resources) {
2564 if (!var)
2565 return 0;
2566 var->clear(resources);
2567 return &var->toObject();
2568 }
2569 VariantType type() const {
2570 return type_;
2571 }
2572 void clear(ResourceManager* resources);
2573 static void clear(VariantData* var, ResourceManager* resources) {
2574 if (!var)
2575 return;
2576 var->clear(resources);
2577 }
2578};
2579class VariantData;
2580class VariantWithId;
2581class ResourceManager {
2582 union SlotData {
2583 VariantData variant;
2584#if ARDUINOJSON_USE_EXTENSIONS
2585 VariantExtension extension;
2586#endif
2587 };
2588 public:
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_);
2595 }
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_);
2603 }
2604 Allocator* allocator() const {
2605 return allocator_;
2606 }
2607 size_t size() const {
2608 return variantPools_.size() + stringPool_.size();
2609 }
2610 bool overflowed() const {
2611 return overflowed_;
2612 }
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;
2620#endif
2621 template <typename TAdaptedString>
2622 StringNode* saveString(TAdaptedString str) {
2623 if (str.isNull())
2624 return 0;
2625 auto node = stringPool_.add(str, allocator_);
2626 if (!node)
2627 overflowed_ = true;
2628 return node;
2629 }
2630 void saveString(StringNode* node) {
2631 stringPool_.add(node);
2632 }
2633 template <typename TAdaptedString>
2634 StringNode* getString(const TAdaptedString& str) const {
2635 return stringPool_.get(str);
2636 }
2637 StringNode* createString(size_t length) {
2638 auto node = StringNode::create(length, allocator_);
2639 if (!node)
2640 overflowed_ = true;
2641 return node;
2642 }
2643 StringNode* resizeString(StringNode* node, size_t length) {
2644 node = StringNode::resize(node, length, allocator_);
2645 if (!node)
2646 overflowed_ = true;
2647 return node;
2648 }
2649 void destroyString(StringNode* node) {
2650 StringNode::destroy(node, allocator_);
2651 }
2652 void dereferenceString(const char* s) {
2653 stringPool_.dereference(s, allocator_);
2654 }
2655 void clear() {
2656 variantPools_.clear(allocator_);
2657 overflowed_ = false;
2658 stringPool_.clear(allocator_);
2659 }
2660 void shrinkToFit() {
2661 variantPools_.shrinkToFit(allocator_);
2662 }
2663 private:
2664 Allocator* allocator_;
2665 bool overflowed_;
2666 StringPool stringPool_;
2667 MemoryPoolList<SlotData> variantPools_;
2668};
2669template <typename T, typename Enable = void>
2670struct IsString : false_type {};
2671template <typename T>
2672struct IsString<T, void_t<typename StringAdapter<T>::AdaptedString>>
2673 : true_type {};
2674ARDUINOJSON_END_PRIVATE_NAMESPACE
2675ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2676class JsonArray;
2677class JsonObject;
2678class JsonVariant;
2679ARDUINOJSON_END_PUBLIC_NAMESPACE
2680ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
2681template <typename T>
2682struct VariantTo {};
2683template <>
2684struct VariantTo<JsonArray> {
2685 typedef JsonArray type;
2686};
2687template <>
2688struct VariantTo<JsonObject> {
2689 typedef JsonObject type;
2690};
2691template <>
2692struct VariantTo<JsonVariant> {
2693 typedef JsonVariant type;
2694};
2695class VariantAttorney {
2696 public:
2697 template <typename TClient>
2698 static auto getResourceManager(TClient& client)
2699 -> decltype(client.getResourceManager()) {
2700 return client.getResourceManager();
2701 }
2702 template <typename TClient>
2703 static auto getData(TClient& client) -> decltype(client.getData()) {
2704 return client.getData();
2705 }
2706 template <typename TClient>
2707 static VariantData* getOrCreateData(TClient& client) {
2708 return client.getOrCreateData();
2709 }
2710};
2711enum CompareResult {
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
2718};
2719template <typename T>
2720CompareResult arithmeticCompare(const T& lhs, const T& rhs) {
2721 if (lhs < rhs)
2722 return COMPARE_RESULT_LESS;
2723 else if (lhs > rhs)
2724 return COMPARE_RESULT_GREATER;
2725 else
2726 return COMPARE_RESULT_EQUAL;
2727}
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);
2734}
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));
2741}
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));
2749}
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) {
2756 if (rhs < 0)
2757 return COMPARE_RESULT_GREATER;
2758 return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
2759}
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) {
2766 if (lhs < 0)
2767 return COMPARE_RESULT_LESS;
2768 return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
2769}
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>* =
2774 0) {
2775 return arithmeticCompare<double>(static_cast<double>(lhs),
2776 static_cast<double>(rhs));
2777}
2778template <typename T2>
2779CompareResult arithmeticCompareNegateLeft(
2780 JsonUInt, const T2&, enable_if_t<is_unsigned<T2>::value>* = 0) {
2781 return COMPARE_RESULT_LESS;
2782}
2783template <typename T2>
2784CompareResult arithmeticCompareNegateLeft(
2785 JsonUInt lhs, const T2& rhs, enable_if_t<is_signed<T2>::value>* = 0) {
2786 if (rhs > 0)
2787 return COMPARE_RESULT_LESS;
2788 return arithmeticCompare(-rhs, static_cast<T2>(lhs));
2789}
2790template <typename T1>
2791CompareResult arithmeticCompareNegateRight(
2792 const T1&, JsonUInt, enable_if_t<is_unsigned<T1>::value>* = 0) {
2793 return COMPARE_RESULT_GREATER;
2794}
2795template <typename T1>
2796CompareResult arithmeticCompareNegateRight(
2797 const T1& lhs, JsonUInt rhs, enable_if_t<is_signed<T1>::value>* = 0) {
2798 if (lhs > 0)
2799 return COMPARE_RESULT_GREATER;
2800 return arithmeticCompare(static_cast<T1>(rhs), -lhs);
2801}
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,
2812 const T& rhs); // VariantCompare.cpp
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>();
2821 else
2822 return defaultValue;
2823 }
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*>();
2828 else
2829 return defaultValue;
2830 }
2831 template <typename T>
2832 friend enable_if_t<IsVariant<T>::value, JsonVariantConst> operator|(
2833 const TVariant& variant, T defaultValue) {
2834 if (variant)
2835 return variant;
2836 else
2837 return defaultValue;
2838 }
2839 template <typename T>
2840 friend bool operator==(T* lhs, TVariant rhs) {
2841 return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
2842 }
2843 template <typename T>
2844 friend bool operator==(const T& lhs, TVariant rhs) {
2845 return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
2846 }
2847 template <typename T>
2848 friend bool operator==(TVariant lhs, T* rhs) {
2849 return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
2850 }
2851 template <typename T>
2852 friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
2853 operator==(TVariant lhs, const T& rhs) {
2854 return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
2855 }
2856 template <typename T>
2857 friend bool operator!=(T* lhs, TVariant rhs) {
2858 return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
2859 }
2860 template <typename T>
2861 friend bool operator!=(const T& lhs, TVariant rhs) {
2862 return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
2863 }
2864 template <typename T>
2865 friend bool operator!=(TVariant lhs, T* rhs) {
2866 return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
2867 }
2868 template <typename T>
2869 friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
2870 operator!=(TVariant lhs, const T& rhs) {
2871 return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
2872 }
2873 template <typename T>
2874 friend bool operator<(T* lhs, TVariant rhs) {
2875 return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
2876 }
2877 template <typename T>
2878 friend bool operator<(const T& lhs, TVariant rhs) {
2879 return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
2880 }
2881 template <typename T>
2882 friend bool operator<(TVariant lhs, T* rhs) {
2883 return compare(lhs, rhs) == COMPARE_RESULT_LESS;
2884 }
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;
2889 }
2890 template <typename T>
2891 friend bool operator<=(T* lhs, TVariant rhs) {
2892 return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2893 }
2894 template <typename T>
2895 friend bool operator<=(const T& lhs, TVariant rhs) {
2896 return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2897 }
2898 template <typename T>
2899 friend bool operator<=(TVariant lhs, T* rhs) {
2900 return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2901 }
2902 template <typename T>
2903 friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
2904 operator<=(TVariant lhs, const T& rhs) {
2905 return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2906 }
2907 template <typename T>
2908 friend bool operator>(T* lhs, TVariant rhs) {
2909 return compare(rhs, lhs) == COMPARE_RESULT_LESS;
2910 }
2911 template <typename T>
2912 friend bool operator>(const T& lhs, TVariant rhs) {
2913 return compare(rhs, lhs) == COMPARE_RESULT_LESS;
2914 }
2915 template <typename T>
2916 friend bool operator>(TVariant lhs, T* rhs) {
2917 return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
2918 }
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;
2923 }
2924 template <typename T>
2925 friend bool operator>=(T* lhs, TVariant rhs) {
2926 return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2927 }
2928 template <typename T>
2929 friend bool operator>=(const T& lhs, TVariant rhs) {
2930 return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2931 }
2932 template <typename T>
2933 friend bool operator>=(TVariant lhs, T* rhs) {
2934 return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2935 }
2936 template <typename T>
2937 friend enable_if_t<!is_base_of<VariantOperatorTag, T>::value, bool>
2938 operator>=(TVariant lhs, const T& rhs) {
2939 return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2940 }
2941};
2942ARDUINOJSON_END_PRIVATE_NAMESPACE
2943ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2944class JsonArray;
2945class JsonObject;
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,
2953 JsonVariantConst>;
2954 public:
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_);
2961 }
2962 bool isUnbound() const {
2963 return !data_;
2964 }
2965 size_t nesting() const {
2966 return detail::VariantData::nesting(data_, resources_);
2967 }
2968 size_t size() const {
2969 return detail::VariantData::size(data_, resources_);
2970 }
2971 template <typename T,
2972 detail::enable_if_t<ConversionSupported<T>::value, bool> = true>
2973 T as() const {
2974 return Converter<T>::fromJson(*this);
2975 }
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);
2982 }
2983 template <typename T>
2984 detail::enable_if_t<!ConversionSupported<T>::value, bool> is() const {
2985 return false;
2986 }
2987 template <typename T>
2988 operator T() const {
2989 return as<T>();
2990 }
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_),
2996 resources_);
2997 }
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_),
3003 resources_);
3004 }
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_),
3010 resources_);
3011 }
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>());
3017 else
3018 return operator[](key.template as<const char*>());
3019 }
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),
3025 resources_) != 0;
3026 }
3027 template <typename TChar>
3028 ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
3029 detail::enable_if_t<detail::IsString<TChar*>::value, bool> containsKey(
3030 TChar* key) const {
3031 return detail::VariantData::getMember(getData(), detail::adaptString(key),
3032 resources_) != 0;
3033 }
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*>());
3039 }
3040 ARDUINOJSON_DEPRECATED("always returns zero")
3041 size_t memoryUsage() const {
3042 return 0;
3043 }
3044 protected:
3045 const detail::VariantData* getData() const {
3046 return data_;
3047 }
3048 const detail::ResourceManager* getResourceManager() const {
3049 return resources_;
3050 }
3051 private:
3052 const detail::VariantData* data_;
3053 const detail::ResourceManager* resources_;
3054};
3055class JsonVariant;
3056ARDUINOJSON_END_PUBLIC_NAMESPACE
3057ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
3058template <typename>
3059class ElementProxy;
3060template <typename, typename>
3061class MemberProxy;
3062template <typename TDerived>
3063class VariantRefBase : public VariantTag {
3064 friend class VariantAttorney;
3065 public:
3066 void clear() const {
3067 VariantData::clear(getOrCreateData(), getResourceManager());
3068 }
3069 bool isNull() const {
3070 return VariantData::isNull(getData());
3071 }
3072 bool isUnbound() const {
3073 return !getData();
3074 }
3075 template <typename T>
3076 T as() const;
3077 template <typename T, typename = enable_if_t<!is_same<T, TDerived>::value>>
3078 operator T() const {
3079 return as<T>();
3080 }
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);
3092 }
3093 template <typename T>
3094 bool set(T* value) const {
3095 return doSet<Converter<T*>>(value);
3096 }
3097 size_t size() const {
3098 return VariantData::size(getData(), getResourceManager());
3099 }
3100 size_t nesting() const {
3101 return VariantData::nesting(getData(), getResourceManager());
3102 }
3103 template <typename T>
3104 enable_if_t<!is_same<T, JsonVariant>::value, T> add() const {
3105 return add<JsonVariant>().template to<T>();
3106 }
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());
3113 }
3114 template <typename T>
3115 bool add(T* value) const {
3116 return detail::VariantData::addValue(getOrCreateData(), value,
3117 getResourceManager());
3118 }
3119 void remove(size_t index) const {
3120 VariantData::removeElement(getData(), index, getResourceManager());
3121 }
3122 template <typename TChar>
3123 enable_if_t<IsString<TChar*>::value> remove(TChar* key) const {
3124 VariantData::removeMember(getData(), adaptString(key),
3125 getResourceManager());
3126 }
3127 template <typename TString>
3128 enable_if_t<IsString<TString>::value> remove(const TString& key) const {
3129 VariantData::removeMember(getData(), adaptString(key),
3130 getResourceManager());
3131 }
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>());
3136 else
3137 remove(key.template as<const char*>());
3138 }
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>
3152 FORCE_INLINE
3153 enable_if_t<IsString<TString>::value, MemberProxy<TDerived, TString>>
3154 operator[](const TString& key) const;
3155 template <typename TChar>
3156 FORCE_INLINE
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>());
3164 else
3165 return operator[](key.template as<const char*>());
3166 }
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 {
3187 return 0;
3188 }
3189 ARDUINOJSON_DEPRECATED("performs a deep copy")
3190 void shallowCopy(JsonVariantConst src) const {
3191 set(src);
3192 }
3193 private:
3194 TDerived& derived() {
3195 return static_cast<TDerived&>(*this);
3196 }
3197 const TDerived& derived() const {
3198 return static_cast<const TDerived&>(*this);
3199 }
3200 ResourceManager* getResourceManager() const {
3201 return VariantAttorney::getResourceManager(derived());
3202 }
3203 VariantData* getData() const {
3204 return VariantAttorney::getData(derived());
3205 }
3206 VariantData* getOrCreateData() const {
3207 return VariantAttorney::getOrCreateData(derived());
3208 }
3209 FORCE_INLINE FLArduinoJson::JsonVariant getVariant() const;
3210 FORCE_INLINE FLArduinoJson::JsonVariantConst getVariantConst() const {
3211 return FLArduinoJson::JsonVariantConst(getData(), getResourceManager());
3212 }
3213 template <typename T>
3214 FORCE_INLINE enable_if_t<is_same<T, JsonVariantConst>::value, T> getVariant()
3215 const {
3216 return getVariantConst();
3217 }
3218 template <typename T>
3219 FORCE_INLINE enable_if_t<is_same<T, JsonVariant>::value, T> getVariant()
3220 const {
3221 return getVariant();
3222 }
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,
3229 bool>{});
3230 }
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;
3236};
3237template <typename TUpstream>
3238class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
3239 public VariantOperators<ElementProxy<TUpstream>> {
3240 friend class VariantAttorney;
3241 public:
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) {
3247 this->set(src);
3248 return *this;
3249 }
3250 template <typename T>
3251 ElementProxy& operator=(const T& src) {
3252 this->set(src);
3253 return *this;
3254 }
3255 template <typename T>
3256 ElementProxy& operator=(T* src) {
3257 this->set(src);
3258 return *this;
3259 }
3260 private:
3261 ResourceManager* getResourceManager() const {
3262 return VariantAttorney::getResourceManager(upstream_);
3263 }
3264 FORCE_INLINE VariantData* getData() const {
3265 return VariantData::getElement(
3266 VariantAttorney::getData(upstream_), index_,
3267 VariantAttorney::getResourceManager(upstream_));
3268 }
3269 VariantData* getOrCreateData() const {
3270 auto data = VariantAttorney::getOrCreateData(upstream_);
3271 if (!data)
3272 return nullptr;
3273 return data->getOrAddElement(
3274 index_, VariantAttorney::getResourceManager(upstream_));
3275 }
3276 TUpstream upstream_;
3277 size_t index_;
3278};
3279ARDUINOJSON_END_PRIVATE_NAMESPACE
3280ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
3281class JsonVariant : public detail::VariantRefBase<JsonVariant>,
3282 public detail::VariantOperators<JsonVariant> {
3283 friend class detail::VariantAttorney;
3284 public:
3285 JsonVariant() : data_(0), resources_(0) {}
3286 JsonVariant(detail::VariantData* data, detail::ResourceManager* resources)
3287 : data_(data), resources_(resources) {}
3288 private:
3289 detail::ResourceManager* getResourceManager() const {
3290 return resources_;
3291 }
3292 detail::VariantData* getData() const {
3293 return data_;
3294 }
3295 detail::VariantData* getOrCreateData() const {
3296 return data_;
3297 }
3298 detail::VariantData* data_;
3299 detail::ResourceManager* resources_;
3300};
3301namespace detail {
3302bool copyVariant(JsonVariant dst, JsonVariantConst src);
3303}
3304template <>
3305struct Converter<JsonVariant> : private detail::VariantAttorney {
3306 static void toJson(JsonVariantConst src, JsonVariant dst) {
3307 copyVariant(dst, src);
3308 }
3309 static JsonVariant fromJson(JsonVariant src) {
3310 return src;
3311 }
3312 static bool checkJson(JsonVariant src) {
3313 auto data = getData(src);
3314 return !!data;
3315 }
3316};
3317template <>
3318struct Converter<JsonVariantConst> : private detail::VariantAttorney {
3319 static void toJson(JsonVariantConst src, JsonVariant dst) {
3320 copyVariant(dst, src);
3321 }
3322 static JsonVariantConst fromJson(JsonVariantConst src) {
3323 return JsonVariantConst(getData(src), getResourceManager(src));
3324 }
3325 static bool checkJson(JsonVariantConst src) {
3326 auto data = getData(src);
3327 return !!data;
3328 }
3329};
3330template <typename T>
3331class Ref {
3332 public:
3333 Ref(T value) : value_(value) {}
3334 T* operator->() {
3335 return &value_;
3336 }
3337 T& operator*() {
3338 return value_;
3339 }
3340 private:
3341 T value_;
3342};
3343class JsonArrayIterator {
3344 friend class JsonArray;
3345 public:
3346 JsonArrayIterator() {}
3347 explicit JsonArrayIterator(detail::ArrayData::iterator iterator,
3348 detail::ResourceManager* resources)
3349 : iterator_(iterator), resources_(resources) {}
3350 JsonVariant operator*() {
3351 return JsonVariant(iterator_.data(), resources_);
3352 }
3353 Ref<JsonVariant> operator->() {
3354 return operator*();
3355 }
3356 bool operator==(const JsonArrayIterator& other) const {
3357 return iterator_ == other.iterator_;
3358 }
3359 bool operator!=(const JsonArrayIterator& other) const {
3360 return iterator_ != other.iterator_;
3361 }
3362 JsonArrayIterator& operator++() {
3363 iterator_.next(resources_);
3364 return *this;
3365 }
3366 private:
3367 detail::ArrayData::iterator iterator_;
3368 detail::ResourceManager* resources_;
3369};
3370class JsonArrayConstIterator {
3371 friend class JsonArray;
3372 public:
3373 JsonArrayConstIterator() {}
3374 explicit JsonArrayConstIterator(detail::ArrayData::iterator iterator,
3375 const detail::ResourceManager* resources)
3376 : iterator_(iterator), resources_(resources) {}
3377 JsonVariantConst operator*() const {
3378 return JsonVariantConst(iterator_.data(), resources_);
3379 }
3380 Ref<JsonVariantConst> operator->() {
3381 return operator*();
3382 }
3383 bool operator==(const JsonArrayConstIterator& other) const {
3384 return iterator_ == other.iterator_;
3385 }
3386 bool operator!=(const JsonArrayConstIterator& other) const {
3387 return iterator_ != other.iterator_;
3388 }
3389 JsonArrayConstIterator& operator++() {
3390 iterator_.next(resources_);
3391 return *this;
3392 }
3393 private:
3394 detail::ArrayData::iterator iterator_;
3395 const detail::ResourceManager* resources_;
3396};
3397class JsonObject;
3398class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
3399 friend class JsonArray;
3400 friend class detail::VariantAttorney;
3401 public:
3402 typedef JsonArrayConstIterator iterator;
3403 iterator begin() const {
3404 if (!data_)
3405 return iterator();
3406 return iterator(data_->createIterator(resources_), resources_);
3407 }
3408 iterator end() const {
3409 return iterator();
3410 }
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_),
3420 resources_);
3421 }
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>());
3427 else
3428 return JsonVariantConst();
3429 }
3430 operator JsonVariantConst() const {
3431 return JsonVariantConst(getData(), resources_);
3432 }
3433 bool isNull() const {
3434 return data_ == 0;
3435 }
3436 operator bool() const {
3437 return data_ != 0;
3438 }
3439 size_t nesting() const {
3440 return detail::VariantData::nesting(getData(), resources_);
3441 }
3442 size_t size() const {
3443 return data_ ? data_->size(resources_) : 0;
3444 }
3445 ARDUINOJSON_DEPRECATED("always returns zero")
3446 size_t memoryUsage() const {
3447 return 0;
3448 }
3449 private:
3450 const detail::VariantData* getData() const {
3451 return collectionToVariant(data_);
3452 }
3453 const detail::ArrayData* data_;
3454 const detail::ResourceManager* resources_;
3455};
3456inline bool operator==(JsonArrayConst lhs, JsonArrayConst rhs) {
3457 if (!lhs && !rhs)
3458 return true;
3459 if (!lhs || !rhs)
3460 return false;
3461 auto a = lhs.begin();
3462 auto b = rhs.begin();
3463 for (;;) {
3464 if (a == b) // same pointer or both null
3465 return true;
3466 if (a == lhs.end() || b == rhs.end())
3467 return false;
3468 if (*a != *b)
3469 return false;
3470 ++a;
3471 ++b;
3472 }
3473}
3474class JsonObject;
3475class JsonArray : public detail::VariantOperators<JsonArray> {
3476 friend class detail::VariantAttorney;
3477 public:
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() {
3483 void* data = data_; // prevent warning cast-align
3484 return JsonVariant(reinterpret_cast<detail::VariantData*>(data),
3485 resources_);
3486 }
3487 operator JsonArrayConst() const {
3488 return JsonArrayConst(data_, resources_);
3489 }
3490 template <typename T>
3491 detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() const {
3492 return add<JsonVariant>().to<T>();
3493 }
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_),
3497 resources_);
3498 }
3499 template <typename T>
3500 bool add(const T& value) const {
3501 return detail::ArrayData::addValue(data_, value, resources_);
3502 }
3503 template <typename T>
3504 bool add(T* value) const {
3505 return detail::ArrayData::addValue(data_, value, resources_);
3506 }
3507 iterator begin() const {
3508 if (!data_)
3509 return iterator();
3510 return iterator(data_->createIterator(resources_), resources_);
3511 }
3512 iterator end() const {
3513 return iterator();
3514 }
3515 bool set(JsonArrayConst src) const {
3516 if (!data_)
3517 return false;
3518 clear();
3519 for (auto element : src) {
3520 if (!add(element))
3521 return false;
3522 }
3523 return true;
3524 }
3525 void remove(iterator it) const {
3526 detail::ArrayData::remove(data_, it.iterator_, resources_);
3527 }
3528 void remove(size_t index) const {
3529 detail::ArrayData::removeElement(data_, index, resources_);
3530 }
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>());
3536 }
3537 void clear() const {
3538 detail::ArrayData::clear(data_, resources_);
3539 }
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)};
3545 }
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>());
3552 else
3553 return {*this, size_t(-1)};
3554 }
3555 operator JsonVariantConst() const {
3556 return JsonVariantConst(collectionToVariant(data_), resources_);
3557 }
3558 bool isNull() const {
3559 return data_ == 0;
3560 }
3561 operator bool() const {
3562 return data_ != 0;
3563 }
3564 size_t nesting() const {
3565 return detail::VariantData::nesting(collectionToVariant(data_), resources_);
3566 }
3567 size_t size() const {
3568 return data_ ? data_->size(resources_) : 0;
3569 }
3570 ARDUINOJSON_DEPRECATED("use add<JsonVariant>() instead")
3571 JsonVariant add() const {
3572 return add<JsonVariant>();
3573 }
3574 ARDUINOJSON_DEPRECATED("use add<JsonArray>() instead")
3575 JsonArray createNestedArray() const {
3576 return add<JsonArray>();
3577 }
3578 ARDUINOJSON_DEPRECATED("use add<JsonObject>() instead")
3579 JsonObject createNestedObject() const;
3580 ARDUINOJSON_DEPRECATED("always returns zero")
3581 size_t memoryUsage() const {
3582 return 0;
3583 }
3584 private:
3585 detail::ResourceManager* getResourceManager() const {
3586 return resources_;
3587 }
3588 detail::VariantData* getData() const {
3589 return collectionToVariant(data_);
3590 }
3591 detail::VariantData* getOrCreateData() const {
3592 return collectionToVariant(data_);
3593 }
3594 detail::ArrayData* data_;
3595 detail::ResourceManager* resources_;
3596};
3597class JsonPair {
3598 public:
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);
3605 }
3606 }
3607 JsonString key() const {
3608 return key_;
3609 }
3610 JsonVariant value() {
3611 return value_;
3612 }
3613 private:
3614 JsonString key_;
3615 JsonVariant value_;
3616};
3617class JsonPairConst {
3618 public:
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);
3625 }
3626 }
3627 JsonString key() const {
3628 return key_;
3629 }
3630 JsonVariantConst value() const {
3631 return value_;
3632 }
3633 private:
3634 JsonString key_;
3635 JsonVariantConst value_;
3636};
3637class JsonObjectIterator {
3638 friend class JsonObject;
3639 public:
3640 JsonObjectIterator() {}
3641 explicit JsonObjectIterator(detail::ObjectData::iterator iterator,
3642 detail::ResourceManager* resources)
3643 : iterator_(iterator), resources_(resources) {}
3644 JsonPair operator*() const {
3645 return JsonPair(iterator_, resources_);
3646 }
3647 Ref<JsonPair> operator->() {
3648 return operator*();
3649 }
3650 bool operator==(const JsonObjectIterator& other) const {
3651 return iterator_ == other.iterator_;
3652 }
3653 bool operator!=(const JsonObjectIterator& other) const {
3654 return iterator_ != other.iterator_;
3655 }
3656 JsonObjectIterator& operator++() {
3657 iterator_.next(resources_); // key
3658 iterator_.next(resources_); // value
3659 return *this;
3660 }
3661 private:
3662 detail::ObjectData::iterator iterator_;
3663 detail::ResourceManager* resources_;
3664};
3665class JsonObjectConstIterator {
3666 friend class JsonObject;
3667 public:
3668 JsonObjectConstIterator() {}
3669 explicit JsonObjectConstIterator(detail::ObjectData::iterator iterator,
3670 const detail::ResourceManager* resources)
3671 : iterator_(iterator), resources_(resources) {}
3672 JsonPairConst operator*() const {
3673 return JsonPairConst(iterator_, resources_);
3674 }
3675 Ref<JsonPairConst> operator->() {
3676 return operator*();
3677 }
3678 bool operator==(const JsonObjectConstIterator& other) const {
3679 return iterator_ == other.iterator_;
3680 }
3681 bool operator!=(const JsonObjectConstIterator& other) const {
3682 return iterator_ != other.iterator_;
3683 }
3684 JsonObjectConstIterator& operator++() {
3685 iterator_.next(resources_); // key
3686 iterator_.next(resources_); // value
3687 return *this;
3688 }
3689 private:
3690 detail::ObjectData::iterator iterator_;
3691 const detail::ResourceManager* resources_;
3692};
3693class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
3694 friend class JsonObject;
3695 friend class detail::VariantAttorney;
3696 public:
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_);
3704 }
3705 bool isNull() const {
3706 return data_ == 0;
3707 }
3708 operator bool() const {
3709 return data_ != 0;
3710 }
3711 size_t nesting() const {
3712 return detail::VariantData::nesting(getData(), resources_);
3713 }
3714 size_t size() const {
3715 return data_ ? data_->size(resources_) : 0;
3716 }
3717 iterator begin() const {
3718 if (!data_)
3719 return iterator();
3720 return iterator(data_->createIterator(resources_), resources_);
3721 }
3722 iterator end() const {
3723 return iterator();
3724 }
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),
3730 resources_) != 0;
3731 }
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),
3736 resources_) != 0;
3737 }
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*>());
3743 }
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_),
3749 resources_);
3750 }
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_),
3756 resources_);
3757 }
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*>());
3763 else
3764 return JsonVariantConst();
3765 }
3766 ARDUINOJSON_DEPRECATED("always returns zero")
3767 size_t memoryUsage() const {
3768 return 0;
3769 }
3770 private:
3771 const detail::VariantData* getData() const {
3772 return collectionToVariant(data_);
3773 }
3774 const detail::ObjectData* data_;
3775 const detail::ResourceManager* resources_;
3776};
3777inline bool operator==(JsonObjectConst lhs, JsonObjectConst rhs) {
3778 if (!lhs && !rhs) // both are null
3779 return true;
3780 if (!lhs || !rhs) // only one is null
3781 return false;
3782 size_t count = 0;
3783 for (auto kvp : lhs) {
3784 auto rhsValue = rhs[kvp.key()];
3785 if (rhsValue.isUnbound())
3786 return false;
3787 if (kvp.value() != rhsValue)
3788 return false;
3789 count++;
3790 }
3791 return count == rhs.size();
3792}
3793ARDUINOJSON_END_PUBLIC_NAMESPACE
3794ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
3795template <typename TUpstream, typename TStringRef>
3796class MemberProxy
3797 : public VariantRefBase<MemberProxy<TUpstream, TStringRef>>,
3798 public VariantOperators<MemberProxy<TUpstream, TStringRef>> {
3799 friend class VariantAttorney;
3800 public:
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) {
3806 this->set(src);
3807 return *this;
3808 }
3809 template <typename T>
3810 MemberProxy& operator=(const T& src) {
3811 this->set(src);
3812 return *this;
3813 }
3814 template <typename T>
3815 MemberProxy& operator=(T* src) {
3816 this->set(src);
3817 return *this;
3818 }
3819 private:
3820 ResourceManager* getResourceManager() const {
3821 return VariantAttorney::getResourceManager(upstream_);
3822 }
3823 VariantData* getData() const {
3824 return VariantData::getMember(
3825 VariantAttorney::getData(upstream_), adaptString(key_),
3826 VariantAttorney::getResourceManager(upstream_));
3827 }
3828 VariantData* getOrCreateData() const {
3829 auto data = VariantAttorney::getOrCreateData(upstream_);
3830 if (!data)
3831 return nullptr;
3832 return data->getOrAddMember(adaptString(key_),
3833 VariantAttorney::getResourceManager(upstream_));
3834 }
3835 private:
3836 TUpstream upstream_;
3837 TStringRef key_;
3838};
3839ARDUINOJSON_END_PRIVATE_NAMESPACE
3840ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
3841class JsonArray;
3842class JsonObject : public detail::VariantOperators<JsonObject> {
3843 friend class detail::VariantAttorney;
3844 public:
3845 typedef JsonObjectIterator iterator;
3846 JsonObject() : data_(0), resources_(0) {}
3847 JsonObject(detail::ObjectData* data, detail::ResourceManager* resource)
3848 : data_(data), resources_(resource) {}
3849 operator JsonVariant() const {
3850 void* data = data_; // prevent warning cast-align
3851 return JsonVariant(reinterpret_cast<detail::VariantData*>(data),
3852 resources_);
3853 }
3854 operator JsonObjectConst() const {
3855 return JsonObjectConst(data_, resources_);
3856 }
3857 operator JsonVariantConst() const {
3858 return JsonVariantConst(collectionToVariant(data_), resources_);
3859 }
3860 bool isNull() const {
3861 return data_ == 0;
3862 }
3863 operator bool() const {
3864 return data_ != 0;
3865 }
3866 size_t nesting() const {
3867 return detail::VariantData::nesting(collectionToVariant(data_), resources_);
3868 }
3869 size_t size() const {
3870 return data_ ? data_->size(resources_) : 0;
3871 }
3872 iterator begin() const {
3873 if (!data_)
3874 return iterator();
3875 return iterator(data_->createIterator(resources_), resources_);
3876 }
3877 iterator end() const {
3878 return iterator();
3879 }
3880 void clear() const {
3881 detail::ObjectData::clear(data_, resources_);
3882 }
3883 bool set(JsonObjectConst src) {
3884 if (!data_ || !src.data_)
3885 return false;
3886 clear();
3887 for (auto kvp : src) {
3888 if (!operator[](kvp.key()).set(kvp.value()))
3889 return false;
3890 }
3891 return true;
3892 }
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};
3898 }
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};
3904 }
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*>()};
3911 else
3912 return {*this, nullptr};
3913 }
3914 FORCE_INLINE void remove(iterator it) const {
3915 detail::ObjectData::remove(data_, it.iterator_, resources_);
3916 }
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),
3921 resources_);
3922 }
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*>());
3928 }
3929 template <typename TChar>
3930 FORCE_INLINE void remove(TChar* key) const {
3931 detail::ObjectData::removeMember(data_, detail::adaptString(key),
3932 resources_);
3933 }
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),
3939 resources_) != 0;
3940 }
3941 template <typename TChar>
3942 ARDUINOJSON_DEPRECATED("use obj[\"key\"].is<T>() instead")
3943 detail::enable_if_t<detail::IsString<TChar*>::value, bool> containsKey(
3944 TChar* key) const {
3945 return detail::ObjectData::getMember(data_, detail::adaptString(key),
3946 resources_) != 0;
3947 }
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*>());
3953 }
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>();
3958 }
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>();
3963 }
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>();
3968 }
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>();
3973 }
3974 ARDUINOJSON_DEPRECATED("always returns zero")
3975 size_t memoryUsage() const {
3976 return 0;
3977 }
3978 private:
3979 detail::ResourceManager* getResourceManager() const {
3980 return resources_;
3981 }
3982 detail::VariantData* getData() const {
3983 return detail::collectionToVariant(data_);
3984 }
3985 detail::VariantData* getOrCreateData() const {
3986 return detail::collectionToVariant(data_);
3987 }
3988 detail::ObjectData* data_;
3989 detail::ResourceManager* resources_;
3990};
3991class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
3992 friend class detail::VariantAttorney;
3993 public:
3994 explicit JsonDocument(Allocator* alloc = detail::DefaultAllocator::instance())
3995 : resources_(alloc) {}
3996 JsonDocument(const JsonDocument& src) : JsonDocument(src.allocator()) {
3997 set(src);
3998 }
3999 JsonDocument(JsonDocument&& src)
4000 : JsonDocument(detail::DefaultAllocator::instance()) {
4001 swap(*this, src);
4002 }
4003 template <typename T>
4004 JsonDocument(
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) {
4012 set(src);
4013 }
4014 JsonDocument& operator=(JsonDocument src) {
4015 swap(*this, src);
4016 return *this;
4017 }
4018 template <typename T>
4019 JsonDocument& operator=(const T& src) {
4020 set(src);
4021 return *this;
4022 }
4023 Allocator* allocator() const {
4024 return resources_.allocator();
4025 }
4026 void shrinkToFit() {
4027 resources_.shrinkToFit();
4028 }
4029 template <typename T>
4030 T as() {
4031 return getVariant().template as<T>();
4032 }
4033 template <typename T>
4034 T as() const {
4035 return getVariant().template as<T>();
4036 }
4037 void clear() {
4038 resources_.clear();
4039 data_.reset();
4040 }
4041 template <typename T>
4042 bool is() {
4043 return getVariant().template is<T>();
4044 }
4045 template <typename T>
4046 bool is() const {
4047 return getVariant().template is<T>();
4048 }
4049 bool isNull() const {
4050 return getVariant().isNull();
4051 }
4052 bool overflowed() const {
4053 return resources_.overflowed();
4054 }
4055 size_t nesting() const {
4056 return data_.nesting(&resources_);
4057 }
4058 size_t size() const {
4059 return data_.size(&resources_);
4060 }
4061 bool set(const JsonDocument& src) {
4062 return to<JsonVariant>().set(src.as<JsonVariantConst>());
4063 }
4064 template <typename T>
4065 detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, bool> set(
4066 const T& src) {
4067 return to<JsonVariant>().set(src);
4068 }
4069 template <typename T>
4070 typename detail::VariantTo<T>::type to() {
4071 clear();
4072 return getVariant().template to<T>();
4073 }
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;
4078 }
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;
4084 }
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*>());
4090 }
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};
4096 }
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};
4102 }
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_);
4108 }
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_);
4114 }
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)};
4120 }
4121 JsonVariantConst operator[](size_t index) const {
4122 return JsonVariantConst(data_.getElement(index, &resources_), &resources_);
4123 }
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>());
4131 return {};
4132 }
4133 template <typename T>
4134 detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() {
4135 return add<JsonVariant>().to<T>();
4136 }
4137 template <typename T>
4138 detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() {
4139 return JsonVariant(data_.addElement(&resources_), &resources_);
4140 }
4141 template <typename TValue>
4142 bool add(const TValue& value) {
4143 return data_.addValue(value, &resources_);
4144 }
4145 template <typename TChar>
4146 bool add(TChar* value) {
4147 return data_.addValue(value, &resources_);
4148 }
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());
4153 }
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());
4158 }
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());
4164 }
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>());
4172 }
4173 operator JsonVariant() {
4174 return getVariant();
4175 }
4176 operator JsonVariantConst() const {
4177 return getVariant();
4178 }
4179 friend void swap(JsonDocument& a, JsonDocument& b) {
4180 swap(a.resources_, b.resources_);
4181 swap_(a.data_, b.data_);
4182 }
4183 ARDUINOJSON_DEPRECATED("use add<JsonVariant>() instead")
4184 JsonVariant add() {
4185 return add<JsonVariant>();
4186 }
4187 ARDUINOJSON_DEPRECATED("use add<JsonArray>() instead")
4188 JsonArray createNestedArray() {
4189 return add<JsonArray>();
4190 }
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>();
4195 }
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>();
4200 }
4201 ARDUINOJSON_DEPRECATED("use add<JsonObject>() instead")
4202 JsonObject createNestedObject() {
4203 return add<JsonObject>();
4204 }
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>();
4209 }
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>();
4214 }
4215 ARDUINOJSON_DEPRECATED("always returns zero")
4216 size_t memoryUsage() const {
4217 return 0;
4218 }
4219 private:
4220 JsonVariant getVariant() {
4221 return JsonVariant(&data_, &resources_);
4222 }
4223 JsonVariantConst getVariant() const {
4224 return JsonVariantConst(&data_, &resources_);
4225 }
4226 detail::ResourceManager* getResourceManager() {
4227 return &resources_;
4228 }
4229 detail::VariantData* getData() {
4230 return &data_;
4231 }
4232 const detail::VariantData* getData() const {
4233 return &data_;
4234 }
4235 detail::VariantData* getOrCreateData() {
4236 return &data_;
4237 }
4238 detail::ResourceManager resources_;
4239 detail::VariantData data_;
4240};
4241inline void convertToJson(const JsonDocument& src, JsonVariant dst) {
4242 dst.set(src.as<JsonVariantConst>());
4243}
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&) {
4251 return TResult();
4252 }
4253};
4254template <typename TResult>
4255struct JsonVariantVisitor {
4256 typedef TResult result_type;
4257 template <typename T>
4258 TResult visit(const T&) {
4259 return TResult();
4260 }
4261};
4262template <typename TVisitor>
4263class VisitorAdapter {
4264 public:
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_));
4270 }
4271 result_type visit(const ObjectData& value) {
4272 return visitor_->visit(JsonObjectConst(&value, resources_));
4273 }
4274 template <typename T>
4275 result_type visit(const T& value) {
4276 return visitor_->visit(value);
4277 }
4278 private:
4279 TVisitor* visitor_;
4280 const ResourceManager* resources_;
4281};
4282template <typename TVisitor>
4283typename TVisitor::result_type accept(JsonVariantConst variant,
4284 TVisitor& visit) {
4285 auto data = VariantAttorney::getData(variant);
4286 if (!data)
4287 return visit.visit(nullptr);
4288 auto resources = VariantAttorney::getResourceManager(variant);
4289 VisitorAdapter<TVisitor> adapter(visit, resources);
4290 return data->accept(adapter, resources);
4291}
4292struct ComparerBase : JsonVariantVisitor<CompareResult> {};
4293template <typename T, typename Enable = void>
4294struct Comparer;
4295template <typename T>
4296struct Comparer<T, enable_if_t<IsString<T>::value>> : ComparerBase {
4297 T rhs; // TODO: store adapted string?
4298 explicit Comparer(T value) : rhs(value) {}
4299 CompareResult visit(JsonString lhs) {
4300 int i = stringCompare(adaptString(rhs), adaptString(lhs));
4301 if (i < 0)
4302 return COMPARE_RESULT_GREATER;
4303 else if (i > 0)
4304 return COMPARE_RESULT_LESS;
4305 else
4306 return COMPARE_RESULT_EQUAL;
4307 }
4308 CompareResult visit(nullptr_t) {
4309 if (adaptString(rhs).isNull())
4310 return COMPARE_RESULT_EQUAL;
4311 else
4312 return COMPARE_RESULT_DIFFER;
4313 }
4314 using ComparerBase::visit;
4315};
4316template <typename T>
4317struct Comparer<
4318 T, enable_if_t<is_integral<T>::value || is_floating_point<T>::value>>
4319 : ComparerBase {
4320 T rhs;
4321 explicit Comparer(T value) : rhs(value) {}
4322 template <typename U>
4323 enable_if_t<is_floating_point<U>::value || is_integral<U>::value,
4324 CompareResult>
4325 visit(const U& lhs) {
4326 return arithmeticCompare(lhs, rhs);
4327 }
4328 template <typename U>
4329 enable_if_t<!is_floating_point<U>::value && !is_integral<U>::value,
4330 CompareResult>
4331 visit(const U& lhs) {
4332 return ComparerBase::visit(lhs);
4333 }
4334};
4335struct NullComparer : ComparerBase {
4336 CompareResult visit(nullptr_t) {
4337 return COMPARE_RESULT_EQUAL;
4338 }
4339 using ComparerBase::visit;
4340};
4341template <>
4342struct Comparer<nullptr_t, void> : NullComparer {
4343 explicit Comparer(nullptr_t) : NullComparer() {}
4344};
4345struct ArrayComparer : ComparerBase {
4346 JsonArrayConst rhs_;
4347 explicit ArrayComparer(JsonArrayConst rhs) : rhs_(rhs) {}
4348 CompareResult visit(JsonArrayConst lhs) {
4349 if (rhs_ == lhs)
4350 return COMPARE_RESULT_EQUAL;
4351 else
4352 return COMPARE_RESULT_DIFFER;
4353 }
4354 using ComparerBase::visit;
4355};
4356struct ObjectComparer : ComparerBase {
4357 JsonObjectConst rhs_;
4358 explicit ObjectComparer(JsonObjectConst rhs) : rhs_(rhs) {}
4359 CompareResult visit(JsonObjectConst lhs) {
4360 if (lhs == rhs_)
4361 return COMPARE_RESULT_EQUAL;
4362 else
4363 return COMPARE_RESULT_DIFFER;
4364 }
4365 using ComparerBase::visit;
4366};
4367struct RawComparer : ComparerBase {
4368 RawString rhs_;
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);
4373 if (n < 0)
4374 return COMPARE_RESULT_LESS;
4375 else if (n > 0)
4376 return COMPARE_RESULT_GREATER;
4377 else
4378 return COMPARE_RESULT_EQUAL;
4379 }
4380 using ComparerBase::visit;
4381};
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);
4388 }
4389 CompareResult visit(JsonObjectConst lhs) {
4390 ObjectComparer comparer(lhs);
4391 return reverseResult(comparer);
4392 }
4393 CompareResult visit(JsonFloat lhs) {
4394 Comparer<JsonFloat> comparer(lhs);
4395 return reverseResult(comparer);
4396 }
4397 CompareResult visit(JsonString lhs) {
4398 Comparer<JsonString> comparer(lhs);
4399 return reverseResult(comparer);
4400 }
4401 CompareResult visit(RawString value) {
4402 RawComparer comparer(value);
4403 return reverseResult(comparer);
4404 }
4405 CompareResult visit(JsonInteger lhs) {
4406 Comparer<JsonInteger> comparer(lhs);
4407 return reverseResult(comparer);
4408 }
4409 CompareResult visit(JsonUInt lhs) {
4410 Comparer<JsonUInt> comparer(lhs);
4411 return reverseResult(comparer);
4412 }
4413 CompareResult visit(bool lhs) {
4414 Comparer<bool> comparer(lhs);
4415 return reverseResult(comparer);
4416 }
4417 CompareResult visit(nullptr_t) {
4418 NullComparer comparer;
4419 return reverseResult(comparer);
4420 }
4421 private:
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;
4430 default:
4431 return reversedResult;
4432 }
4433 }
4434};
4435template <typename T>
4436struct Comparer<
4437 T, enable_if_t<is_convertible<T, FLArduinoJson::JsonVariantConst>::value>>
4438 : VariantComparer {
4439 explicit Comparer(const T& value)
4440 : VariantComparer(static_cast<JsonVariantConst>(value)) {}
4441};
4442template <typename T>
4443CompareResult compare(FLArduinoJson::JsonVariantConst lhs, const T& rhs) {
4444 Comparer<T> comparer(rhs);
4445 return accept(lhs, comparer);
4446}
4447inline ArrayData::iterator ArrayData::at(
4448 size_t index, const ResourceManager* resources) const {
4449 auto it = createIterator(resources);
4450 while (!it.done() && index) {
4451 it.next(resources);
4452 --index;
4453 }
4454 return it;
4455}
4456inline VariantData* ArrayData::addElement(ResourceManager* resources) {
4457 auto slot = resources->allocVariant();
4458 if (!slot)
4459 return nullptr;
4460 CollectionData::appendOne(slot, resources);
4461 return slot.ptr();
4462}
4463inline VariantData* ArrayData::getOrAddElement(size_t index,
4464 ResourceManager* resources) {
4465 auto it = createIterator(resources);
4466 while (!it.done() && index > 0) {
4467 it.next(resources);
4468 index--;
4469 }
4470 if (it.done())
4471 index++;
4472 VariantData* element = it.data();
4473 while (index > 0) {
4474 element = addElement(resources);
4475 if (!element)
4476 return nullptr;
4477 index--;
4478 }
4479 return element;
4480}
4481inline VariantData* ArrayData::getElement(
4482 size_t index, const ResourceManager* resources) const {
4483 return at(index, resources).data();
4484}
4485inline void ArrayData::removeElement(size_t index, ResourceManager* resources) {
4486 remove(at(index, resources), resources);
4487}
4488template <typename T>
4489inline bool ArrayData::addValue(T&& value, ResourceManager* resources) {
4490 ARDUINOJSON_ASSERT(resources != nullptr);
4491 auto slot = resources->allocVariant();
4492 if (!slot)
4493 return false;
4494 JsonVariant variant(slot.ptr(), resources);
4495 if (!variant.set(detail::forward<T>(value))) {
4496 resources->freeVariant(slot);
4497 return false;
4498 }
4499 CollectionData::appendOne(slot, resources);
4500 return true;
4501}
4502constexpr size_t sizeofArray(size_t n) {
4503 return n * ResourceManager::slotSize;
4504}
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);
4511}
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);
4517}
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) {
4522 bool ok = true;
4523 for (size_t i = 0; i < len; i++) {
4524 ok &= copyArray(src[i], dst.template add<JsonVariant>());
4525 }
4526 return ok;
4527}
4528template <typename TDestination>
4529inline bool copyArray(const char* src, size_t, const TDestination& dst) {
4530 return dst.set(src);
4531}
4532template <typename T>
4533inline bool copyArray(const T& src, JsonDocument& dst) {
4534 return copyArray(src, dst.to<JsonArray>());
4535}
4536template <typename T>
4537inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
4538 return copyArray(src, len, dst.to<JsonArray>());
4539}
4540template <typename T>
4541inline detail::enable_if_t<!detail::is_array<T>::value, size_t> copyArray(
4542 JsonVariantConst src, T& dst) {
4543 dst = src.as<T>();
4544 return 1;
4545}
4546template <typename T, size_t N>
4547inline size_t copyArray(JsonArrayConst src, T (&dst)[N]) {
4548 return copyArray(src, dst, N);
4549}
4550template <typename T>
4551inline size_t copyArray(JsonArrayConst src, T* dst, size_t len) {
4552 size_t i = 0;
4553 for (JsonArrayConst::iterator it = src.begin(); it != src.end() && i < len;
4554 ++it)
4555 copyArray(*it, dst[i++]);
4556 return i;
4557}
4558template <size_t N>
4559inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) {
4560 JsonString s = src;
4561 size_t len = N - 1;
4562 if (len > s.size())
4563 len = s.size();
4564 memcpy(dst, s.c_str(), len);
4565 dst[len] = 0;
4566 return 1;
4567}
4568template <typename TSource, typename T>
4569inline detail::enable_if_t<detail::is_array<T>::value &&
4570 detail::is_base_of<JsonDocument, TSource>::value,
4571 size_t>
4572copyArray(const TSource& src, T& dst) {
4573 return copyArray(src.template as<JsonArrayConst>(), dst);
4574}
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;
4582}
4583inline size_t addPadding(size_t bytes) {
4584 const size_t mask = sizeof(void*) - 1;
4585 return (bytes + mask) & ~mask;
4586}
4587template <size_t bytes>
4588struct AddPadding {
4589 static const size_t mask = sizeof(void*) - 1;
4590 static const size_t value = (bytes + mask) & ~mask;
4591};
4592#else
4593inline bool isAligned(size_t) {
4594 return true;
4595}
4596inline size_t addPadding(size_t bytes) {
4597 return bytes;
4598}
4599template <size_t bytes>
4600struct AddPadding {
4601 static const size_t value = bytes;
4602};
4603#endif
4604template <typename T>
4605inline bool isAligned(T* ptr) {
4606 return isAligned(reinterpret_cast<size_t>(ptr));
4607}
4608template <typename T>
4609inline T* addPadding(T* p) {
4610 size_t address = addPadding(reinterpret_cast<size_t>(p));
4611 return reinterpret_cast<T*>(address);
4612}
4613inline CollectionIterator::CollectionIterator(VariantData* slot, SlotId slotId)
4614 : slot_(slot), currentId_(slotId) {
4615 nextId_ = slot_ ? slot_->next() : NULL_SLOT;
4616}
4617inline void CollectionIterator::next(const ResourceManager* resources) {
4618 ARDUINOJSON_ASSERT(currentId_ != NULL_SLOT);
4619 slot_ = resources->getVariant(nextId_);
4620 currentId_ = nextId_;
4621 if (slot_)
4622 nextId_ = slot_->next();
4623}
4624inline CollectionData::iterator CollectionData::createIterator(
4625 const ResourceManager* resources) const {
4626 return iterator(resources->getVariant(head_), head_);
4627}
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());
4633 tail_ = slot.id();
4634 } else {
4635 head_ = slot.id();
4636 tail_ = slot.id();
4637 }
4638}
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());
4646 tail_ = value.id();
4647 } else {
4648 head_ = key.id();
4649 tail_ = value.id();
4650 }
4651}
4652inline void CollectionData::clear(ResourceManager* resources) {
4653 auto next = head_;
4654 while (next != NULL_SLOT) {
4655 auto currId = next;
4656 auto slot = resources->getVariant(next);
4657 next = slot->next();
4658 resources->freeVariant({slot, currId});
4659 }
4660 head_ = NULL_SLOT;
4661 tail_ = NULL_SLOT;
4662}
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)
4670 break;
4671 prev = Slot<VariantData>(currentSlot, currentId);
4672 currentId = currentSlot->next();
4673 }
4674 return prev;
4675}
4676inline void CollectionData::removeOne(iterator it, ResourceManager* resources) {
4677 if (it.done())
4678 return;
4679 auto curr = it.slot_;
4680 auto prev = getPreviousSlot(curr, resources);
4681 auto next = curr->next();
4682 if (prev)
4683 prev->setNext(next);
4684 else
4685 head_ = next;
4686 if (next == NULL_SLOT)
4687 tail_ = prev.id();
4688 resources->freeVariant({it.slot_, it.currentId_});
4689}
4690inline void CollectionData::removePair(ObjectData::iterator it,
4691 ResourceManager* resources) {
4692 if (it.done())
4693 return;
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);
4700}
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;
4707 }
4708 return maxChildNesting + 1;
4709}
4710inline size_t CollectionData::size(const ResourceManager* resources) const {
4711 size_t count = 0;
4712 for (auto it = createIterator(resources); !it.done(); it.next(resources))
4713 count++;
4714 return count;
4715}
4716inline Slot<VariantData> ResourceManager::allocVariant() {
4717 auto p = variantPools_.allocSlot(allocator_);
4718 if (!p) {
4719 overflowed_ = true;
4720 return {};
4721 }
4722 return {new (&p->variant) VariantData, p.id()};
4723}
4724inline void ResourceManager::freeVariant(Slot<VariantData> variant) {
4725 variant->clear(this);
4726 variantPools_.freeSlot({alias_cast<SlotData*>(variant.ptr()), variant.id()});
4727}
4728inline VariantData* ResourceManager::getVariant(SlotId id) const {
4729 return reinterpret_cast<VariantData*>(variantPools_.getSlot(id));
4730}
4731#if ARDUINOJSON_USE_EXTENSIONS
4732inline Slot<VariantExtension> ResourceManager::allocExtension() {
4733 auto p = variantPools_.allocSlot(allocator_);
4734 if (!p) {
4735 overflowed_ = true;
4736 return {};
4737 }
4738 return {&p->extension, p.id()};
4739}
4740inline void ResourceManager::freeExtension(SlotId id) {
4741 auto p = getExtension(id);
4742 variantPools_.freeSlot({reinterpret_cast<SlotData*>(p), id});
4743}
4744inline VariantExtension* ResourceManager::getExtension(SlotId id) const {
4745 return &variantPools_.getSlot(id)->extension;
4746}
4747#endif
4748template <typename TAdaptedString>
4749inline VariantData* ObjectData::getMember(
4750 TAdaptedString key, const ResourceManager* resources) const {
4751 auto it = findKey(key, resources);
4752 if (it.done())
4753 return nullptr;
4754 it.next(resources);
4755 return it.data();
4756}
4757template <typename TAdaptedString>
4758VariantData* ObjectData::getOrAddMember(TAdaptedString key,
4759 ResourceManager* resources) {
4760 auto data = getMember(key, resources);
4761 if (data)
4762 return data;
4763 return addMember(key, resources);
4764}
4765template <typename TAdaptedString>
4766inline ObjectData::iterator ObjectData::findKey(
4767 TAdaptedString key, const ResourceManager* resources) const {
4768 if (key.isNull())
4769 return iterator();
4770 bool isKey = true;
4771 for (auto it = createIterator(resources); !it.done(); it.next(resources)) {
4772 if (isKey && stringEquals(key, adaptString(it->asString())))
4773 return it;
4774 isKey = !isKey;
4775 }
4776 return iterator();
4777}
4778template <typename TAdaptedString>
4779inline void ObjectData::removeMember(TAdaptedString key,
4780 ResourceManager* resources) {
4781 remove(findKey(key, resources), resources);
4782}
4783template <typename TAdaptedString>
4784inline VariantData* ObjectData::addMember(TAdaptedString key,
4785 ResourceManager* resources) {
4786 auto keySlot = resources->allocVariant();
4787 if (!keySlot)
4788 return nullptr;
4789 auto valueSlot = resources->allocVariant();
4790 if (!valueSlot)
4791 return nullptr;
4792 if (!keySlot->setString(key, resources))
4793 return nullptr;
4794 CollectionData::appendPair(keySlot, valueSlot, resources);
4795 return valueSlot.ptr();
4796}
4797constexpr size_t sizeofObject(size_t n) {
4798 return 2 * n * ResourceManager::slotSize;
4799}
4800class EscapeSequence {
4801 public:
4802 static char escapeChar(char c) {
4803 const char* p = escapeTable(true);
4804 while (p[0] && p[1] != c) {
4805 p += 2;
4806 }
4807 return p[0];
4808 }
4809 static char unescapeChar(char c) {
4810 const char* p = escapeTable(false);
4811 for (;;) {
4812 if (p[0] == '\0')
4813 return 0;
4814 if (p[0] == c)
4815 return p[1];
4816 p += 2;
4817 }
4818 }
4819 private:
4820 static const char* escapeTable(bool isSerializing) {
4821 return &"//''\"\"\\\\b\bf\fn\nr\rt\t"[isSerializing ? 4 : 0];
4822 }
4823};
4824struct FloatParts {
4825 uint32_t integral;
4826 uint32_t decimal;
4827 int16_t exponent;
4828 int8_t decimalPlaces;
4829};
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);
4841 }
4842 bit >>= 1;
4843 }
4844 }
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);
4850 }
4851 bit >>= 1;
4852 }
4853 }
4854 return powersOf10;
4855}
4856constexpr uint32_t pow10(int exponent) {
4857 return (exponent == 0) ? 1 : 10 * pow10(exponent - 1);
4858}
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;
4865 decimalPlaces--;
4866 }
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) {
4873 decimal = 0;
4874 integral++;
4875 if (exponent && integral >= 10) {
4876 exponent++;
4877 integral = 1;
4878 }
4879 }
4880 while (decimal % 10 == 0 && decimalPlaces > 0) {
4881 decimal /= 10;
4882 decimalPlaces--;
4883 }
4884 return {integral, decimal, exponent, decimalPlaces};
4885}
4886template <typename TWriter>
4887class CountingDecorator {
4888 public:
4889 explicit CountingDecorator(TWriter& writer) : writer_(writer), count_(0) {}
4890 void write(uint8_t c) {
4891 count_ += writer_.write(c);
4892 }
4893 void write(const uint8_t* s, size_t n) {
4894 count_ += writer_.write(s, n);
4895 }
4896 size_t count() const {
4897 return count_;
4898 }
4899 private:
4900 TWriter writer_;
4901 size_t count_;
4902};
4903template <typename TWriter>
4904class TextFormatter {
4905 public:
4906 explicit TextFormatter(TWriter writer) : writer_(writer) {}
4907 TextFormatter& operator=(const TextFormatter&) = delete;
4908 size_t bytesWritten() const {
4909 return writer_.count();
4910 }
4911 void writeBoolean(bool value) {
4912 if (value)
4913 writeRaw("true");
4914 else
4915 writeRaw("false");
4916 }
4917 void writeString(const char* value) {
4918 ARDUINOJSON_ASSERT(value != NULL);
4919 writeRaw('\"');
4920 while (*value)
4921 writeChar(*value++);
4922 writeRaw('\"');
4923 }
4924 void writeString(const char* value, size_t n) {
4925 ARDUINOJSON_ASSERT(value != NULL);
4926 writeRaw('\"');
4927 while (n--)
4928 writeChar(*value++);
4929 writeRaw('\"');
4930 }
4931 void writeChar(char c) {
4932 char specialChar = EscapeSequence::escapeChar(c);
4933 if (specialChar) {
4934 writeRaw('\\');
4935 writeRaw(specialChar);
4936 } else if (c) {
4937 writeRaw(c);
4938 } else {
4939 writeRaw("\\u0000");
4940 }
4941 }
4942 template <typename T>
4943 void writeFloat(T value) {
4944 writeFloat(JsonFloat(value), sizeof(T) >= 8 ? 9 : 6);
4945 }
4946 void writeFloat(JsonFloat value, int8_t decimalPlaces) {
4947 if (isnan(value))
4948 return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
4949#if ARDUINOJSON_ENABLE_INFINITY
4950 if (value < 0.0) {
4951 writeRaw('-');
4952 value = -value;
4953 }
4954 if (isinf(value))
4955 return writeRaw("Infinity");
4956#else
4957 if (isinf(value))
4958 return writeRaw("null");
4959 if (value < 0.0) {
4960 writeRaw('-');
4961 value = -value;
4962 }
4963#endif
4964 auto parts = decomposeFloat(value, decimalPlaces);
4965 writeInteger(parts.integral);
4966 if (parts.decimalPlaces)
4967 writeDecimals(parts.decimal, parts.decimalPlaces);
4968 if (parts.exponent) {
4969 writeRaw('e');
4970 writeInteger(parts.exponent);
4971 }
4972 }
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;
4977 if (value < 0) {
4978 writeRaw('-');
4979 unsigned_value = unsigned_type(unsigned_type(~value) + 1);
4980 } else {
4981 unsigned_value = unsigned_type(value);
4982 }
4983 writeInteger(unsigned_value);
4984 }
4985 template <typename T>
4986 enable_if_t<is_unsigned<T>::value> writeInteger(T value) {
4987 char buffer[22];
4988 char* end = buffer + sizeof(buffer);
4989 char* begin = end;
4990 do {
4991 *--begin = char(value % 10 + '0');
4992 value = T(value / 10);
4993 } while (value);
4994 writeRaw(begin, end);
4995 }
4996 void writeDecimals(uint32_t value, int8_t width) {
4997 char buffer[16];
4998 char* end = buffer + sizeof(buffer);
4999 char* begin = end;
5000 while (width--) {
5001 *--begin = char(value % 10 + '0');
5002 value /= 10;
5003 }
5004 *--begin = '.';
5005 writeRaw(begin, end);
5006 }
5007 void writeRaw(const char* s) {
5008 writer_.write(reinterpret_cast<const uint8_t*>(s), strlen(s));
5009 }
5010 void writeRaw(const char* s, size_t n) {
5011 writer_.write(reinterpret_cast<const uint8_t*>(s), n);
5012 }
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));
5016 }
5017 template <size_t N>
5018 void writeRaw(const char (&s)[N]) {
5019 writer_.write(reinterpret_cast<const uint8_t*>(s), N - 1);
5020 }
5021 void writeRaw(char c) {
5022 writer_.write(static_cast<uint8_t>(c));
5023 }
5024 protected:
5025 CountingDecorator<TWriter> writer_;
5026};
5027class DummyWriter {
5028 public:
5029 size_t write(uint8_t) {
5030 return 1;
5031 }
5032 size_t write(const uint8_t*, size_t n) {
5033 return n;
5034 }
5035};
5036template <template <typename> class TSerializer>
5037size_t measure(FLArduinoJson::JsonVariantConst source) {
5038 DummyWriter dp;
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);
5043}
5044template <typename TDestination, typename Enable = void>
5045class Writer {
5046 public:
5047 explicit Writer(TDestination& dest) : dest_(&dest) {}
5048 size_t write(uint8_t c) {
5049 return dest_->write(c);
5050 }
5051 size_t write(const uint8_t* s, size_t n) {
5052 return dest_->write(s, n);
5053 }
5054 private:
5055 TDestination* dest_;
5056};
5057class StaticStringWriter {
5058 public:
5059 StaticStringWriter(char* buf, size_t size) : end(buf + size), p(buf) {}
5060 size_t write(uint8_t c) {
5061 if (p >= end)
5062 return 0;
5063 *p++ = static_cast<char>(c);
5064 return 1;
5065 }
5066 size_t write(const uint8_t* s, size_t n) {
5067 char* begin = p;
5068 while (p < end && n > 0) {
5069 *p++ = static_cast<char>(*s++);
5070 n--;
5071 }
5072 return size_t(p - begin);
5073 }
5074 private:
5075 char* end;
5076 char* p;
5077};
5078ARDUINOJSON_END_PRIVATE_NAMESPACE
5079#if ARDUINOJSON_ENABLE_STD_STRING
5080ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5081template <class T, typename = void>
5082struct is_std_string : false_type {};
5083template <class T>
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 {
5087};
5088template <typename TDestination>
5089class Writer<TDestination, enable_if_t<is_std_string<TDestination>::value>> {
5090 public:
5091 Writer(TDestination& str) : str_(&str) {
5092 str.clear();
5093 }
5094 size_t write(uint8_t c) {
5095 str_->push_back(static_cast<char>(c));
5096 return 1;
5097 }
5098 size_t write(const uint8_t* s, size_t n) {
5099 str_->append(reinterpret_cast<const char*>(s), n);
5100 return n;
5101 }
5102 private:
5103 TDestination* str_;
5104};
5105ARDUINOJSON_END_PRIVATE_NAMESPACE
5106#endif
5107#if ARDUINOJSON_ENABLE_ARDUINO_STRING
5108ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5109template <>
5110class Writer<::String, void> {
5111 static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
5112 public:
5113 explicit Writer(::String& str) : destination_(&str), size_(0) {
5114 str = static_cast<const char*>(0);
5115 }
5116 ~Writer() {
5117 flush();
5118 }
5119 size_t write(uint8_t c) {
5120 if (size_ + 1 >= bufferCapacity)
5121 if (flush() != 0)
5122 return 0;
5123 buffer_[size_++] = static_cast<char>(c);
5124 return 1;
5125 }
5126 size_t write(const uint8_t* s, size_t n) {
5127 for (size_t i = 0; i < n; i++) {
5128 write(s[i]);
5129 }
5130 return n;
5131 }
5132 size_t flush() {
5133 ARDUINOJSON_ASSERT(size_ < bufferCapacity);
5134 buffer_[size_] = 0;
5135 if (destination_->concat(buffer_))
5136 size_ = 0;
5137 return size_;
5138 }
5139 private:
5140 ::String* destination_;
5141 char buffer_[bufferCapacity];
5142 size_t size_;
5143};
5144ARDUINOJSON_END_PRIVATE_NAMESPACE
5145#endif
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>> {
5151 public:
5152 explicit Writer(std::ostream& os) : os_(&os) {}
5153 size_t write(uint8_t c) {
5154 os_->put(static_cast<char>(c));
5155 return 1;
5156 }
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));
5160 return n;
5161 }
5162 private:
5163 std::ostream* os_;
5164};
5165ARDUINOJSON_END_PRIVATE_NAMESPACE
5166#endif
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>> {
5172 public:
5173 explicit Writer(::Print& print) : print_(&print) {}
5174 size_t write(uint8_t c) {
5175 return print_->write(c);
5176 }
5177 size_t write(const uint8_t* s, size_t n) {
5178 return print_->write(s, n);
5179 }
5180 private:
5181 ::Print* print_;
5182};
5183ARDUINOJSON_END_PRIVATE_NAMESPACE
5184#endif
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);
5192}
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);
5198}
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);
5204}
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);
5210 if (n < bufferSize)
5211 reinterpret_cast<char*>(buffer)[n] = 0;
5212 return n;
5213}
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);
5218}
5219template <typename TWriter>
5220class JsonSerializer : public VariantDataVisitor<size_t> {
5221 public:
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) {
5226 write('[');
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)
5233 write(',');
5234 }
5235 write(']');
5236 return bytesWritten();
5237 }
5238 size_t visit(const ObjectData& object) {
5239 write('{');
5240 auto slotId = object.head();
5241 bool isKey = true;
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 ? ':' : ',');
5248 isKey = !isKey;
5249 }
5250 write('}');
5251 return bytesWritten();
5252 }
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();
5257 }
5258 size_t visit(const char* value) {
5259 formatter_.writeString(value);
5260 return bytesWritten();
5261 }
5262 size_t visit(JsonString value) {
5263 formatter_.writeString(value.c_str(), value.size());
5264 return bytesWritten();
5265 }
5266 size_t visit(RawString value) {
5267 formatter_.writeRaw(value.data(), value.size());
5268 return bytesWritten();
5269 }
5270 size_t visit(JsonInteger value) {
5271 formatter_.writeInteger(value);
5272 return bytesWritten();
5273 }
5274 size_t visit(JsonUInt value) {
5275 formatter_.writeInteger(value);
5276 return bytesWritten();
5277 }
5278 size_t visit(bool value) {
5279 formatter_.writeBoolean(value);
5280 return bytesWritten();
5281 }
5282 size_t visit(nullptr_t) {
5283 formatter_.writeRaw("null");
5284 return bytesWritten();
5285 }
5286 protected:
5287 size_t bytesWritten() const {
5288 return formatter_.bytesWritten();
5289 }
5290 void write(char c) {
5291 formatter_.writeRaw(c);
5292 }
5293 void write(const char* s) {
5294 formatter_.writeRaw(s);
5295 }
5296 private:
5297 TextFormatter<TWriter> formatter_;
5298 protected:
5299 const ResourceManager* resources_;
5300};
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);
5308}
5309inline size_t serializeJson(JsonVariantConst source, void* buffer,
5310 size_t bufferSize) {
5311 using namespace detail;
5312 return serialize<JsonSerializer>(source, buffer, bufferSize);
5313}
5314inline size_t measureJson(JsonVariantConst source) {
5315 using namespace detail;
5316 return measure<JsonSerializer>(source);
5317}
5318#if ARDUINOJSON_ENABLE_STD_STREAM
5319template <typename T>
5320inline detail::enable_if_t<detail::is_convertible<T, JsonVariantConst>::value,
5321 std::ostream&>
5322operator<<(std::ostream& os, const T& source) {
5323 serializeJson(source, os);
5324 return os;
5325}
5326#endif
5327ARDUINOJSON_END_PUBLIC_NAMESPACE
5328ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5329class StringBuilder {
5330 public:
5331 static const size_t initialCapacity = 31;
5332 StringBuilder(ResourceManager* resources) : resources_(resources) {}
5333 ~StringBuilder() {
5334 if (node_)
5335 resources_->destroyString(node_);
5336 }
5337 void startString() {
5338 size_ = 0;
5339 if (!node_)
5340 node_ = resources_->createString(initialCapacity);
5341 }
5342 StringNode* save() {
5343 ARDUINOJSON_ASSERT(node_ != nullptr);
5344 node_->data[size_] = 0;
5345 StringNode* node = resources_->getString(adaptString(node_->data, size_));
5346 if (!node) {
5347 node = resources_->resizeString(node_, size_);
5348 ARDUINOJSON_ASSERT(node != nullptr); // realloc to smaller can't fail
5349 resources_->saveString(node);
5350 node_ = nullptr; // next time we need a new string
5351 } else {
5352 node->references++;
5353 }
5354 return node;
5355 }
5356 void append(const char* s) {
5357 while (*s)
5358 append(*s++);
5359 }
5360 void append(const char* s, size_t n) {
5361 while (n-- > 0) // TODO: memcpy
5362 append(*s++);
5363 }
5364 void append(char c) {
5365 if (node_ && size_ == node_->length)
5366 node_ = resources_->resizeString(node_, size_ * 2U + 1);
5367 if (node_)
5368 node_->data[size_++] = c;
5369 }
5370 bool isValid() const {
5371 return node_ != nullptr;
5372 }
5373 size_t size() const {
5374 return size_;
5375 }
5376 JsonString str() const {
5377 ARDUINOJSON_ASSERT(node_ != nullptr);
5378 node_->data[size_] = 0;
5379 return JsonString(node_->data, size_, JsonString::Copied);
5380 }
5381 private:
5382 ResourceManager* resources_;
5383 StringNode* node_ = nullptr;
5384 size_t size_ = 0;
5385};
5386ARDUINOJSON_END_PRIVATE_NAMESPACE
5387#if ARDUINOJSON_ENABLE_STD_STRING
5388#include <string>
5389#endif
5390#if ARDUINOJSON_ENABLE_STRING_VIEW
5391#include <string_view>
5392#endif
5393ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
5394template <typename T, typename Enable>
5395struct Converter {
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); // Error here? See https://arduinojson.org/v7/unsupported-set/
5401 }
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");
5405 T result; // Error here? See https://arduinojson.org/v7/non-default-constructible/
5406 convertFromJson(src, result); // Error here? See https://arduinojson.org/v7/unsupported-as/
5407 return result;
5408 }
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");
5412 T dummy = T();
5413 return canConvertFromJson(src, dummy); // Error here? See https://arduinojson.org/v7/unsupported-is/
5414 }
5415};
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);
5424 if (!data)
5425 return false;
5426 auto resources = getResourceManager(dst);
5427 data->clear(resources);
5428 return data->setInteger(src, resources);
5429 }
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();
5435 }
5436 static bool checkJson(JsonVariantConst src) {
5437 auto data = getData(src);
5438 auto resources = getResourceManager(src);
5439 return data && data->template isInteger<T>(resources);
5440 }
5441};
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));
5447 }
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))
5452 : T();
5453 }
5454 static bool checkJson(JsonVariantConst src) {
5455 auto data = getData(src);
5456 auto resources = getResourceManager(src);
5457 return data && data->template isInteger<int>(resources);
5458 }
5459};
5460template <>
5461struct Converter<bool> : private detail::VariantAttorney {
5462 static bool toJson(bool src, JsonVariant dst) {
5463 auto data = getData(dst);
5464 if (!data)
5465 return false;
5466 auto resources = getResourceManager(dst);
5467 data->clear(resources);
5468 data->setBoolean(src);
5469 return true;
5470 }
5471 static bool fromJson(JsonVariantConst src) {
5472 auto data = getData(src);
5473 auto resources = getResourceManager(src);
5474 return data ? data->asBoolean(resources) : false;
5475 }
5476 static bool checkJson(JsonVariantConst src) {
5477 auto data = getData(src);
5478 return data && data->isBoolean();
5479 }
5480};
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);
5486 if (!data)
5487 return false;
5488 auto resources = getResourceManager(dst);
5489 data->clear(resources);
5490 return data->setFloat(src, resources);
5491 }
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;
5496 }
5497 static bool checkJson(JsonVariantConst src) {
5498 auto data = getData(src);
5499 return data && data->isFloat();
5500 }
5501};
5502template <>
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));
5507 }
5508 static const char* fromJson(JsonVariantConst src) {
5509 auto data = getData(src);
5510 return data ? data->asString().c_str() : 0;
5511 }
5512 static bool checkJson(JsonVariantConst src) {
5513 auto data = getData(src);
5514 return data && data->isString();
5515 }
5516};
5517template <>
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));
5522 }
5523 static JsonString fromJson(JsonVariantConst src) {
5524 auto data = getData(src);
5525 return data ? data->asString() : 0;
5526 }
5527 static bool checkJson(JsonVariantConst src) {
5528 auto data = getData(src);
5529 return data && data->isString();
5530 }
5531};
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);
5539}
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));
5545 }
5546};
5547template <>
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));
5551 }
5552 static detail::nullptr_t fromJson(JsonVariantConst) {
5553 return nullptr;
5554 }
5555 static bool checkJson(JsonVariantConst src) {
5556 auto data = getData(src);
5557 return data == 0 || data->isNull();
5558 }
5559};
5560#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
5561namespace detail {
5562class StringBuilderPrint : public Print {
5563 public:
5564 StringBuilderPrint(ResourceManager* resources) : copier_(resources) {
5565 copier_.startString();
5566 }
5567 StringNode* save() {
5568 ARDUINOJSON_ASSERT(!overflowed());
5569 return copier_.save();
5570 }
5571 size_t write(uint8_t c) {
5572 copier_.append(char(c));
5573 return copier_.isValid() ? 1 : 0;
5574 }
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())
5579 return i;
5580 }
5581 return size;
5582 }
5583 bool overflowed() const {
5584 return !copier_.isValid();
5585 }
5586 private:
5587 StringBuilder copier_;
5588};
5589} // namespace detail
5590
5591// Modified to work when printable.h isn't present. -- Zach Vorhies.
5592template<typename Printable>
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)
5597 return;
5598 data->clear(resources);
5599 detail::StringBuilderPrint print(resources);
5600 src.printTo(print);
5601 if (print.overflowed())
5602 return;
5603 data->setOwnedString(print.save());
5604}
5605
5606#endif
5607#if ARDUINOJSON_ENABLE_ARDUINO_STRING
5608inline void convertFromJson(JsonVariantConst src, ::String& dst) {
5609 JsonString str = src.as<JsonString>();
5610 if (str)
5611 dst = str.c_str();
5612 else
5613 serializeJson(src, dst);
5614}
5615inline bool canConvertFromJson(JsonVariantConst src, const ::String&) {
5616 return src.is<JsonString>();
5617}
5618#endif
5619#if ARDUINOJSON_ENABLE_STD_STRING
5620inline void convertFromJson(JsonVariantConst src, std::string& dst) {
5621 JsonString str = src.as<JsonString>();
5622 if (str)
5623 dst.assign(str.c_str(), str.size());
5624 else
5625 serializeJson(src, dst);
5626}
5627inline bool canConvertFromJson(JsonVariantConst src, const std::string&) {
5628 return src.is<JsonString>();
5629}
5630#endif
5631#if ARDUINOJSON_ENABLE_STRING_VIEW
5632inline void convertFromJson(JsonVariantConst src, std::string_view& dst) {
5633 JsonString str = src.as<JsonString>();
5634 if (str) // the standard doesn't allow passing null to the constructor
5635 dst = std::string_view(str.c_str(), str.size());
5636}
5637inline bool canConvertFromJson(JsonVariantConst src, const std::string_view&) {
5638 return src.is<JsonString>();
5639}
5640#endif
5641template <>
5642struct Converter<JsonArrayConst> : private detail::VariantAttorney {
5643 static void toJson(JsonArrayConst src, JsonVariant dst) {
5644 if (src.isNull())
5645 dst.set(nullptr);
5646 else
5647 dst.to<JsonArray>().set(src);
5648 }
5649 static JsonArrayConst fromJson(JsonVariantConst src) {
5650 auto data = getData(src);
5651 auto array = data ? data->asArray() : nullptr;
5652 return JsonArrayConst(array, getResourceManager(src));
5653 }
5654 static bool checkJson(JsonVariantConst src) {
5655 auto data = getData(src);
5656 return data && data->isArray();
5657 }
5658};
5659template <>
5660struct Converter<JsonArray> : private detail::VariantAttorney {
5661 static void toJson(JsonVariantConst src, JsonVariant dst) {
5662 if (src.isNull())
5663 dst.set(nullptr);
5664 else
5665 dst.to<JsonArray>().set(src);
5666 }
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);
5671 }
5672 static bool checkJson(JsonVariant src) {
5673 auto data = getData(src);
5674 return data && data->isArray();
5675 }
5676};
5677template <>
5678struct Converter<JsonObjectConst> : private detail::VariantAttorney {
5679 static void toJson(JsonVariantConst src, JsonVariant dst) {
5680 if (src.isNull())
5681 dst.set(nullptr);
5682 else
5683 dst.to<JsonObject>().set(src);
5684 }
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));
5689 }
5690 static bool checkJson(JsonVariantConst src) {
5691 auto data = getData(src);
5692 return data && data->isObject();
5693 }
5694};
5695template <>
5696struct Converter<JsonObject> : private detail::VariantAttorney {
5697 static void toJson(JsonVariantConst src, JsonVariant dst) {
5698 if (src.isNull())
5699 dst.set(nullptr);
5700 else
5701 dst.to<JsonObject>().set(src);
5702 }
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);
5707 }
5708 static bool checkJson(JsonVariant src) {
5709 auto data = getData(src);
5710 return data && data->isObject();
5711 }
5712};
5713ARDUINOJSON_END_PUBLIC_NAMESPACE
5714ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5715class JsonVariantCopier {
5716 public:
5717 typedef bool result_type;
5718 JsonVariantCopier(JsonVariant dst) : dst_(dst) {}
5719 template <typename T>
5720 bool visit(T src) {
5721 return dst_.set(src);
5722 }
5723 private:
5724 JsonVariant dst_;
5725};
5726inline bool copyVariant(JsonVariant dst, JsonVariantConst src) {
5727 if (dst.isUnbound())
5728 return false;
5729 JsonVariantCopier copier(dst);
5730 return accept(src, copier);
5731}
5732template <typename T>
5733inline void VariantData::setRawString(SerializedValue<T> value,
5734 ResourceManager* resources) {
5735 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
5736 auto dup = resources->saveString(adaptString(value.data(), value.size()));
5737 if (dup)
5738 setRawString(dup);
5739}
5740template <typename TAdaptedString>
5741inline bool VariantData::setString(TAdaptedString value,
5742 ResourceManager* resources) {
5743 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
5744 if (value.isNull())
5745 return false;
5746 if (value.isLinked()) {
5747 setLinkedString(value.data());
5748 return true;
5749 }
5750 auto dup = resources->saveString(value);
5751 if (dup) {
5752 setOwnedString(dup);
5753 return true;
5754 }
5755 return false;
5756}
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);
5763#endif
5764 auto collection = asCollection();
5765 if (collection)
5766 collection->clear(resources);
5767 type_ = VariantType::Null;
5768}
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)
5774 : nullptr;
5775}
5776#endif
5777template <typename T>
5778enable_if_t<sizeof(T) == 8, bool> VariantData::setFloat(
5779 T value, ResourceManager* resources) {
5780 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
5781 (void)resources; // silence warning
5782 float valueAsFloat = static_cast<float>(value);
5783#if ARDUINOJSON_USE_DOUBLE
5784 if (value == valueAsFloat) {
5785 type_ = VariantType::Float;
5786 content_.asFloat = valueAsFloat;
5787 } else {
5788 auto extension = resources->allocExtension();
5789 if (!extension)
5790 return false;
5791 type_ = VariantType::Double;
5792 content_.asSlotId = extension.id();
5793 extension->asDouble = value;
5794 }
5795#else
5796 type_ = VariantType::Float;
5797 content_.asFloat = valueAsFloat;
5798#endif
5799 return true;
5800}
5801template <typename T>
5802enable_if_t<is_signed<T>::value, bool> VariantData::setInteger(
5803 T value, ResourceManager* resources) {
5804 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
5805 (void)resources; // silence warning
5806 if (canConvertNumber<int32_t>(value)) {
5807 type_ = VariantType::Int32;
5808 content_.asInt32 = static_cast<int32_t>(value);
5809 }
5810#if ARDUINOJSON_USE_LONG_LONG
5811 else {
5812 auto extension = resources->allocExtension();
5813 if (!extension)
5814 return false;
5815 type_ = VariantType::Int64;
5816 content_.asSlotId = extension.id();
5817 extension->asInt64 = value;
5818 }
5819#endif
5820 return true;
5821}
5822template <typename T>
5823enable_if_t<is_unsigned<T>::value, bool> VariantData::setInteger(
5824 T value, ResourceManager* resources) {
5825 ARDUINOJSON_ASSERT(type_ == VariantType::Null); // must call clear() first
5826 (void)resources; // silence warning
5827 if (canConvertNumber<uint32_t>(value)) {
5828 type_ = VariantType::Uint32;
5829 content_.asUint32 = static_cast<uint32_t>(value);
5830 }
5831#if ARDUINOJSON_USE_LONG_LONG
5832 else {
5833 auto extension = resources->allocExtension();
5834 if (!extension)
5835 return false;
5836 type_ = VariantType::Uint64;
5837 content_.asSlotId = extension.id();
5838 extension->asUint64 = value;
5839 }
5840#endif
5841 return true;
5842}
5843template <typename TDerived>
5844inline JsonVariant VariantRefBase<TDerived>::add() const {
5845 return add<JsonVariant>();
5846}
5847template <typename TDerived>
5848template <typename T>
5849inline T VariantRefBase<TDerived>::as() const {
5850 using variant_type = // JsonVariantConst or JsonVariant?
5851 typename function_traits<decltype(&Converter<T>::fromJson)>::arg1_type;
5852 return Converter<T>::fromJson(getVariant<variant_type>());
5853}
5854template <typename TDerived>
5855inline JsonArray VariantRefBase<TDerived>::createNestedArray() const {
5856 return add<JsonArray>();
5857}
5858template <typename TDerived>
5859template <typename TChar>
5860inline JsonArray VariantRefBase<TDerived>::createNestedArray(TChar* key) const {
5861 return operator[](key).template to<JsonArray>();
5862}
5863template <typename TDerived>
5864template <typename TString>
5865inline JsonArray VariantRefBase<TDerived>::createNestedArray(
5866 const TString& key) const {
5867 return operator[](key).template to<JsonArray>();
5868}
5869template <typename TDerived>
5870inline JsonObject VariantRefBase<TDerived>::createNestedObject() const {
5871 return add<JsonObject>();
5872}
5873template <typename TDerived>
5874template <typename TChar>
5875inline JsonObject VariantRefBase<TDerived>::createNestedObject(
5876 TChar* key) const {
5877 return operator[](key).template to<JsonObject>();
5878}
5879template <typename TDerived>
5880template <typename TString>
5881inline JsonObject VariantRefBase<TDerived>::createNestedObject(
5882 const TString& key) const {
5883 return operator[](key).template to<JsonObject>();
5884}
5885template <typename TDerived>
5886inline void convertToJson(const VariantRefBase<TDerived>& src,
5887 JsonVariant dst) {
5888 dst.set(src.template as<JsonVariantConst>());
5889}
5890template <typename TDerived>
5891template <typename T>
5892inline enable_if_t<is_same<T, JsonVariant>::value, T>
5893VariantRefBase<TDerived>::add() const {
5894 return JsonVariant(
5895 detail::VariantData::addElement(getOrCreateData(), getResourceManager()),
5896 getResourceManager());
5897}
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;
5904}
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;
5911}
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*>());
5917}
5918template <typename TDerived>
5919inline JsonVariant VariantRefBase<TDerived>::getVariant() const {
5920 return JsonVariant(getData(), getResourceManager());
5921}
5922template <typename TDerived>
5923inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant() const {
5924 return JsonVariant(getOrCreateData(), getResourceManager());
5925}
5926template <typename TDerived>
5927template <typename T>
5928inline bool VariantRefBase<TDerived>::is() const {
5929 using variant_type = // JsonVariantConst or JsonVariant?
5930 typename function_traits<decltype(&Converter<T>::checkJson)>::arg1_type;
5931 return Converter<T>::checkJson(getVariant<variant_type>());
5932}
5933template <typename TDerived>
5934inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
5935 size_t index) const {
5936 return ElementProxy<TDerived>(derived(), index);
5937}
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);
5943}
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);
5949}
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();
5956}
5957template <typename TDerived>
5958template <typename TConverter, typename T>
5959inline bool VariantRefBase<TDerived>::doSet(T&& value, true_type) const {
5960 return TConverter::toJson(value, getOrCreateVariant());
5961}
5962template <typename TDerived>
5963template <typename T>
5964inline enable_if_t<is_same<T, JsonArray>::value, JsonArray>
5965VariantRefBase<TDerived>::to() const {
5966 return JsonArray(
5967 VariantData::toArray(getOrCreateData(), getResourceManager()),
5968 getResourceManager());
5969}
5970template <typename TDerived>
5971template <typename T>
5972enable_if_t<is_same<T, JsonObject>::value, JsonObject>
5973VariantRefBase<TDerived>::to() const {
5974 return JsonObject(
5975 VariantData::toObject(getOrCreateData(), getResourceManager()),
5976 getResourceManager());
5977}
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);
5986}
5987ARDUINOJSON_END_PRIVATE_NAMESPACE
5988#if ARDUINOJSON_ENABLE_STD_STREAM
5989#endif
5990ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
5991class DeserializationError {
5992 public:
5993 enum Code {
5994 Ok,
5995 EmptyInput,
5996 IncompleteInput,
5997 InvalidInput,
5998 NoMemory,
5999 TooDeep
6000 };
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_;
6006 }
6007 friend bool operator!=(const DeserializationError& lhs,
6008 const DeserializationError& rhs) {
6009 return lhs.code_ != rhs.code_;
6010 }
6011 friend bool operator==(const DeserializationError& lhs, Code rhs) {
6012 return lhs.code_ == rhs;
6013 }
6014 friend bool operator==(Code lhs, const DeserializationError& rhs) {
6015 return lhs == rhs.code_;
6016 }
6017 friend bool operator!=(const DeserializationError& lhs, Code rhs) {
6018 return lhs.code_ != rhs;
6019 }
6020 friend bool operator!=(Code lhs, const DeserializationError& rhs) {
6021 return lhs != rhs.code_;
6022 }
6023 explicit operator bool() const {
6024 return code_ != Ok;
6025 }
6026 Code code() const {
6027 return code_;
6028 }
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_];
6036 }
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_));
6049 }
6050#endif
6051 private:
6052 Code code_;
6053};
6054#if ARDUINOJSON_ENABLE_STD_STREAM
6055inline std::ostream& operator<<(std::ostream& s,
6056 const DeserializationError& e) {
6057 s << e.c_str();
6058 return s;
6059}
6060inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
6061 s << DeserializationError(c).c_str();
6062 return s;
6063}
6064#endif
6065namespace DeserializationOption {
6066class Filter {
6067 public:
6068#if ARDUINOJSON_AUTO_SHRINK
6069 explicit Filter(JsonDocument& doc) : variant_(doc) {
6070 doc.shrinkToFit();
6071 }
6072#endif
6073 explicit Filter(JsonVariantConst variant) : variant_(variant) {}
6074 bool allow() const {
6075 return variant_;
6076 }
6077 bool allowArray() const {
6078 return variant_ == true || variant_.is<JsonArrayConst>();
6079 }
6080 bool allowObject() const {
6081 return variant_ == true || variant_.is<JsonObjectConst>();
6082 }
6083 bool allowValue() const {
6084 return variant_ == true;
6085 }
6086 template <typename TKey>
6087 Filter operator[](const TKey& key) const {
6088 if (variant_ == true) // "true" means "allow recursively"
6089 return *this;
6090 JsonVariantConst member = variant_[key];
6091 return Filter(member.isNull() ? variant_["*"] : member);
6092 }
6093 private:
6094 JsonVariantConst variant_;
6095};
6096} // namespace DeserializationOption
6097namespace detail {
6098struct AllowAllFilter {
6099 bool allow() const {
6100 return true;
6101 }
6102 bool allowArray() const {
6103 return true;
6104 }
6105 bool allowObject() const {
6106 return true;
6107 }
6108 bool allowValue() const {
6109 return true;
6110 }
6111 template <typename TKey>
6112 AllowAllFilter operator[](const TKey&) const {
6113 return AllowAllFilter();
6114 }
6115};
6116} // namespace detail
6117namespace DeserializationOption {
6118class NestingLimit {
6119 public:
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));
6125 }
6126 bool reached() const {
6127 return value_ == 0;
6128 }
6129 private:
6130 uint8_t value_;
6131};
6132} // namespace DeserializationOption
6133ARDUINOJSON_END_PUBLIC_NAMESPACE
6134ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
6135template <typename TFilter>
6136struct DeserializationOptions {
6137 TFilter filter;
6138 DeserializationOption::NestingLimit nestingLimit;
6139};
6140template <typename TFilter>
6141inline DeserializationOptions<TFilter> makeDeserializationOptions(
6142 TFilter filter, DeserializationOption::NestingLimit nestingLimit = {}) {
6143 return {filter, nestingLimit};
6144}
6145template <typename TFilter>
6146inline DeserializationOptions<TFilter> makeDeserializationOptions(
6147 DeserializationOption::NestingLimit nestingLimit, TFilter filter) {
6148 return {filter, nestingLimit};
6149}
6150inline DeserializationOptions<AllowAllFilter> makeDeserializationOptions(
6151 DeserializationOption::NestingLimit nestingLimit = {}) {
6152 return {{}, nestingLimit};
6153}
6154template <typename TSource, typename Enable = void>
6155struct Reader {
6156 public:
6157 Reader(TSource& source) : source_(&source) {}
6158 int read() {
6159 return source_->read(); // Error here? See https://arduinojson.org/v7/invalid-input/
6160 }
6161 size_t readBytes(char* buffer, size_t length) {
6162 return source_->readBytes(buffer, length);
6163 }
6164 private:
6165 TSource* source_;
6166};
6167template <typename TSource, typename Enable = void>
6168struct BoundedReader {
6169};
6170template <typename TIterator>
6171class IteratorReader {
6172 TIterator ptr_, end_;
6173 public:
6174 explicit IteratorReader(TIterator begin, TIterator end)
6175 : ptr_(begin), end_(end) {}
6176 int read() {
6177 if (ptr_ < end_)
6178 return static_cast<unsigned char>(*ptr_++);
6179 else
6180 return -1;
6181 }
6182 size_t readBytes(char* buffer, size_t length) {
6183 size_t i = 0;
6184 while (i < length && ptr_ < end_)
6185 buffer[i++] = *ptr_++;
6186 return i;
6187 }
6188};
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(),
6194 source.end()) {}
6195};
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;
6201};
6202template <typename T>
6203struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
6204template <typename TSource>
6205struct Reader<TSource*, enable_if_t<IsCharOrVoid<TSource>::value>> {
6206 const char* ptr_;
6207 public:
6208 explicit Reader(const void* ptr)
6209 : ptr_(ptr ? reinterpret_cast<const char*>(ptr) : "") {}
6210 int read() {
6211 return static_cast<unsigned char>(*ptr_++);
6212 }
6213 size_t readBytes(char* buffer, size_t length) {
6214 for (size_t i = 0; i < length; i++)
6215 buffer[i] = *ptr_++;
6216 return length;
6217 }
6218};
6219template <typename TSource>
6220struct BoundedReader<TSource*, enable_if_t<IsCharOrVoid<TSource>::value>>
6221 : public IteratorReader<const char*> {
6222 public:
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) {}
6226};
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*>()) {}
6232};
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>> {
6238 public:
6239 explicit Reader(Stream& stream) : stream_(&stream) {}
6240 int read() {
6241 char c;
6242 return stream_->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
6243 }
6244 size_t readBytes(char* buffer, size_t length) {
6245 return stream_->readBytes(buffer, length);
6246 }
6247 private:
6248 Stream* stream_;
6249};
6250ARDUINOJSON_END_PRIVATE_NAMESPACE
6251#endif
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()) {}
6259};
6260ARDUINOJSON_END_PRIVATE_NAMESPACE
6261#endif
6262#if ARDUINOJSON_ENABLE_PROGMEM
6263ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
6264template <>
6265struct Reader<const __FlashStringHelper*, void> {
6266 const char* ptr_;
6267 public:
6268 explicit Reader(const __FlashStringHelper* ptr)
6269 : ptr_(reinterpret_cast<const char*>(ptr)) {}
6270 int read() {
6271 return pgm_read_byte(ptr_++);
6272 }
6273 size_t readBytes(char* buffer, size_t length) {
6274 memcpy_P(buffer, ptr_, length);
6275 ptr_ += length;
6276 return length;
6277 }
6278};
6279template <>
6280struct BoundedReader<const __FlashStringHelper*, void> {
6281 const char* ptr_;
6282 const char* end_;
6283 public:
6284 explicit BoundedReader(const __FlashStringHelper* ptr, size_t size)
6285 : ptr_(reinterpret_cast<const char*>(ptr)), end_(ptr_ + size) {}
6286 int read() {
6287 if (ptr_ < end_)
6288 return pgm_read_byte(ptr_++);
6289 else
6290 return -1;
6291 }
6292 size_t readBytes(char* buffer, size_t length) {
6293 size_t available = static_cast<size_t>(end_ - ptr_);
6294 if (available < length)
6295 length = available;
6296 memcpy_P(buffer, ptr_, length);
6297 ptr_ += length;
6298 return length;
6299 }
6300};
6301ARDUINOJSON_END_PRIVATE_NAMESPACE
6302#endif
6303#if ARDUINOJSON_ENABLE_STD_STREAM
6304#include <istream>
6305ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
6306template <typename TSource>
6307struct Reader<TSource, enable_if_t<is_base_of<std::istream, TSource>::value>> {
6308 public:
6309 explicit Reader(std::istream& stream) : stream_(&stream) {}
6310 int read() {
6311 return stream_->get();
6312 }
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());
6316 }
6317 private:
6318 std::istream* stream_;
6319};
6320ARDUINOJSON_END_PRIVATE_NAMESPACE
6321#endif
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)};
6326}
6327template <typename TChar>
6328BoundedReader<TChar*> makeReader(TChar* input, size_t inputSize) {
6329 return BoundedReader<TChar*>{input, inputSize};
6330}
6331template <typename...>
6332struct first_or_void {
6333 using type = void;
6334};
6335template <typename T, typename... Rest>
6336struct first_or_void<T, Rest...> {
6337 using type = T;
6338};
6339template <class T, class = void>
6340struct is_deserialize_destination : false_type {};
6341template <class T>
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&) {
6348}
6349#if ARDUINOJSON_AUTO_SHRINK
6350inline void shrinkJsonDocument(JsonDocument& doc) {
6351 doc.shrinkToFit();
6352}
6353#endif
6354template <template <typename> class TDeserializer, typename TDestination,
6355 typename TReader, typename TOptions>
6356DeserializationError doDeserialize(TDestination&& dst, TReader reader,
6357 TOptions options) {
6358 auto data = VariantAttorney::getOrCreateData(dst);
6359 if (!data)
6360 return DeserializationError::NoMemory;
6361 auto resources = VariantAttorney::getResourceManager(dst);
6362 dst.clear();
6363 auto err = TDeserializer<TReader>(resources, reader)
6364 .parse(*data, options.filter, options.nestingLimit);
6365 shrinkJsonDocument(dst);
6366 return err;
6367}
6368template <template <typename> class TDeserializer, typename TDestination,
6369 typename TStream, typename... Args,
6370 typename = enable_if_t< // issue #1897
6371 !is_integral<typename first_or_void<Args...>::type>::value>>
6372DeserializationError deserialize(TDestination&& dst, TStream&& input,
6373 Args... args) {
6374 return doDeserialize<TDeserializer>(
6375 dst, makeReader(detail::forward<TStream>(input)),
6376 makeDeserializationOptions(args...));
6377}
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...));
6385}
6386template <typename TReader>
6387class Latch {
6388 public:
6389 Latch(TReader reader) : reader_(reader), loaded_(false) {
6390#if ARDUINOJSON_DEBUG
6391 ended_ = false;
6392#endif
6393 }
6394 void clear() {
6395 loaded_ = false;
6396 }
6397 int last() const {
6398 return current_;
6399 }
6400 FORCE_INLINE char current() {
6401 if (!loaded_) {
6402 load();
6403 }
6404 return current_;
6405 }
6406 private:
6407 void load() {
6408 ARDUINOJSON_ASSERT(!ended_);
6409 int c = reader_.read();
6410#if ARDUINOJSON_DEBUG
6411 if (c <= 0)
6412 ended_ = true;
6413#endif
6414 current_ = static_cast<char>(c > 0 ? c : 0);
6415 loaded_ = true;
6416 }
6417 TReader reader_;
6418 char current_; // NOLINT(clang-analyzer-optin.cplusplus.UninitializedObject)
6419 bool loaded_;
6420#if ARDUINOJSON_DEBUG
6421 bool ended_;
6422#endif
6423};
6424ARDUINOJSON_END_PRIVATE_NAMESPACE
6425#if defined(__GNUC__)
6426# if __GNUC__ >= 7
6427# pragma GCC diagnostic push
6428# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
6429# endif
6430#endif
6431ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
6432namespace Utf16 {
6433inline bool isHighSurrogate(uint16_t codeunit) {
6434 return codeunit >= 0xD800 && codeunit < 0xDC00;
6435}
6436inline bool isLowSurrogate(uint16_t codeunit) {
6437 return codeunit >= 0xDC00 && codeunit < 0xE000;
6438}
6439class Codepoint {
6440 public:
6441 Codepoint() : highSurrogate_(0), codepoint_(0) {}
6442 bool append(uint16_t codeunit) {
6443 if (isHighSurrogate(codeunit)) {
6444 highSurrogate_ = codeunit & 0x3FF;
6445 return false;
6446 }
6447 if (isLowSurrogate(codeunit)) {
6448 codepoint_ =
6449 uint32_t(0x10000 + ((highSurrogate_ << 10) | (codeunit & 0x3FF)));
6450 return true;
6451 }
6452 codepoint_ = codeunit;
6453 return true;
6454 }
6455 uint32_t value() const {
6456 return codepoint_;
6457 }
6458 private:
6459 uint16_t highSurrogate_;
6460 uint32_t codepoint_;
6461};
6462} // namespace Utf16
6463ARDUINOJSON_END_PRIVATE_NAMESPACE
6464#if defined(__GNUC__)
6465# if __GNUC__ >= 8
6466# pragma GCC diagnostic pop
6467# endif
6468#endif
6469ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
6470namespace Utf8 {
6471template <typename TStringBuilder>
6472inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) {
6473 if (codepoint32 < 0x80) {
6474 str.append(char(codepoint32));
6475 } else {
6476 char buf[5];
6477 char* p = buf;
6478 *(p++) = 0;
6479 *(p++) = char((codepoint32 | 0x80) & 0xBF);
6480 uint16_t codepoint16 = uint16_t(codepoint32 >> 6);
6481 if (codepoint16 < 0x20) { // 0x800
6482 *(p++) = char(codepoint16 | 0xC0);
6483 } else {
6484 *(p++) = char((codepoint16 | 0x80) & 0xBF);
6485 codepoint16 = uint16_t(codepoint16 >> 6);
6486 if (codepoint16 < 0x10) { // 0x10000
6487 *(p++) = char(codepoint16 | 0xE0);
6488 } else {
6489 *(p++) = char((codepoint16 | 0x80) & 0xBF);
6490 codepoint16 = uint16_t(codepoint16 >> 6);
6491 *(p++) = char(codepoint16 | 0xF0);
6492 }
6493 }
6494 while (*(--p)) {
6495 str.append(*p);
6496 }
6497 }
6498}
6499} // namespace Utf8
6500#ifndef isdigit
6501inline bool isdigit(char c) {
6502 return '0' <= c && c <= '9';
6503}
6504#endif
6505inline bool issign(char c) {
6506 return '-' == c || c == '+';
6507}
6508template <typename A, typename B>
6509using largest_type = conditional_t<(sizeof(A) > sizeof(B)), A, B>;
6510enum class NumberType : uint8_t {
6511 Invalid,
6512 Float,
6513 SignedInteger,
6514 UnsignedInteger,
6515#if ARDUINOJSON_USE_DOUBLE
6516 Double,
6517#endif
6518};
6519union NumberValue {
6520 NumberValue() {}
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) {}
6526#endif
6527 JsonInteger asSignedInteger;
6528 JsonUInt asUnsignedInteger;
6529 float asFloat;
6530#if ARDUINOJSON_USE_DOUBLE
6531 double asDouble;
6532#endif
6533};
6534class Number {
6535 NumberType type_;
6536 NumberValue value_;
6537 public:
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) {}
6544#endif
6545 template <typename T>
6546 T convertTo() const {
6547 switch (type_) {
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);
6557#endif
6558 default:
6559 return T();
6560 }
6561 }
6562 NumberType type() const {
6563 return type_;
6564 }
6565 JsonInteger asSignedInteger() const {
6566 ARDUINOJSON_ASSERT(type_ == NumberType::SignedInteger);
6567 return value_.asSignedInteger;
6568 }
6569 JsonUInt asUnsignedInteger() const {
6570 ARDUINOJSON_ASSERT(type_ == NumberType::UnsignedInteger);
6571 return value_.asUnsignedInteger;
6572 }
6573 float asFloat() const {
6574 ARDUINOJSON_ASSERT(type_ == NumberType::Float);
6575 return value_.asFloat;
6576 }
6577#if ARDUINOJSON_USE_DOUBLE
6578 double asDouble() const {
6579 ARDUINOJSON_ASSERT(type_ == NumberType::Double);
6580 return value_.asDouble;
6581 }
6582#endif
6583};
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;
6590 switch (*s) {
6591 case '-':
6592 is_negative = true;
6593 s++;
6594 break;
6595 case '+':
6596 s++;
6597 break;
6598 }
6599#if ARDUINOJSON_ENABLE_NAN
6600 if (*s == 'n' || *s == 'N') {
6601 return Number(traits::nan());
6602 }
6603#endif
6604#if ARDUINOJSON_ENABLE_INFINITY
6605 if (*s == 'i' || *s == 'I') {
6606 return Number(is_negative ? -traits::inf() : traits::inf());
6607 }
6608#endif
6609 if (!isdigit(*s) && *s != '.')
6610 return Number();
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)
6617 break;
6618 mantissa *= 10;
6619 if (mantissa > maxUint - digit)
6620 break;
6621 mantissa += digit;
6622 s++;
6623 }
6624 if (*s == '\0') {
6625 if (is_negative) {
6626 const mantissa_t sintMantissaMax = mantissa_t(1)
6627 << (sizeof(JsonInteger) * 8 - 1);
6628 if (mantissa <= sintMantissaMax) {
6629 return Number(JsonInteger(~mantissa + 1));
6630 }
6631 } else {
6632 return Number(JsonUInt(mantissa));
6633 }
6634 }
6635 while (mantissa > traits::mantissa_max) {
6636 mantissa /= 10;
6637 exponent_offset++;
6638 }
6639 while (isdigit(*s)) {
6640 exponent_offset++;
6641 s++;
6642 }
6643 if (*s == '.') {
6644 s++;
6645 while (isdigit(*s)) {
6646 if (mantissa < traits::mantissa_max / 10) {
6647 mantissa = mantissa * 10 + uint8_t(*s - '0');
6648 exponent_offset--;
6649 }
6650 s++;
6651 }
6652 }
6653 int exponent = 0;
6654 if (*s == 'e' || *s == 'E') {
6655 s++;
6656 bool negative_exponent = false;
6657 if (*s == '-') {
6658 negative_exponent = true;
6659 s++;
6660 } else if (*s == '+') {
6661 s++;
6662 }
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);
6668 else
6669 return Number(is_negative ? -traits::inf() : traits::inf());
6670 }
6671 s++;
6672 }
6673 if (negative_exponent)
6674 exponent = -exponent;
6675 }
6676 exponent += exponent_offset;
6677 if (*s != '\0')
6678 return Number();
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;
6683 if (isDouble) {
6684 auto final_result = make_float(double(mantissa), exponent);
6685 return Number(is_negative ? -final_result : final_result);
6686 } else
6687#endif
6688 {
6689 auto final_result = make_float(float(mantissa), exponent);
6690 return Number(is_negative ? -final_result : final_result);
6691 }
6692}
6693template <typename T>
6694inline T parseNumber(const char* s) {
6695 return parseNumber(s).convertTo<T>();
6696}
6697template <typename TReader>
6698class JsonDeserializer {
6699 public:
6700 JsonDeserializer(ResourceManager* resources, TReader reader)
6701 : stringBuilder_(resources),
6702 foundSomething_(false),
6703 latch_(reader),
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;
6712 }
6713 return err;
6714 }
6715 private:
6716 char current() {
6717 return latch_.current();
6718 }
6719 void move() {
6720 latch_.clear();
6721 }
6722 bool eat(char charToSkip) {
6723 if (current() != charToSkip)
6724 return false;
6725 move();
6726 return true;
6727 }
6728 template <typename TFilter>
6729 DeserializationError::Code parseVariant(
6730 VariantData& variant, TFilter filter,
6731 DeserializationOption::NestingLimit nestingLimit) {
6732 DeserializationError::Code err;
6733 err = skipSpacesAndComments();
6734 if (err)
6735 return err;
6736 switch (current()) {
6737 case '[':
6738 if (filter.allowArray())
6739 return parseArray(variant.toArray(), filter, nestingLimit);
6740 else
6741 return skipArray(nestingLimit);
6742 case '{':
6743 if (filter.allowObject())
6744 return parseObject(variant.toObject(), filter, nestingLimit);
6745 else
6746 return skipObject(nestingLimit);
6747 case '\"':
6748 case '\'':
6749 if (filter.allowValue())
6750 return parseStringValue(variant);
6751 else
6752 return skipQuotedString();
6753 case 't':
6754 if (filter.allowValue())
6755 variant.setBoolean(true);
6756 return skipKeyword("true");
6757 case 'f':
6758 if (filter.allowValue())
6759 variant.setBoolean(false);
6760 return skipKeyword("false");
6761 case 'n':
6762 return skipKeyword("null");
6763 default:
6764 if (filter.allowValue())
6765 return parseNumericValue(variant);
6766 else
6767 return skipNumericValue();
6768 }
6769 }
6770 DeserializationError::Code skipVariant(
6771 DeserializationOption::NestingLimit nestingLimit) {
6772 DeserializationError::Code err;
6773 err = skipSpacesAndComments();
6774 if (err)
6775 return err;
6776 switch (current()) {
6777 case '[':
6778 return skipArray(nestingLimit);
6779 case '{':
6780 return skipObject(nestingLimit);
6781 case '\"':
6782 case '\'':
6783 return skipQuotedString();
6784 case 't':
6785 return skipKeyword("true");
6786 case 'f':
6787 return skipKeyword("false");
6788 case 'n':
6789 return skipKeyword("null");
6790 default:
6791 return skipNumericValue();
6792 }
6793 }
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() == '[');
6802 move();
6803 err = skipSpacesAndComments();
6804 if (err)
6805 return err;
6806 if (eat(']'))
6807 return DeserializationError::Ok;
6808 TFilter elementFilter = filter[0UL];
6809 for (;;) {
6810 if (elementFilter.allow()) {
6811 VariantData* value = array.addElement(resources_);
6812 if (!value)
6813 return DeserializationError::NoMemory;
6814 err = parseVariant(*value, elementFilter, nestingLimit.decrement());
6815 if (err)
6816 return err;
6817 } else {
6818 err = skipVariant(nestingLimit.decrement());
6819 if (err)
6820 return err;
6821 }
6822 err = skipSpacesAndComments();
6823 if (err)
6824 return err;
6825 if (eat(']'))
6826 return DeserializationError::Ok;
6827 if (!eat(','))
6828 return DeserializationError::InvalidInput;
6829 }
6830 }
6831 DeserializationError::Code skipArray(
6832 DeserializationOption::NestingLimit nestingLimit) {
6833 DeserializationError::Code err;
6834 if (nestingLimit.reached())
6835 return DeserializationError::TooDeep;
6836 ARDUINOJSON_ASSERT(current() == '[');
6837 move();
6838 for (;;) {
6839 err = skipVariant(nestingLimit.decrement());
6840 if (err)
6841 return err;
6842 err = skipSpacesAndComments();
6843 if (err)
6844 return err;
6845 if (eat(']'))
6846 return DeserializationError::Ok;
6847 if (!eat(','))
6848 return DeserializationError::InvalidInput;
6849 }
6850 }
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() == '{');
6859 move();
6860 err = skipSpacesAndComments();
6861 if (err)
6862 return err;
6863 if (eat('}'))
6864 return DeserializationError::Ok;
6865 for (;;) {
6866 err = parseKey();
6867 if (err)
6868 return err;
6869 err = skipSpacesAndComments();
6870 if (err)
6871 return err;
6872 if (!eat(':'))
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_);
6878 if (!member) {
6879 auto savedKey = stringBuilder_.save();
6880 member = object.addMember(savedKey, resources_);
6881 if (!member)
6882 return DeserializationError::NoMemory;
6883 } else {
6884 member->clear(resources_);
6885 }
6886 err = parseVariant(*member, memberFilter, nestingLimit.decrement());
6887 if (err)
6888 return err;
6889 } else {
6890 err = skipVariant(nestingLimit.decrement());
6891 if (err)
6892 return err;
6893 }
6894 err = skipSpacesAndComments();
6895 if (err)
6896 return err;
6897 if (eat('}'))
6898 return DeserializationError::Ok;
6899 if (!eat(','))
6900 return DeserializationError::InvalidInput;
6901 err = skipSpacesAndComments();
6902 if (err)
6903 return err;
6904 }
6905 }
6906 DeserializationError::Code skipObject(
6907 DeserializationOption::NestingLimit nestingLimit) {
6908 DeserializationError::Code err;
6909 if (nestingLimit.reached())
6910 return DeserializationError::TooDeep;
6911 ARDUINOJSON_ASSERT(current() == '{');
6912 move();
6913 err = skipSpacesAndComments();
6914 if (err)
6915 return err;
6916 if (eat('}'))
6917 return DeserializationError::Ok;
6918 for (;;) {
6919 err = skipKey();
6920 if (err)
6921 return err;
6922 err = skipSpacesAndComments();
6923 if (err)
6924 return err;
6925 if (!eat(':'))
6926 return DeserializationError::InvalidInput;
6927 err = skipVariant(nestingLimit.decrement());
6928 if (err)
6929 return err;
6930 err = skipSpacesAndComments();
6931 if (err)
6932 return err;
6933 if (eat('}'))
6934 return DeserializationError::Ok;
6935 if (!eat(','))
6936 return DeserializationError::InvalidInput;
6937 err = skipSpacesAndComments();
6938 if (err)
6939 return err;
6940 }
6941 }
6942 DeserializationError::Code parseKey() {
6943 stringBuilder_.startString();
6944 if (isQuote(current())) {
6945 return parseQuotedString();
6946 } else {
6947 return parseNonQuotedString();
6948 }
6949 }
6950 DeserializationError::Code parseStringValue(VariantData& variant) {
6951 DeserializationError::Code err;
6952 stringBuilder_.startString();
6953 err = parseQuotedString();
6954 if (err)
6955 return err;
6956 variant.setOwnedString(stringBuilder_.save());
6957 return DeserializationError::Ok;
6958 }
6959 DeserializationError::Code parseQuotedString() {
6960#if ARDUINOJSON_DECODE_UNICODE
6961 Utf16::Codepoint codepoint;
6962 DeserializationError::Code err;
6963#endif
6964 const char stopChar = current();
6965 move();
6966 for (;;) {
6967 char c = current();
6968 move();
6969 if (c == stopChar)
6970 break;
6971 if (c == '\0')
6972 return DeserializationError::IncompleteInput;
6973 if (c == '\\') {
6974 c = current();
6975 if (c == '\0')
6976 return DeserializationError::IncompleteInput;
6977 if (c == 'u') {
6978#if ARDUINOJSON_DECODE_UNICODE
6979 move();
6980 uint16_t codeunit;
6981 err = parseHex4(codeunit);
6982 if (err)
6983 return err;
6984 if (codepoint.append(codeunit))
6985 Utf8::encodeCodepoint(codepoint.value(), stringBuilder_);
6986#else
6987 stringBuilder_.append('\\');
6988#endif
6989 continue;
6990 }
6991 c = EscapeSequence::unescapeChar(c);
6992 if (c == '\0')
6993 return DeserializationError::InvalidInput;
6994 move();
6995 }
6996 stringBuilder_.append(c);
6997 }
6998 if (!stringBuilder_.isValid())
6999 return DeserializationError::NoMemory;
7000 return DeserializationError::Ok;
7001 }
7002 DeserializationError::Code parseNonQuotedString() {
7003 char c = current();
7004 ARDUINOJSON_ASSERT(c);
7005 if (canBeInNonQuotedString(c)) { // no quotes
7006 do {
7007 move();
7008 stringBuilder_.append(c);
7009 c = current();
7010 } while (canBeInNonQuotedString(c));
7011 } else {
7012 return DeserializationError::InvalidInput;
7013 }
7014 if (!stringBuilder_.isValid())
7015 return DeserializationError::NoMemory;
7016 return DeserializationError::Ok;
7017 }
7018 DeserializationError::Code skipKey() {
7019 if (isQuote(current())) {
7020 return skipQuotedString();
7021 } else {
7022 return skipNonQuotedString();
7023 }
7024 }
7025 DeserializationError::Code skipQuotedString() {
7026 const char stopChar = current();
7027 move();
7028 for (;;) {
7029 char c = current();
7030 move();
7031 if (c == stopChar)
7032 break;
7033 if (c == '\0')
7034 return DeserializationError::IncompleteInput;
7035 if (c == '\\') {
7036 if (current() != '\0')
7037 move();
7038 }
7039 }
7040 return DeserializationError::Ok;
7041 }
7042 DeserializationError::Code skipNonQuotedString() {
7043 char c = current();
7044 while (canBeInNonQuotedString(c)) {
7045 move();
7046 c = current();
7047 }
7048 return DeserializationError::Ok;
7049 }
7050 DeserializationError::Code parseNumericValue(VariantData& result) {
7051 uint8_t n = 0;
7052 char c = current();
7053 while (canBeInNumber(c) && n < 63) {
7054 move();
7055 buffer_[n++] = c;
7056 c = current();
7057 }
7058 buffer_[n] = 0;
7059 auto number = parseNumber(buffer_);
7060 switch (number.type()) {
7061 case NumberType::UnsignedInteger:
7062 if (result.setInteger(number.asUnsignedInteger(), resources_))
7063 return DeserializationError::Ok;
7064 else
7065 return DeserializationError::NoMemory;
7066 case NumberType::SignedInteger:
7067 if (result.setInteger(number.asSignedInteger(), resources_))
7068 return DeserializationError::Ok;
7069 else
7070 return DeserializationError::NoMemory;
7071 case NumberType::Float:
7072 if (result.setFloat(number.asFloat(), resources_))
7073 return DeserializationError::Ok;
7074 else
7075 return DeserializationError::NoMemory;
7076#if ARDUINOJSON_USE_DOUBLE
7077 case NumberType::Double:
7078 if (result.setFloat(number.asDouble(), resources_))
7079 return DeserializationError::Ok;
7080 else
7081 return DeserializationError::NoMemory;
7082#endif
7083 default:
7084 return DeserializationError::InvalidInput;
7085 }
7086 }
7087 DeserializationError::Code skipNumericValue() {
7088 char c = current();
7089 while (canBeInNumber(c)) {
7090 move();
7091 c = current();
7092 }
7093 return DeserializationError::Ok;
7094 }
7095 DeserializationError::Code parseHex4(uint16_t& result) {
7096 result = 0;
7097 for (uint8_t i = 0; i < 4; ++i) {
7098 char digit = current();
7099 if (!digit)
7100 return DeserializationError::IncompleteInput;
7101 uint8_t value = decodeHex(digit);
7102 if (value > 0x0F)
7103 return DeserializationError::InvalidInput;
7104 result = uint16_t((result << 4) | value);
7105 move();
7106 }
7107 return DeserializationError::Ok;
7108 }
7109 static inline bool isBetween(char c, char min, char max) {
7110 return min <= c && c <= max;
7111 }
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');
7116#else
7117 c == 'e' || c == 'E';
7118#endif
7119 }
7120 static inline bool canBeInNonQuotedString(char c) {
7121 return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
7122 isBetween(c, 'A', 'Z');
7123 }
7124 static inline bool isQuote(char c) {
7125 return c == '\'' || c == '\"';
7126 }
7127 static inline uint8_t decodeHex(char c) {
7128 if (c < 'A')
7129 return uint8_t(c - '0');
7130 c = char(c & ~0x20); // uppercase
7131 return uint8_t(c - 'A' + 10);
7132 }
7133 DeserializationError::Code skipSpacesAndComments() {
7134 for (;;) {
7135 switch (current()) {
7136 case '\0':
7137 return foundSomething_ ? DeserializationError::IncompleteInput
7138 : DeserializationError::EmptyInput;
7139 case ' ':
7140 case '\t':
7141 case '\r':
7142 case '\n':
7143 move();
7144 continue;
7145#if ARDUINOJSON_ENABLE_COMMENTS
7146 case '/':
7147 move(); // skip '/'
7148 switch (current()) {
7149 case '*': {
7150 move(); // skip '*'
7151 bool wasStar = false;
7152 for (;;) {
7153 char c = current();
7154 if (c == '\0')
7155 return DeserializationError::IncompleteInput;
7156 if (c == '/' && wasStar) {
7157 move();
7158 break;
7159 }
7160 wasStar = c == '*';
7161 move();
7162 }
7163 break;
7164 }
7165 case '/':
7166 for (;;) {
7167 move();
7168 char c = current();
7169 if (c == '\0')
7170 return DeserializationError::IncompleteInput;
7171 if (c == '\n')
7172 break;
7173 }
7174 break;
7175 default:
7176 return DeserializationError::InvalidInput;
7177 }
7178 break;
7179#endif
7180 default:
7181 foundSomething_ = true;
7182 return DeserializationError::Ok;
7183 }
7184 }
7185 }
7186 DeserializationError::Code skipKeyword(const char* s) {
7187 while (*s) {
7188 char c = current();
7189 if (c == '\0')
7190 return DeserializationError::IncompleteInput;
7191 if (*s != c)
7192 return DeserializationError::InvalidInput;
7193 ++s;
7194 move();
7195 }
7196 return DeserializationError::Ok;
7197 }
7198 StringBuilder stringBuilder_;
7199 bool foundSomething_;
7200 Latch<TReader> latch_;
7201 ResourceManager* resources_;
7202 char buffer_[64]; // using a member instead of a local variable because it
7203};
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)...);
7213}
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)...);
7221}
7222ARDUINOJSON_END_PUBLIC_NAMESPACE
7223ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
7224template <typename TWriter>
7225class PrettyJsonSerializer : public JsonSerializer<TWriter> {
7226 typedef JsonSerializer<TWriter> base;
7227 public:
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_);
7232 if (!it.done()) {
7233 base::write("[\r\n");
7234 nesting_++;
7235 while (!it.done()) {
7236 indent();
7237 it->accept(*this, base::resources_);
7238 it.next(base::resources_);
7239 base::write(it.done() ? "\r\n" : ",\r\n");
7240 }
7241 nesting_--;
7242 indent();
7243 base::write("]");
7244 } else {
7245 base::write("[]");
7246 }
7247 return this->bytesWritten();
7248 }
7249 size_t visit(const ObjectData& object) {
7250 auto it = object.createIterator(base::resources_);
7251 if (!it.done()) {
7252 base::write("{\r\n");
7253 nesting_++;
7254 bool isKey = true;
7255 while (!it.done()) {
7256 if (isKey)
7257 indent();
7258 it->accept(*this, base::resources_);
7259 it.next(base::resources_);
7260 if (isKey)
7261 base::write(": ");
7262 else
7263 base::write(it.done() ? "\r\n" : ",\r\n");
7264 isKey = !isKey;
7265 }
7266 nesting_--;
7267 indent();
7268 base::write("}");
7269 } else {
7270 base::write("{}");
7271 }
7272 return this->bytesWritten();
7273 }
7274 using base::visit;
7275 private:
7276 void indent() {
7277 for (uint8_t i = 0; i < nesting_; i++)
7278 base::write(ARDUINOJSON_TAB);
7279 }
7280 uint8_t nesting_;
7281};
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);
7289}
7290inline size_t serializeJsonPretty(JsonVariantConst source, void* buffer,
7291 size_t bufferSize) {
7292 using namespace FLArduinoJson::detail;
7293 return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
7294}
7295inline size_t measureJsonPretty(JsonVariantConst source) {
7296 using namespace FLArduinoJson::detail;
7297 return measure<PrettyJsonSerializer>(source);
7298}
7299class MsgPackBinary {
7300 public:
7301 MsgPackBinary() : data_(nullptr), size_(0) {}
7302 explicit MsgPackBinary(const void* c, size_t size) : data_(c), size_(size) {}
7303 const void* data() const {
7304 return data_;
7305 }
7306 size_t size() const {
7307 return size_;
7308 }
7309 private:
7310 const void* data_;
7311 size_t size_;
7312};
7313template <>
7314struct Converter<MsgPackBinary> : private detail::VariantAttorney {
7315 static void toJson(MsgPackBinary src, JsonVariant dst) {
7316 auto data = VariantAttorney::getData(dst);
7317 if (!data)
7318 return;
7319 auto resources = getResourceManager(dst);
7320 data->clear(resources);
7321 if (src.data()) {
7322 size_t headerSize = src.size() >= 0x10000 ? 5
7323 : src.size() >= 0x100 ? 3
7324 : 2;
7325 auto str = resources->createString(src.size() + headerSize);
7326 if (str) {
7327 resources->saveString(str);
7328 auto ptr = reinterpret_cast<uint8_t*>(str->data);
7329 switch (headerSize) {
7330 case 2:
7331 ptr[0] = uint8_t(0xc4);
7332 ptr[1] = uint8_t(src.size() & 0xff);
7333 break;
7334 case 3:
7335 ptr[0] = uint8_t(0xc5);
7336 ptr[1] = uint8_t(src.size() >> 8 & 0xff);
7337 ptr[2] = uint8_t(src.size() & 0xff);
7338 break;
7339 case 5:
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);
7345 break;
7346 default:
7347 ARDUINOJSON_ASSERT(false);
7348 }
7349 memcpy(ptr + headerSize, src.data(), src.size());
7350 data->setRawString(str);
7351 return;
7352 }
7353 }
7354 }
7355 static MsgPackBinary fromJson(JsonVariantConst src) {
7356 auto data = getData(src);
7357 if (!data)
7358 return {};
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) { // bin 8
7363 size_t size = p[1];
7364 if (size + 2 == n)
7365 return MsgPackBinary(p + 2, size);
7366 } else if (n >= 3 && p[0] == 0xc5) { // bin 16
7367 size_t size = size_t(p[1] << 8) | p[2];
7368 if (size + 3 == n)
7369 return MsgPackBinary(p + 3, size);
7370 } else if (n >= 5 && p[0] == 0xc6) { // bin 32
7371 size_t size =
7372 size_t(p[1] << 24) | size_t(p[2] << 16) | size_t(p[3] << 8) | p[4];
7373 if (size + 5 == n)
7374 return MsgPackBinary(p + 5, size);
7375 }
7376 return {};
7377 }
7378 static bool checkJson(JsonVariantConst src) {
7379 return fromJson(src).data() != nullptr;
7380 }
7381};
7382ARDUINOJSON_END_PUBLIC_NAMESPACE
7383ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
7384class StringBuffer {
7385 public:
7386 StringBuffer(ResourceManager* resources) : resources_(resources) {}
7387 ~StringBuffer() {
7388 if (node_)
7389 resources_->destroyString(node_);
7390 }
7391 char* reserve(size_t capacity) {
7392 if (node_ && capacity > node_->length) {
7393 resources_->destroyString(node_);
7394 node_ = nullptr;
7395 }
7396 if (!node_)
7397 node_ = resources_->createString(capacity);
7398 if (!node_)
7399 return nullptr;
7400 size_ = capacity;
7401 node_->data[capacity] = 0; // null-terminate the string
7402 return node_->data;
7403 }
7404 StringNode* save() {
7405 ARDUINOJSON_ASSERT(node_ != nullptr);
7406 node_->data[size_] = 0;
7407 auto node = resources_->getString(adaptString(node_->data, size_));
7408 if (node) {
7409 node->references++;
7410 return node;
7411 }
7412 if (node_->length != size_) {
7413 node = resources_->resizeString(node_, size_);
7414 ARDUINOJSON_ASSERT(node != nullptr); // realloc to smaller can't fail
7415 } else {
7416 node = node_;
7417 }
7418 node_ = nullptr;
7419 resources_->saveString(node);
7420 return node;
7421 }
7422 JsonString str() const {
7423 ARDUINOJSON_ASSERT(node_ != nullptr);
7424 return JsonString(node_->data, node_->length, JsonString::Copied);
7425 }
7426 private:
7427 ResourceManager* resources_;
7428 StringNode* node_ = nullptr;
7429 size_t size_ = 0;
7430};
7431#if ARDUINOJSON_LITTLE_ENDIAN
7432inline void swapBytes(uint8_t& a, uint8_t& b) {
7433 uint8_t t(a);
7434 a = b;
7435 b = t;
7436}
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]);
7442}
7443inline void fixEndianness(uint8_t* p, integral_constant<size_t, 4>) {
7444 swapBytes(p[0], p[3]);
7445 swapBytes(p[1], p[2]);
7446}
7447inline void fixEndianness(uint8_t* p, integral_constant<size_t, 2>) {
7448 swapBytes(p[0], p[1]);
7449}
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)>());
7455}
7456#else
7457template <typename T>
7458inline void fixEndianness(T&) {}
7459#endif
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));
7465}
7466template <typename TReader>
7467class MsgPackDeserializer {
7468 public:
7469 MsgPackDeserializer(ResourceManager* resources, TReader reader)
7470 : resources_(resources),
7471 reader_(reader),
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;
7480 }
7481 private:
7482 template <typename TFilter>
7483 DeserializationError::Code parseVariant(
7484 VariantData* variant, TFilter filter,
7485 DeserializationOption::NestingLimit nestingLimit) {
7486 DeserializationError::Code err;
7487 uint8_t header[5];
7488 err = readBytes(header, 1);
7489 if (err)
7490 return err;
7491 const uint8_t& code = header[0];
7492 foundSomething_ = true;
7493 bool allowValue = filter.allowValue();
7494 if (allowValue) {
7495 ARDUINOJSON_ASSERT(variant != 0);
7496 }
7497 if (code >= 0xcc && code <= 0xd3) {
7498 auto width = uint8_t(1U << ((code - 0xcc) % 4));
7499 if (allowValue)
7500 return readInteger(variant, width, code >= 0xd0);
7501 else
7502 return skipBytes(width);
7503 }
7504 switch (code) {
7505 case 0xc0:
7506 return DeserializationError::Ok;
7507 case 0xc1:
7508 return DeserializationError::InvalidInput;
7509 case 0xc2:
7510 case 0xc3:
7511 if (allowValue)
7512 variant->setBoolean(code == 0xc3);
7513 return DeserializationError::Ok;
7514 case 0xca:
7515 if (allowValue)
7516 return readFloat<float>(variant);
7517 else
7518 return skipBytes(4);
7519 case 0xcb:
7520 if (allowValue)
7521 return readDouble<double>(variant);
7522 else
7523 return skipBytes(8);
7524 }
7525 if (code <= 0x7f || code >= 0xe0) { // fixint
7526 if (allowValue)
7527 variant->setInteger(static_cast<int8_t>(code), resources_);
7528 return DeserializationError::Ok;
7529 }
7530 uint8_t sizeBytes = 0;
7531 size_t size = 0;
7532 bool isExtension = code >= 0xc7 && code <= 0xc9;
7533 switch (code) {
7534 case 0xc4: // bin 8
7535 case 0xc7: // ext 8
7536 case 0xd9: // str 8
7537 sizeBytes = 1;
7538 break;
7539 case 0xc5: // bin 16
7540 case 0xc8: // ext 16
7541 case 0xda: // str 16
7542 case 0xdc: // array 16
7543 case 0xde: // map 16
7544 sizeBytes = 2;
7545 break;
7546 case 0xc6: // bin 32
7547 case 0xc9: // ext 32
7548 case 0xdb: // str 32
7549 case 0xdd: // array 32
7550 case 0xdf: // map 32
7551 sizeBytes = 4;
7552 break;
7553 }
7554 if (code >= 0xd4 && code <= 0xd8) { // fixext
7555 size = size_t(1) << (code - 0xd4);
7556 isExtension = true;
7557 }
7558 switch (code & 0xf0) {
7559 case 0x90: // fixarray
7560 case 0x80: // fixmap
7561 size = code & 0x0F;
7562 break;
7563 }
7564 switch (code & 0xe0) {
7565 case 0xa0: // fixstr
7566 size = code & 0x1f;
7567 break;
7568 }
7569 if (sizeBytes) {
7570 err = readBytes(header + 1, sizeBytes);
7571 if (err)
7572 return err;
7573 uint32_t size32 = 0;
7574 for (uint8_t i = 0; i < sizeBytes; i++)
7575 size32 = (size32 << 8) | header[i + 1];
7576 size = size_t(size32);
7577 if (size < size32) // integer overflow
7578 return DeserializationError::NoMemory; // (not testable on 32/64-bit)
7579 }
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) {
7585 if (allowValue)
7586 return readString(variant, size);
7587 else
7588 return skipBytes(size);
7589 }
7590 if (isExtension)
7591 size++; // to include the type
7592 if (allowValue)
7593 return readRawString(variant, header, uint8_t(1 + sizeBytes), size);
7594 else
7595 return skipBytes(size);
7596 }
7597 DeserializationError::Code readByte(uint8_t& value) {
7598 int c = reader_.read();
7599 if (c < 0)
7600 return DeserializationError::IncompleteInput;
7601 value = static_cast<uint8_t>(c);
7602 return DeserializationError::Ok;
7603 }
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;
7608 }
7609 template <typename T>
7610 DeserializationError::Code readBytes(T& value) {
7611 return readBytes(&value, sizeof(value));
7612 }
7613 DeserializationError::Code skipBytes(size_t n) {
7614 for (; n; --n) {
7615 if (reader_.read() < 0)
7616 return DeserializationError::IncompleteInput;
7617 }
7618 return DeserializationError::Ok;
7619 }
7620 DeserializationError::Code readInteger(VariantData* variant, uint8_t width,
7621 bool isSigned) {
7622 uint8_t buffer[8];
7623 auto err = readBytes(buffer, width);
7624 if (err)
7625 return err;
7626 union {
7627 int64_t signedValue;
7628 uint64_t unsignedValue;
7629 };
7630 if (isSigned)
7631 signedValue = static_cast<int8_t>(buffer[0]); // propagate sign bit
7632 else
7633 unsignedValue = static_cast<uint8_t>(buffer[0]);
7634 for (uint8_t i = 1; i < width; i++)
7635 unsignedValue = (unsignedValue << 8) | buffer[i];
7636 if (isSigned) {
7637 auto truncatedValue = static_cast<JsonInteger>(signedValue);
7638 if (truncatedValue == signedValue) {
7639 if (!variant->setInteger(truncatedValue, resources_))
7640 return DeserializationError::NoMemory;
7641 }
7642 } else {
7643 auto truncatedValue = static_cast<JsonUInt>(unsignedValue);
7644 if (truncatedValue == unsignedValue)
7645 if (!variant->setInteger(truncatedValue, resources_))
7646 return DeserializationError::NoMemory;
7647 }
7648 return DeserializationError::Ok;
7649 }
7650 template <typename T>
7651 enable_if_t<sizeof(T) == 4, DeserializationError::Code> readFloat(
7652 VariantData* variant) {
7653 DeserializationError::Code err;
7654 T value;
7655 err = readBytes(value);
7656 if (err)
7657 return err;
7658 fixEndianness(value);
7659 variant->setFloat(value, resources_);
7660 return DeserializationError::Ok;
7661 }
7662 template <typename T>
7663 enable_if_t<sizeof(T) == 8, DeserializationError::Code> readDouble(
7664 VariantData* variant) {
7665 DeserializationError::Code err;
7666 T value;
7667 err = readBytes(value);
7668 if (err)
7669 return err;
7670 fixEndianness(value);
7671 if (variant->setFloat(value, resources_))
7672 return DeserializationError::Ok;
7673 else
7674 return DeserializationError::NoMemory;
7675 }
7676 template <typename T>
7677 enable_if_t<sizeof(T) == 4, DeserializationError::Code> readDouble(
7678 VariantData* variant) {
7679 DeserializationError::Code err;
7680 uint8_t i[8]; // input is 8 bytes
7681 T value; // output is 4 bytes
7682 uint8_t* o = reinterpret_cast<uint8_t*>(&value);
7683 err = readBytes(i, 8);
7684 if (err)
7685 return err;
7686 doubleToFloat(i, o);
7687 fixEndianness(value);
7688 variant->setFloat(value, resources_);
7689 return DeserializationError::Ok;
7690 }
7691 DeserializationError::Code readString(VariantData* variant, size_t n) {
7692 DeserializationError::Code err;
7693 err = readString(n);
7694 if (err)
7695 return err;
7696 variant->setOwnedString(stringBuffer_.save());
7697 return DeserializationError::Ok;
7698 }
7699 DeserializationError::Code readString(size_t n) {
7700 char* p = stringBuffer_.reserve(n);
7701 if (!p)
7702 return DeserializationError::NoMemory;
7703 return readBytes(p, n);
7704 }
7705 DeserializationError::Code readRawString(VariantData* variant,
7706 const void* header,
7707 uint8_t headerSize, size_t n) {
7708 auto totalSize = size_t(headerSize + n);
7709 if (totalSize < n) // integer overflow
7710 return DeserializationError::NoMemory; // (not testable on 64-bit)
7711 char* p = stringBuffer_.reserve(totalSize);
7712 if (!p)
7713 return DeserializationError::NoMemory;
7714 memcpy(p, header, headerSize);
7715 auto err = readBytes(p + headerSize, n);
7716 if (err)
7717 return err;
7718 variant->setRawString(stringBuffer_.save());
7719 return DeserializationError::Ok;
7720 }
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();
7729 ArrayData* array;
7730 if (allowArray) {
7731 ARDUINOJSON_ASSERT(variant != 0);
7732 array = &variant->toArray();
7733 } else {
7734 array = 0;
7735 }
7736 TFilter elementFilter = filter[0U];
7737 for (; n; --n) {
7738 VariantData* value;
7739 if (elementFilter.allow()) {
7740 ARDUINOJSON_ASSERT(array != 0);
7741 value = array->addElement(resources_);
7742 if (!value)
7743 return DeserializationError::NoMemory;
7744 } else {
7745 value = 0;
7746 }
7747 err = parseVariant(value, elementFilter, nestingLimit.decrement());
7748 if (err)
7749 return err;
7750 }
7751 return DeserializationError::Ok;
7752 }
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;
7760 ObjectData* object;
7761 if (filter.allowObject()) {
7762 ARDUINOJSON_ASSERT(variant != 0);
7763 object = &variant->toObject();
7764 } else {
7765 object = 0;
7766 }
7767 for (; n; --n) {
7768 err = readKey();
7769 if (err)
7770 return err;
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_);
7778 if (!member)
7779 return DeserializationError::NoMemory;
7780 } else {
7781 member = 0;
7782 }
7783 err = parseVariant(member, memberFilter, nestingLimit.decrement());
7784 if (err)
7785 return err;
7786 }
7787 return DeserializationError::Ok;
7788 }
7789 DeserializationError::Code readKey() {
7790 DeserializationError::Code err;
7791 uint8_t code;
7792 err = readByte(code);
7793 if (err)
7794 return err;
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));
7799 uint32_t size = 0;
7800 for (uint8_t i = 0; i < sizeBytes; i++) {
7801 err = readByte(code);
7802 if (err)
7803 return err;
7804 size = (size << 8) | code;
7805 }
7806 return readString(size);
7807 }
7808 return DeserializationError::InvalidInput;
7809 }
7810 ResourceManager* resources_;
7811 TReader reader_;
7812 StringBuffer stringBuffer_;
7813 bool foundSomething_;
7814};
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)...);
7824}
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),
7831 input,
7832 detail::forward<Args>(args)...);
7833}
7834class MsgPackExtension {
7835 public:
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 {
7840 return type_;
7841 }
7842 const void* data() const {
7843 return data_;
7844 }
7845 size_t size() const {
7846 return size_;
7847 }
7848 private:
7849 const void* data_;
7850 size_t size_;
7851 int8_t type_;
7852};
7853template <>
7854struct Converter<MsgPackExtension> : private detail::VariantAttorney {
7855 static void toJson(MsgPackExtension src, JsonVariant dst) {
7856 auto data = VariantAttorney::getData(dst);
7857 if (!data)
7858 return;
7859 auto resources = getResourceManager(dst);
7860 data->clear(resources);
7861 if (src.data()) {
7862 uint8_t format, sizeBytes;
7863 if (src.size() >= 0x10000) {
7864 format = 0xc9; // ext 32
7865 sizeBytes = 4;
7866 } else if (src.size() >= 0x100) {
7867 format = 0xc8; // ext 16
7868 sizeBytes = 2;
7869 } else if (src.size() == 16) {
7870 format = 0xd8; // fixext 16
7871 sizeBytes = 0;
7872 } else if (src.size() == 8) {
7873 format = 0xd7; // fixext 8
7874 sizeBytes = 0;
7875 } else if (src.size() == 4) {
7876 format = 0xd6; // fixext 4
7877 sizeBytes = 0;
7878 } else if (src.size() == 2) {
7879 format = 0xd5; // fixext 2
7880 sizeBytes = 0;
7881 } else if (src.size() == 1) {
7882 format = 0xd4; // fixext 1
7883 sizeBytes = 0;
7884 } else {
7885 format = 0xc7; // ext 8
7886 sizeBytes = 1;
7887 }
7888 auto str = resources->createString(src.size() + 2 + sizeBytes);
7889 if (str) {
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);
7898 return;
7899 }
7900 }
7901 }
7902 static MsgPackExtension fromJson(JsonVariantConst src) {
7903 auto data = getData(src);
7904 if (!data)
7905 return {};
7906 auto rawstr = data->asRawString();
7907 if (rawstr.size() == 0)
7908 return {};
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) { // fixext 1
7914 headerSize = 2;
7915 payloadSize = size_t(1) << (code - 0xd4);
7916 }
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);
7922 }
7923 if (rawstr.size() == headerSize + payloadSize)
7924 return MsgPackExtension(int8_t(p[headerSize - 1]), p + headerSize,
7925 payloadSize);
7926 return {};
7927 }
7928 static bool checkJson(JsonVariantConst src) {
7929 return fromJson(src).data() != nullptr;
7930 }
7931};
7932ARDUINOJSON_END_PUBLIC_NAMESPACE
7933ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
7934template <typename TWriter>
7935class MsgPackSerializer : public VariantDataVisitor<size_t> {
7936 public:
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(
7942 T value32) {
7943 if (canConvertNumber<JsonInteger>(value32)) {
7944 JsonInteger truncatedValue = JsonInteger(value32);
7945 if (value32 == T(truncatedValue))
7946 return visit(truncatedValue);
7947 }
7948 writeByte(0xCA);
7949 writeInteger(value32);
7950 return bytesWritten();
7951 }
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(
7955 T value64) {
7956 float value32 = float(value64);
7957 if (value32 == value64)
7958 return visit(value32);
7959 writeByte(0xCB);
7960 writeInteger(value64);
7961 return bytesWritten();
7962 }
7963 size_t visit(const ArrayData& array) {
7964 size_t n = array.size(resources_);
7965 if (n < 0x10) {
7966 writeByte(uint8_t(0x90 + n));
7967 } else if (n < 0x10000) {
7968 writeByte(0xDC);
7969 writeInteger(uint16_t(n));
7970 } else {
7971 writeByte(0xDD);
7972 writeInteger(uint32_t(n));
7973 }
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();
7979 }
7980 return bytesWritten();
7981 }
7982 size_t visit(const ObjectData& object) {
7983 size_t n = object.size(resources_);
7984 if (n < 0x10) {
7985 writeByte(uint8_t(0x80 + n));
7986 } else if (n < 0x10000) {
7987 writeByte(0xDE);
7988 writeInteger(uint16_t(n));
7989 } else {
7990 writeByte(0xDF);
7991 writeInteger(uint32_t(n));
7992 }
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();
7998 }
7999 return bytesWritten();
8000 }
8001 size_t visit(const char* value) {
8002 return visit(JsonString(value));
8003 }
8004 size_t visit(JsonString value) {
8005 ARDUINOJSON_ASSERT(value != NULL);
8006 auto n = value.size();
8007 if (n < 0x20) {
8008 writeByte(uint8_t(0xA0 + n));
8009 } else if (n < 0x100) {
8010 writeByte(0xD9);
8011 writeInteger(uint8_t(n));
8012 } else if (n < 0x10000) {
8013 writeByte(0xDA);
8014 writeInteger(uint16_t(n));
8015 } else {
8016 writeByte(0xDB);
8017 writeInteger(uint32_t(n));
8018 }
8019 writeBytes(reinterpret_cast<const uint8_t*>(value.c_str()), n);
8020 return bytesWritten();
8021 }
8022 size_t visit(RawString value) {
8023 writeBytes(reinterpret_cast<const uint8_t*>(value.data()), value.size());
8024 return bytesWritten();
8025 }
8026 size_t visit(JsonInteger value) {
8027 if (value > 0) {
8028 visit(static_cast<JsonUInt>(value));
8029 } else if (value >= -0x20) {
8030 writeInteger(int8_t(value));
8031 } else if (value >= -0x80) {
8032 writeByte(0xD0);
8033 writeInteger(int8_t(value));
8034 } else if (value >= -0x8000) {
8035 writeByte(0xD1);
8036 writeInteger(int16_t(value));
8037 }
8038#if ARDUINOJSON_USE_LONG_LONG
8039 else if (value >= -0x80000000LL)
8040#else
8041 else
8042#endif
8043 {
8044 writeByte(0xD2);
8045 writeInteger(int32_t(value));
8046 }
8047#if ARDUINOJSON_USE_LONG_LONG
8048 else {
8049 writeByte(0xD3);
8050 writeInteger(int64_t(value));
8051 }
8052#endif
8053 return bytesWritten();
8054 }
8055 size_t visit(JsonUInt value) {
8056 if (value <= 0x7F) {
8057 writeInteger(uint8_t(value));
8058 } else if (value <= 0xFF) {
8059 writeByte(0xCC);
8060 writeInteger(uint8_t(value));
8061 } else if (value <= 0xFFFF) {
8062 writeByte(0xCD);
8063 writeInteger(uint16_t(value));
8064 }
8065#if ARDUINOJSON_USE_LONG_LONG
8066 else if (value <= 0xFFFFFFFF)
8067#else
8068 else
8069#endif
8070 {
8071 writeByte(0xCE);
8072 writeInteger(uint32_t(value));
8073 }
8074#if ARDUINOJSON_USE_LONG_LONG
8075 else {
8076 writeByte(0xCF);
8077 writeInteger(uint64_t(value));
8078 }
8079#endif
8080 return bytesWritten();
8081 }
8082 size_t visit(bool value) {
8083 writeByte(value ? 0xC3 : 0xC2);
8084 return bytesWritten();
8085 }
8086 size_t visit(nullptr_t) {
8087 writeByte(0xC0);
8088 return bytesWritten();
8089 }
8090 private:
8091 size_t bytesWritten() const {
8092 return writer_.count();
8093 }
8094 void writeByte(uint8_t c) {
8095 writer_.write(c);
8096 }
8097 void writeBytes(const uint8_t* p, size_t n) {
8098 writer_.write(p, n);
8099 }
8100 template <typename T>
8101 void writeInteger(T value) {
8102 fixEndianness(value);
8103 writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
8104 }
8105 CountingDecorator<TWriter> writer_;
8106 const ResourceManager* resources_;
8107};
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);
8115}
8116inline size_t serializeMsgPack(JsonVariantConst source, void* output,
8117 size_t size) {
8118 using namespace FLArduinoJson::detail;
8119 return serialize<MsgPackSerializer>(source, output, size);
8120}
8121inline size_t measureMsgPack(JsonVariantConst source) {
8122 using namespace FLArduinoJson::detail;
8123 return measure<MsgPackSerializer>(source);
8124}
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
8128#endif
8129#ifdef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
8130#warning "ARDUINOJSON_ENABLE_STRING_DEDUPLICATION has been removed, string deduplication is now always enabled"
8131#endif
8132#ifdef __GNUC__
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)
8146#else
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)
8150#endif
8151ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
8152template <size_t N>
8153class ARDUINOJSON_DEPRECATED("use JsonDocument instead") StaticJsonDocument
8154 : public JsonDocument {
8155 public:
8156 using JsonDocument::JsonDocument;
8157 size_t capacity() const {
8158 return N;
8159 }
8160};
8161namespace detail {
8162template <typename TAllocator>
8163class AllocatorAdapter : public Allocator {
8164 public:
8165 AllocatorAdapter(const AllocatorAdapter&) = delete;
8166 AllocatorAdapter& operator=(const AllocatorAdapter&) = delete;
8167 void* allocate(size_t size) override {
8168 return _allocator.allocate(size);
8169 }
8170 void deallocate(void* ptr) override {
8171 _allocator.deallocate(ptr);
8172 }
8173 void* reallocate(void* ptr, size_t new_size) override {
8174 return _allocator.reallocate(ptr, new_size);
8175 }
8176 static Allocator* instance() {
8177 static AllocatorAdapter instance;
8178 return &instance;
8179 }
8180 private:
8181 AllocatorAdapter() = default;
8182 ~AllocatorAdapter() = default;
8183 TAllocator _allocator;
8184};
8185} // namespace detail
8186template <typename TAllocator>
8187class ARDUINOJSON_DEPRECATED("use JsonDocument instead") BasicJsonDocument
8188 : public JsonDocument {
8189 public:
8190 BasicJsonDocument(size_t capacity)
8191 : JsonDocument(detail::AllocatorAdapter<TAllocator>::instance()),
8192 _capacity(capacity) {}
8193 size_t capacity() const {
8194 return _capacity;
8195 }
8196 void garbageCollect() {}
8197 private:
8198 size_t _capacity;
8199};
8200class ARDUINOJSON_DEPRECATED("use JsonDocument instead") DynamicJsonDocument
8201 : public JsonDocument {
8202 public:
8203 DynamicJsonDocument(size_t capacity) : _capacity(capacity) {}
8204 size_t capacity() const {
8205 return _capacity;
8206 }
8207 void garbageCollect() {}
8208 private:
8209 size_t _capacity;
8210};
8211inline JsonObject JsonArray::createNestedObject() const {
8212 return add<JsonObject>();
8213}
8214ARDUINOJSON_END_PUBLIC_NAMESPACE
8215
8216// using namespace FLArduinoJson;
8217
8218#else
8219
8220#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp
8221
8222#endif
FASTLED_FORCE_INLINE bool operator!=(const CRGB &lhs, const CRGB &rhs)
Check if two CRGB objects do not have the same color data.
Definition crgb.h:657
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.
Definition crgb.h:702
FASTLED_FORCE_INLINE bool operator==(const CRGB &lhs, const CRGB &rhs)
Check if two CRGB objects have the same color data.
Definition crgb.h:651
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.
Definition crgb.h:675
FASTLED_FORCE_INLINE CRGB operator|(const CRGB &p1, const CRGB &p2)
Combine two CRGB objects, taking the largest value of each channel.
Definition crgb.h:728
FASTLED_FORCE_INLINE CRGB operator&(const CRGB &p1, const CRGB &p2)
Combine two CRGB objects, taking the smallest value of each channel.
Definition crgb.h:720
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.
Definition crgb.h:684
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.
Definition crgb.h:693
FASTLED_FORCE_INLINE CRGB operator*(const CRGB &p1, uint8_t d)
Multiply each of the channels by a constant, saturating each channel at 0xFF.
Definition crgb.hpp:221