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