GM6000 Digital Heater Controller Branch: main
SDX-1330
Arduino.h
1// ArduinoJson - https://arduinojson.org
2// Copyright © 2014-2023, Benoit BLANCHON
3// MIT License
4// Version 6.21.5
5
6#pragma once
7
8#ifdef __cplusplus
9
10#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_VER < 1910)
11# error ArduinoJson requires C++11 or newer. Configure your compiler for C++11 or downgrade ArduinoJson to 6.20.
12#endif
13#ifndef ARDUINOJSON_ENABLE_STD_STREAM
14# ifdef __has_include
15# if __has_include(<istream>) && \
16 __has_include(<ostream>) && \
17 !defined(min) && \
18 !defined(max)
19# define ARDUINOJSON_ENABLE_STD_STREAM 1
20# else
21# define ARDUINOJSON_ENABLE_STD_STREAM 0
22# endif
23# else
24# ifdef ARDUINO
25# define ARDUINOJSON_ENABLE_STD_STREAM 0
26# else
27# define ARDUINOJSON_ENABLE_STD_STREAM 1
28# endif
29# endif
30#endif
31#ifndef ARDUINOJSON_ENABLE_STD_STRING
32# ifdef __has_include
33# if __has_include(<string>) && !defined(min) && !defined(max)
34# define ARDUINOJSON_ENABLE_STD_STRING 1
35# else
36# define ARDUINOJSON_ENABLE_STD_STRING 0
37# endif
38# else
39# ifdef ARDUINO
40# define ARDUINOJSON_ENABLE_STD_STRING 0
41# else
42# define ARDUINOJSON_ENABLE_STD_STRING 1
43# endif
44# endif
45#endif
46#ifndef ARDUINOJSON_ENABLE_STRING_VIEW
47# ifdef __has_include
48# if __has_include(<string_view>) && __cplusplus >= 201703L
49# define ARDUINOJSON_ENABLE_STRING_VIEW 1
50# else
51# define ARDUINOJSON_ENABLE_STRING_VIEW 0
52# endif
53# else
54# define ARDUINOJSON_ENABLE_STRING_VIEW 0
55# endif
56#endif
57#ifndef ARDUINOJSON_USE_DOUBLE
58# define ARDUINOJSON_USE_DOUBLE 1
59#endif
60#ifndef ARDUINOJSON_USE_LONG_LONG
61# if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ >= 4 || \
62 defined(_MSC_VER)
63# define ARDUINOJSON_USE_LONG_LONG 1
64# endif
65#endif
66#ifndef ARDUINOJSON_USE_LONG_LONG
67# define ARDUINOJSON_USE_LONG_LONG 0
68#endif
69#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
70# define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
71#endif
72#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE
73# if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ <= 2
74# define ARDUINOJSON_SLOT_OFFSET_SIZE 1
75# elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ >= 8 || \
76 defined(_WIN64) && _WIN64
77# define ARDUINOJSON_SLOT_OFFSET_SIZE 4
78# else
79# define ARDUINOJSON_SLOT_OFFSET_SIZE 2
80# endif
81#endif
82#ifdef ARDUINO
83# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
84# define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
85# endif
86# ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
87# define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
88# endif
89# ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
90# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1
91# endif
92# ifndef ARDUINOJSON_ENABLE_PROGMEM
93# define ARDUINOJSON_ENABLE_PROGMEM 1
94# endif
95#else // ARDUINO
96# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
97# define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
98# endif
99# ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
100# define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
101# endif
102# ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
103# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
104# endif
105# ifndef ARDUINOJSON_ENABLE_PROGMEM
106# ifdef __AVR__
107# define ARDUINOJSON_ENABLE_PROGMEM 1
108# else
109# define ARDUINOJSON_ENABLE_PROGMEM 0
110# endif
111# endif
112#endif // ARDUINO
113#ifndef ARDUINOJSON_DECODE_UNICODE
114# define ARDUINOJSON_DECODE_UNICODE 1
115#endif
116#ifndef ARDUINOJSON_ENABLE_COMMENTS
117# define ARDUINOJSON_ENABLE_COMMENTS 0
118#endif
119#ifndef ARDUINOJSON_ENABLE_NAN
120# define ARDUINOJSON_ENABLE_NAN 0
121#endif
122#ifndef ARDUINOJSON_ENABLE_INFINITY
123# define ARDUINOJSON_ENABLE_INFINITY 0
124#endif
125#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
126# define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
127#endif
128#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
129# define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
130#endif
131#ifndef ARDUINOJSON_LITTLE_ENDIAN
132# if defined(_MSC_VER) || \
133 (defined(__BYTE_ORDER__) && \
134 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
135 defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64)
136# define ARDUINOJSON_LITTLE_ENDIAN 1
137# else
138# define ARDUINOJSON_LITTLE_ENDIAN 0
139# endif
140#endif
141#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
142# if defined(__AVR)
143# define ARDUINOJSON_ENABLE_ALIGNMENT 0
144# else
145# define ARDUINOJSON_ENABLE_ALIGNMENT 1
146# endif
147#endif
148#ifndef ARDUINOJSON_TAB
149# define ARDUINOJSON_TAB " "
150#endif
151#ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
152# define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1
153#endif
154#ifndef ARDUINOJSON_STRING_BUFFER_SIZE
155# define ARDUINOJSON_STRING_BUFFER_SIZE 32
156#endif
157#ifndef ARDUINOJSON_DEBUG
158# ifdef __PLATFORMIO_BUILD_DEBUG__
159# define ARDUINOJSON_DEBUG 1
160# else
161# define ARDUINOJSON_DEBUG 0
162# endif
163#endif
164#if defined(nullptr)
165# error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
166#endif
167#if ARDUINOJSON_ENABLE_ARDUINO_STRING || ARDUINOJSON_ENABLE_ARDUINO_STREAM || \
168 ARDUINOJSON_ENABLE_ARDUINO_PRINT || \
169 (ARDUINOJSON_ENABLE_PROGMEM && defined(ARDUINO))
170#include <Arduino.h>
171#endif
172#if !ARDUINOJSON_DEBUG
173# ifdef __clang__
174# pragma clang system_header
175# elif defined __GNUC__
176# pragma GCC system_header
177# endif
178#endif
179#define ARDUINOJSON_CONCAT_(A, B) A##B
180#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B)
181#define ARDUINOJSON_CONCAT4(A, B, C, D) \
182 ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
183#define ARDUINOJSON_BIN2ALPHA_0000() A
184#define ARDUINOJSON_BIN2ALPHA_0001() B
185#define ARDUINOJSON_BIN2ALPHA_0010() C
186#define ARDUINOJSON_BIN2ALPHA_0011() D
187#define ARDUINOJSON_BIN2ALPHA_0100() E
188#define ARDUINOJSON_BIN2ALPHA_0101() F
189#define ARDUINOJSON_BIN2ALPHA_0110() G
190#define ARDUINOJSON_BIN2ALPHA_0111() H
191#define ARDUINOJSON_BIN2ALPHA_1000() I
192#define ARDUINOJSON_BIN2ALPHA_1001() J
193#define ARDUINOJSON_BIN2ALPHA_1010() K
194#define ARDUINOJSON_BIN2ALPHA_1011() L
195#define ARDUINOJSON_BIN2ALPHA_1100() M
196#define ARDUINOJSON_BIN2ALPHA_1101() N
197#define ARDUINOJSON_BIN2ALPHA_1110() O
198#define ARDUINOJSON_BIN2ALPHA_1111() P
199#define ARDUINOJSON_BIN2ALPHA_(A, B, C, D) ARDUINOJSON_BIN2ALPHA_##A##B##C##D()
200#define ARDUINOJSON_BIN2ALPHA(A, B, C, D) ARDUINOJSON_BIN2ALPHA_(A, B, C, D)
201#define ARDUINOJSON_VERSION "6.21.5"
202#define ARDUINOJSON_VERSION_MAJOR 6
203#define ARDUINOJSON_VERSION_MINOR 21
204#define ARDUINOJSON_VERSION_REVISION 5
205#define ARDUINOJSON_VERSION_MACRO V6215
206#ifndef ARDUINOJSON_VERSION_NAMESPACE
207# define ARDUINOJSON_VERSION_NAMESPACE \
208 ARDUINOJSON_CONCAT4( \
209 ARDUINOJSON_VERSION_MACRO, \
210 ARDUINOJSON_BIN2ALPHA( \
211 ARDUINOJSON_ENABLE_PROGMEM, ARDUINOJSON_USE_LONG_LONG, \
212 ARDUINOJSON_USE_DOUBLE, ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \
213 ARDUINOJSON_BIN2ALPHA( \
214 ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \
215 ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE), \
216 ARDUINOJSON_SLOT_OFFSET_SIZE)
217#endif
218#define ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE \
219 namespace ArduinoJson { \
220 inline namespace ARDUINOJSON_VERSION_NAMESPACE {
221#define ARDUINOJSON_END_PUBLIC_NAMESPACE \
222 } \
223 }
224#define ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE \
225 namespace ArduinoJson { \
226 inline namespace ARDUINOJSON_VERSION_NAMESPACE { \
227 namespace detail {
228#define ARDUINOJSON_END_PRIVATE_NAMESPACE \
229 } \
230 } \
231 }
232ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
233template <typename T, typename Enable = void>
234struct Converter;
235ARDUINOJSON_END_PUBLIC_NAMESPACE
236ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
237template <typename T1, typename T2>
238class InvalidConversion; // Error here? See https://arduinojson.org/v6/invalid-conversion/
239template <typename T>
240struct ConverterNeedsWriteableRef;
241ARDUINOJSON_END_PRIVATE_NAMESPACE
242#include <stddef.h>
243#include <stdint.h>
244ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
245#if ARDUINOJSON_ENABLE_ALIGNMENT
246inline bool isAligned( size_t value ) {
247 const size_t mask = sizeof( void* ) - 1;
248 size_t addr = value;
249 return (addr & mask) == 0;
250}
251inline size_t addPadding( size_t bytes ) {
252 const size_t mask = sizeof( void* ) - 1;
253 return (bytes + mask) & ~mask;
254}
255template <size_t bytes>
256struct AddPadding {
257 static const size_t mask = sizeof( void* ) - 1;
258 static const size_t value = (bytes + mask) & ~mask;
259};
260#else
261inline bool isAligned( size_t ) {
262 return true;
263}
264inline size_t addPadding( size_t bytes ) {
265 return bytes;
266}
267template <size_t bytes>
268struct AddPadding {
269 static const size_t value = bytes;
270};
271#endif
272template <typename T>
273inline bool isAligned( T* ptr ) {
274 return isAligned( reinterpret_cast<size_t>(ptr) );
275}
276template <typename T>
277inline T* addPadding( T* p ) {
278 size_t address = addPadding( reinterpret_cast<size_t>(p) );
279 return reinterpret_cast<T*>(address);
280}
281ARDUINOJSON_END_PRIVATE_NAMESPACE
282#if ARDUINOJSON_DEBUG
283#include <assert.h>
284# define ARDUINOJSON_ASSERT(X) assert(X)
285#else
286# define ARDUINOJSON_ASSERT(X) ((void)0)
287#endif
288ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
289template <size_t X, size_t Y, bool MaxIsX = (X > Y)>
290struct Max {};
291template <size_t X, size_t Y>
292struct Max<X, Y, true> {
293 static const size_t value = X;
294};
295template <size_t X, size_t Y>
296struct Max<X, Y, false> {
297 static const size_t value = Y;
298};
299template <bool Condition, class TrueType, class FalseType>
300struct conditional {
301 typedef TrueType type;
302};
303template <class TrueType, class FalseType>
304struct conditional<false, TrueType, FalseType> {
305 typedef FalseType type;
306};
307template <bool Condition, typename T = void>
308struct enable_if {};
309template <typename T>
310struct enable_if<true, T> {
311 typedef T type;
312};
313template <typename T, T v>
314struct integral_constant {
315 static const T value = v;
316};
317typedef integral_constant<bool, true> true_type;
318typedef integral_constant<bool, false> false_type;
319template <typename T>
320struct is_array : false_type {};
321template <typename T>
322struct is_array<T[]> : true_type {};
323template <typename T, size_t N>
324struct is_array<T[N]> : true_type {};
325template <typename T>
326struct remove_reference {
327 typedef T type;
328};
329template <typename T>
330struct remove_reference<T&> {
331 typedef T type;
332};
333template <typename TBase, typename TDerived>
334class is_base_of {
335protected: // <- to avoid GCC's "all member functions in class are private"
336 static int probe( const TBase* );
337 static char probe( ... );
338public:
339 static const bool value =
340 sizeof( probe( reinterpret_cast<typename remove_reference<TDerived>::type*>(
341 0) ) ) == sizeof( int );
342};
343template <typename T>
344T&& declval();
345template <typename T>
346struct is_class {
347protected: // <- to avoid GCC's "all member functions in class are private"
348 template <typename U>
349 static int probe( void (U::*)(void) );
350 template <typename>
351 static char probe( ... );
352public:
353 static const bool value = sizeof( probe<T>( 0 ) ) == sizeof( int );
354};
355template <typename T>
356struct is_const : false_type {};
357template <typename T>
358struct is_const<const T> : true_type {};
359ARDUINOJSON_END_PRIVATE_NAMESPACE
360#ifdef _MSC_VER
361# pragma warning(push)
362# pragma warning(disable : 4244)
363#endif
364#ifdef __ICCARM__
365#pragma diag_suppress=Pa093
366#endif
367ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
368template <typename From, typename To>
369struct is_convertible {
370protected: // <- to avoid GCC's "all member functions in class are private"
371 static int probe( To );
372 static char probe( ... );
373 static From& from_;
374public:
375 static const bool value = sizeof( probe( from_ ) ) == sizeof( int );
376};
377ARDUINOJSON_END_PRIVATE_NAMESPACE
378#ifdef _MSC_VER
379# pragma warning(pop)
380#endif
381#ifdef __ICCARM__
382#pragma diag_default=Pa093
383#endif
384ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
385template <typename T, typename U>
386struct is_same : false_type {};
387template <typename T>
388struct is_same<T, T> : true_type {};
389template <typename T>
390struct remove_cv {
391 typedef T type;
392};
393template <typename T>
394struct remove_cv<const T> {
395 typedef T type;
396};
397template <typename T>
398struct remove_cv<volatile T> {
399 typedef T type;
400};
401template <typename T>
402struct remove_cv<const volatile T> {
403 typedef T type;
404};
405template <class T>
406struct is_floating_point
407 : integral_constant<
408 bool, //
409 is_same<float, typename remove_cv<T>::type>::value ||
410 is_same<double, typename remove_cv<T>::type>::value> {};
411template <typename T>
412struct is_integral : integral_constant<bool,
413 is_same<typename remove_cv<T>::type, signed char>::value ||
414 is_same<typename remove_cv<T>::type, unsigned char>::value ||
415 is_same<typename remove_cv<T>::type, signed short>::value ||
416 is_same<typename remove_cv<T>::type, unsigned short>::value ||
417 is_same<typename remove_cv<T>::type, signed int>::value ||
418 is_same<typename remove_cv<T>::type, unsigned int>::value ||
419 is_same<typename remove_cv<T>::type, signed long>::value ||
420 is_same<typename remove_cv<T>::type, unsigned long>::value ||
421 is_same<typename remove_cv<T>::type, signed long long>::value ||
422 is_same<typename remove_cv<T>::type, unsigned long long>::value ||
423 is_same<typename remove_cv<T>::type, char>::value ||
424 is_same<typename remove_cv<T>::type, bool>::value> {};
425template <typename T>
426struct is_enum {
427 static const bool value = is_convertible<T, int>::value &&
428 !is_class<T>::value && !is_integral<T>::value &&
429 !is_floating_point<T>::value;
430};
431template <typename T>
432struct is_pointer : false_type {};
433template <typename T>
434struct is_pointer<T*> : true_type {};
435template <typename T>
436struct is_signed : integral_constant<bool,
437 is_same<typename remove_cv<T>::type, char>::value ||
438 is_same<typename remove_cv<T>::type, signed char>::value ||
439 is_same<typename remove_cv<T>::type, signed short>::value ||
440 is_same<typename remove_cv<T>::type, signed int>::value ||
441 is_same<typename remove_cv<T>::type, signed long>::value ||
442 is_same<typename remove_cv<T>::type, signed long long>::value ||
443 is_same<typename remove_cv<T>::type, float>::value ||
444 is_same<typename remove_cv<T>::type, double>::value> {};
445template <typename T>
446struct is_unsigned : integral_constant<bool,
447 is_same<typename remove_cv<T>::type, unsigned char>::value ||
448 is_same<typename remove_cv<T>::type, unsigned short>::value ||
449 is_same<typename remove_cv<T>::type, unsigned int>::value ||
450 is_same<typename remove_cv<T>::type, unsigned long>::value ||
451 is_same<typename remove_cv<T>::type, unsigned long long>::value ||
452 is_same<typename remove_cv<T>::type, bool>::value> {};
453template <typename T>
454struct type_identity {
455 typedef T type;
456};
457template <typename T>
458struct make_unsigned;
459template <>
460struct make_unsigned<char> : type_identity<unsigned char> {};
461template <>
462struct make_unsigned<signed char> : type_identity<unsigned char> {};
463template <>
464struct make_unsigned<unsigned char> : type_identity<unsigned char> {};
465template <>
466struct make_unsigned<signed short> : type_identity<unsigned short> {};
467template <>
468struct make_unsigned<unsigned short> : type_identity<unsigned short> {};
469template <>
470struct make_unsigned<signed int> : type_identity<unsigned int> {};
471template <>
472struct make_unsigned<unsigned int> : type_identity<unsigned int> {};
473template <>
474struct make_unsigned<signed long> : type_identity<unsigned long> {};
475template <>
476struct make_unsigned<unsigned long> : type_identity<unsigned long> {};
477template <>
478struct make_unsigned<signed long long> : type_identity<unsigned long long> {};
479template <>
480struct make_unsigned<unsigned long long> : type_identity<unsigned long long> {};
481template <class = void>
482struct make_void {
483 typedef void type;
484};
485template <typename T>
486struct remove_const {
487 typedef T type;
488};
489template <typename T>
490struct remove_const<const T> {
491 typedef T type;
492};
493ARDUINOJSON_END_PRIVATE_NAMESPACE
494#include <string.h>
495#ifdef _MSC_VER // Visual Studio
496# define FORCE_INLINE // __forceinline causes C4714 when returning std::string
497# define NO_INLINE __declspec(noinline)
498#elif defined(__GNUC__) // GCC or Clang
499# define FORCE_INLINE __attribute__((always_inline))
500# define NO_INLINE __attribute__((noinline))
501#else // Other compilers
502# define FORCE_INLINE
503# define NO_INLINE
504#endif
505#if defined(__has_attribute)
506# if __has_attribute(no_sanitize)
507# define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check)))
508# else
509# define ARDUINOJSON_NO_SANITIZE(check)
510# endif
511#else
512# define ARDUINOJSON_NO_SANITIZE(check)
513#endif
514ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
515namespace StringStoragePolicy {
516struct Link {};
517struct Copy {};
518struct LinkOrCopy {
519 bool link;
520};
521} // namespace StringStoragePolicy
522template <typename TString, typename Enable = void>
523struct StringAdapter;
524template <typename TString, typename Enable = void>
525struct SizedStringAdapter;
526template <typename TString>
527typename StringAdapter<TString>::AdaptedString adaptString( const TString& s ) {
528 return StringAdapter<TString>::adapt( s );
529}
530template <typename TChar>
531typename StringAdapter<TChar*>::AdaptedString adaptString( TChar* p ) {
532 return StringAdapter<TChar*>::adapt( p );
533}
534template <typename TChar>
535typename SizedStringAdapter<TChar*>::AdaptedString adaptString( TChar* p,
536 size_t n ) {
537 return SizedStringAdapter<TChar*>::adapt( p, n );
538}
539template <typename T>
540struct IsChar
541 : integral_constant<bool, is_integral<T>::value && sizeof( T ) == 1> {};
542class ZeroTerminatedRamString {
543public:
544 static const size_t typeSortKey = 3;
545 ZeroTerminatedRamString( const char* str ) : str_( str ) {}
546 bool isNull() const {
547 return !str_;
548 }
549 FORCE_INLINE size_t size() const {
550 return str_ ? ::strlen( str_ ) : 0;
551 }
552 char operator[]( size_t i ) const {
553 ARDUINOJSON_ASSERT( str_ != 0 );
554 ARDUINOJSON_ASSERT( i <= size() );
555 return str_[i];
556 }
557 const char* data() const {
558 return str_;
559 }
560 friend int stringCompare( ZeroTerminatedRamString a,
561 ZeroTerminatedRamString b ) {
562 ARDUINOJSON_ASSERT( !a.isNull() );
563 ARDUINOJSON_ASSERT( !b.isNull() );
564 return ::strcmp( a.str_, b.str_ );
565 }
566 friend bool stringEquals( ZeroTerminatedRamString a,
567 ZeroTerminatedRamString b ) {
568 return stringCompare( a, b ) == 0;
569 }
570 StringStoragePolicy::Copy storagePolicy() const {
571 return StringStoragePolicy::Copy();
572 }
573protected:
574 const char* str_;
575};
576template <typename TChar>
577struct StringAdapter<TChar*, typename enable_if<IsChar<TChar>::value>::type> {
578 typedef ZeroTerminatedRamString AdaptedString;
579 static AdaptedString adapt( const TChar* p ) {
580 return AdaptedString( reinterpret_cast<const char*>(p) );
581 }
582};
583template <typename TChar, size_t N>
584struct StringAdapter<TChar[N], typename enable_if<IsChar<TChar>::value>::type> {
585 typedef ZeroTerminatedRamString AdaptedString;
586 static AdaptedString adapt( const TChar* p ) {
587 return AdaptedString( reinterpret_cast<const char*>(p) );
588 }
589};
590class StaticStringAdapter : public ZeroTerminatedRamString {
591public:
592 StaticStringAdapter( const char* str ) : ZeroTerminatedRamString( str ) {}
593 StringStoragePolicy::Link storagePolicy() const {
594 return StringStoragePolicy::Link();
595 }
596};
597template <>
598struct StringAdapter<const char*, void> {
599 typedef StaticStringAdapter AdaptedString;
600 static AdaptedString adapt( const char* p ) {
601 return AdaptedString( p );
602 }
603};
604class SizedRamString {
605public:
606 static const size_t typeSortKey = 2;
607 SizedRamString( const char* str, size_t sz ) : str_( str ), size_( sz ) {}
608 bool isNull() const {
609 return !str_;
610 }
611 size_t size() const {
612 return size_;
613 }
614 char operator[]( size_t i ) const {
615 ARDUINOJSON_ASSERT( str_ != 0 );
616 ARDUINOJSON_ASSERT( i <= size() );
617 return str_[i];
618 }
619 const char* data() const {
620 return str_;
621 }
622 StringStoragePolicy::Copy storagePolicy() const {
623 return StringStoragePolicy::Copy();
624 }
625protected:
626 const char* str_;
627 size_t size_;
628};
629template <typename TChar>
630struct SizedStringAdapter<TChar*,
631 typename enable_if<IsChar<TChar>::value>::type> {
632 typedef SizedRamString AdaptedString;
633 static AdaptedString adapt( const TChar* p, size_t n ) {
634 return AdaptedString( reinterpret_cast<const char*>(p), n );
635 }
636};
637ARDUINOJSON_END_PRIVATE_NAMESPACE
638#if ARDUINOJSON_ENABLE_STD_STREAM
639#include <ostream>
640#endif
641ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
642class JsonString {
643public:
644 enum Ownership { Copied, Linked };
645 JsonString() : data_( 0 ), size_( 0 ), ownership_( Linked ) {}
646 JsonString( const char* data, Ownership ownership = Linked )
647 : data_( data ), size_( data ? ::strlen( data ) : 0 ), ownership_( ownership ) {}
648 JsonString( const char* data, size_t sz, Ownership ownership = Linked )
649 : data_( data ), size_( sz ), ownership_( ownership ) {}
650 const char* c_str() const {
651 return data_;
652 }
653 bool isNull() const {
654 return !data_;
655 }
656 bool isLinked() const {
657 return ownership_ == Linked;
658 }
659 size_t size() const {
660 return size_;
661 }
662 explicit operator bool() const {
663 return data_ != 0;
664 }
665 friend bool operator==( JsonString lhs, JsonString rhs ) {
666 if ( lhs.size_ != rhs.size_ )
667 return false;
668 if ( lhs.data_ == rhs.data_ )
669 return true;
670 if ( !lhs.data_ )
671 return false;
672 if ( !rhs.data_ )
673 return false;
674 return memcmp( lhs.data_, rhs.data_, lhs.size_ ) == 0;
675 }
676 friend bool operator!=( JsonString lhs, JsonString rhs ) {
677 return !(lhs == rhs);
678 }
679#if ARDUINOJSON_ENABLE_STD_STREAM
680 friend std::ostream& operator<<( std::ostream& lhs, const JsonString& rhs ) {
681 lhs.write( rhs.c_str(), static_cast<std::streamsize>(rhs.size()) );
682 return lhs;
683 }
684#endif
685private:
686 const char* data_;
687 size_t size_;
688 Ownership ownership_;
689};
690ARDUINOJSON_END_PUBLIC_NAMESPACE
691ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
692class JsonStringAdapter : public SizedRamString {
693public:
694 JsonStringAdapter( const JsonString& s )
695 : SizedRamString( s.c_str(), s.size() ), linked_( s.isLinked() ) {}
696 StringStoragePolicy::LinkOrCopy storagePolicy() const {
697 StringStoragePolicy::LinkOrCopy policy ={ linked_ };
698 return policy;
699 }
700private:
701 bool linked_;
702};
703template <>
704struct StringAdapter<JsonString> {
705 typedef JsonStringAdapter AdaptedString;
706 static AdaptedString adapt( const JsonString& s ) {
707 return AdaptedString( s );
708 }
709};
710namespace string_traits_impl {
711template <class T, class = void>
712struct has_cstr : false_type {};
713template <class T>
714struct has_cstr<T,
715 typename enable_if<is_same<decltype(declval<const T>().c_str()),
716 const char*>::value>::type>
717 : true_type {};
718template <class T, class = void>
719struct has_data : false_type {};
720template <class T>
721struct has_data<T,
722 typename enable_if<is_same<decltype(declval<const T>().data()),
723 const char*>::value>::type>
724 : true_type {};
725template <class T, class = void>
726struct has_length : false_type {};
727template <class T>
728struct has_length<
729 T, typename enable_if<
730 is_same<decltype(declval<const T>().length()), size_t>::value>::type>
731 : true_type {};
732template <class T, class = void>
733struct has_size : false_type {};
734template <class T>
735struct has_size<
736 T, typename enable_if<
737 is_same<decltype(declval<const T>().size()), size_t>::value>::type>
738 : true_type {};
739} // namespace string_traits_impl
740template <typename T>
741struct string_traits {
742 enum {
743 has_cstr = string_traits_impl::has_cstr<T>::value,
744 has_length = string_traits_impl::has_length<T>::value,
745 has_data = string_traits_impl::has_data<T>::value,
746 has_size = string_traits_impl::has_size<T>::value
747 };
748};
749template <typename T>
750struct StringAdapter<
751 T,
752 typename enable_if<
753 (string_traits<T>::has_cstr || string_traits<T>::has_data) &&
754 (string_traits<T>::has_length || string_traits<T>::has_size)>::type> {
755 typedef SizedRamString AdaptedString;
756 static AdaptedString adapt( const T& s ) {
757 return AdaptedString( get_data( s ), get_size( s ) );
758 }
759private:
760 template <typename U>
761 static typename enable_if<string_traits<U>::has_size, size_t>::type get_size(
762 const U& s ) {
763 return s.size();
764 }
765 template <typename U>
766 static typename enable_if<!string_traits<U>::has_size, size_t>::type get_size(
767 const U& s ) {
768 return s.length();
769 }
770 template <typename U>
771 static typename enable_if<string_traits<U>::has_data, const char*>::type
772 get_data( const U& s ) {
773 return s.data();
774 }
775 template <typename U>
776 static typename enable_if<!string_traits<U>::has_data, const char*>::type
777 get_data( const U& s ) {
778 return s.c_str();
779 }
780};
781ARDUINOJSON_END_PRIVATE_NAMESPACE
782#if ARDUINOJSON_ENABLE_PROGMEM
783#ifdef ARDUINO
784#else
785class __FlashStringHelper;
786#include <avr/pgmspace.h>
787#endif
788ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
789struct pgm_p {
790 pgm_p( const void* p ) : address( reinterpret_cast<const char*>(p) ) {}
791 const char* address;
792};
793ARDUINOJSON_END_PRIVATE_NAMESPACE
794#ifndef strlen_P
795inline size_t strlen_P( ArduinoJson::detail::pgm_p s ) {
796 const char* p = s.address;
797 ARDUINOJSON_ASSERT( p != NULL );
798 while ( pgm_read_byte( p ) )
799 p++;
800 return size_t( p - s.address );
801}
802#endif
803#ifndef strncmp_P
804inline int strncmp_P( const char* a, ArduinoJson::detail::pgm_p b, size_t n ) {
805 const char* s1 = a;
806 const char* s2 = b.address;
807 ARDUINOJSON_ASSERT( s1 != NULL );
808 ARDUINOJSON_ASSERT( s2 != NULL );
809 while ( n-- > 0 ) {
810 char c1 = *s1++;
811 char c2 = static_cast<char>(pgm_read_byte( s2++ ));
812 if ( c1 < c2 )
813 return -1;
814 if ( c1 > c2 )
815 return 1;
816 if ( c1 == 0 /* and c2 as well */ )
817 return 0;
818 }
819 return 0;
820}
821#endif
822#ifndef strcmp_P
823inline int strcmp_P( const char* a, ArduinoJson::detail::pgm_p b ) {
824 const char* s1 = a;
825 const char* s2 = b.address;
826 ARDUINOJSON_ASSERT( s1 != NULL );
827 ARDUINOJSON_ASSERT( s2 != NULL );
828 for ( ;;) {
829 char c1 = *s1++;
830 char c2 = static_cast<char>(pgm_read_byte( s2++ ));
831 if ( c1 < c2 )
832 return -1;
833 if ( c1 > c2 )
834 return 1;
835 if ( c1 == 0 /* and c2 as well */ )
836 return 0;
837 }
838}
839#endif
840#ifndef memcmp_P
841inline int memcmp_P( const void* a, ArduinoJson::detail::pgm_p b, size_t n ) {
842 const uint8_t* p1 = reinterpret_cast<const uint8_t*>(a);
843 const char* p2 = b.address;
844 ARDUINOJSON_ASSERT( p1 != NULL );
845 ARDUINOJSON_ASSERT( p2 != NULL );
846 while ( n-- > 0 ) {
847 uint8_t v1 = *p1++;
848 uint8_t v2 = pgm_read_byte( p2++ );
849 if ( v1 != v2 )
850 return v1 - v2;
851 }
852 return 0;
853}
854#endif
855#ifndef memcpy_P
856inline void* memcpy_P( void* dst, ArduinoJson::detail::pgm_p src, size_t n ) {
857 uint8_t* d = reinterpret_cast<uint8_t*>(dst);
858 const char* s = src.address;
859 ARDUINOJSON_ASSERT( d != NULL );
860 ARDUINOJSON_ASSERT( s != NULL );
861 while ( n-- > 0 ) {
862 *d++ = pgm_read_byte( s++ );
863 }
864 return dst;
865}
866#endif
867#ifndef pgm_read_dword
868inline uint32_t pgm_read_dword( ArduinoJson::detail::pgm_p p ) {
869 uint32_t result;
870 memcpy_P( &result, p.address, 4 );
871 return result;
872}
873#endif
874#ifndef pgm_read_float
875inline float pgm_read_float( ArduinoJson::detail::pgm_p p ) {
876 float result;
877 memcpy_P( &result, p.address, sizeof( float ) );
878 return result;
879}
880#endif
881#ifndef pgm_read_double
882# if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_FLOAT__) && \
883 __SIZEOF_DOUBLE__ == __SIZEOF_FLOAT__
884inline double pgm_read_double( ArduinoJson::detail::pgm_p p ) {
885 return pgm_read_float( p.address );
886}
887# else
888inline double pgm_read_double( ArduinoJson::detail::pgm_p p ) {
889 double result;
890 memcpy_P( &result, p.address, sizeof( double ) );
891 return result;
892}
893# endif
894#endif
895#ifndef pgm_read_ptr
896inline void* pgm_read_ptr( ArduinoJson::detail::pgm_p p ) {
897 void* result;
898 memcpy_P( &result, p.address, sizeof( result ) );
899 return result;
900}
901#endif
902ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
903class FlashString {
904public:
905 static const size_t typeSortKey = 1;
906 FlashString( const __FlashStringHelper* str, size_t sz )
907 : str_( reinterpret_cast<const char*>(str) ), size_( sz ) {}
908 bool isNull() const {
909 return !str_;
910 }
911 char operator[]( size_t i ) const {
912 ARDUINOJSON_ASSERT( str_ != 0 );
913 ARDUINOJSON_ASSERT( i <= size_ );
914 return static_cast<char>(pgm_read_byte( str_ + i ));
915 }
916 size_t size() const {
917 return size_;
918 }
919 friend bool stringEquals( FlashString a, SizedRamString b ) {
920 ARDUINOJSON_ASSERT( a.typeSortKey < b.typeSortKey );
921 ARDUINOJSON_ASSERT( !a.isNull() );
922 ARDUINOJSON_ASSERT( !b.isNull() );
923 if ( a.size() != b.size() )
924 return false;
925 return ::memcmp_P( b.data(), a.str_, a.size_ ) == 0;
926 }
927 friend int stringCompare( FlashString a, SizedRamString b ) {
928 ARDUINOJSON_ASSERT( a.typeSortKey < b.typeSortKey );
929 ARDUINOJSON_ASSERT( !a.isNull() );
930 ARDUINOJSON_ASSERT( !b.isNull() );
931 size_t minsize = a.size() < b.size() ? a.size() : b.size();
932 int res = ::memcmp_P( b.data(), a.str_, minsize );
933 if ( res )
934 return -res;
935 if ( a.size() < b.size() )
936 return -1;
937 if ( a.size() > b.size() )
938 return 1;
939 return 0;
940 }
941 friend void stringGetChars( FlashString s, char* p, size_t n ) {
942 ARDUINOJSON_ASSERT( s.size() <= n );
943 ::memcpy_P( p, s.str_, n );
944 }
945 StringStoragePolicy::Copy storagePolicy() const {
946 return StringStoragePolicy::Copy();
947 }
948private:
949 const char* str_;
950 size_t size_;
951};
952template <>
953struct StringAdapter<const __FlashStringHelper*, void> {
954 typedef FlashString AdaptedString;
955 static AdaptedString adapt( const __FlashStringHelper* s ) {
956 return AdaptedString( s, s ? strlen_P( reinterpret_cast<const char*>(s) ) : 0 );
957 }
958};
959template <>
960struct SizedStringAdapter<const __FlashStringHelper*, void> {
961 typedef FlashString AdaptedString;
962 static AdaptedString adapt( const __FlashStringHelper* s, size_t n ) {
963 return AdaptedString( s, n );
964 }
965};
966ARDUINOJSON_END_PRIVATE_NAMESPACE
967#endif
968ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
969template <typename TAdaptedString1, typename TAdaptedString2>
970typename enable_if<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey,
971 int>::type
972 stringCompare( TAdaptedString1 s1, TAdaptedString2 s2 ) {
973 ARDUINOJSON_ASSERT( !s1.isNull() );
974 ARDUINOJSON_ASSERT( !s2.isNull() );
975 size_t size1 = s1.size();
976 size_t size2 = s2.size();
977 size_t n = size1 < size2 ? size1 : size2;
978 for ( size_t i = 0; i < n; i++ ) {
979 if ( s1[i] != s2[i] )
980 return s1[i] - s2[i];
981 }
982 if ( size1 < size2 )
983 return -1;
984 if ( size1 > size2 )
985 return 1;
986 return 0;
987}
988template <typename TAdaptedString1, typename TAdaptedString2>
989typename enable_if<
990 (TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), int>::type
991 stringCompare( TAdaptedString1 s1, TAdaptedString2 s2 ) {
992 return -stringCompare( s2, s1 );
993}
994template <typename TAdaptedString1, typename TAdaptedString2>
995typename enable_if<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey,
996 bool>::type
997 stringEquals( TAdaptedString1 s1, TAdaptedString2 s2 ) {
998 ARDUINOJSON_ASSERT( !s1.isNull() );
999 ARDUINOJSON_ASSERT( !s2.isNull() );
1000 size_t size1 = s1.size();
1001 size_t size2 = s2.size();
1002 if ( size1 != size2 )
1003 return false;
1004 for ( size_t i = 0; i < size1; i++ ) {
1005 if ( s1[i] != s2[i] )
1006 return false;
1007 }
1008 return true;
1009}
1010template <typename TAdaptedString1, typename TAdaptedString2>
1011typename enable_if<
1012 (TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey), bool>::type
1013 stringEquals( TAdaptedString1 s1, TAdaptedString2 s2 ) {
1014 return stringEquals( s2, s1 );
1015}
1016template <typename TAdaptedString>
1017static void stringGetChars( TAdaptedString s, char* p, size_t n ) {
1018 ARDUINOJSON_ASSERT( s.size() <= n );
1019 for ( size_t i = 0; i < n; i++ ) {
1020 p[i] = s[i];
1021 }
1022}
1023template <int Bits>
1024struct int_t;
1025template <>
1026struct int_t<8> {
1027 typedef int8_t type;
1028};
1029template <>
1030struct int_t<16> {
1031 typedef int16_t type;
1032};
1033template <>
1034struct int_t<32> {
1035 typedef int32_t type;
1036};
1037ARDUINOJSON_END_PRIVATE_NAMESPACE
1038#ifdef _MSC_VER
1039# pragma warning(push)
1040# pragma warning(disable : 4310)
1041#endif
1042ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1043template <typename T, typename Enable = void>
1044struct numeric_limits;
1045template <typename T>
1046struct numeric_limits<T, typename enable_if<is_unsigned<T>::value>::type> {
1047 static T lowest() {
1048 return 0;
1049 }
1050 static T highest() {
1051 return T( -1 );
1052 }
1053};
1054template <typename T>
1055struct numeric_limits<
1056 T, typename enable_if<is_integral<T>::value && is_signed<T>::value>::type> {
1057 static T lowest() {
1058 return T( T( 1 ) << (sizeof( T ) * 8 - 1) );
1059 }
1060 static T highest() {
1061 return T( ~lowest() );
1062 }
1063};
1064ARDUINOJSON_END_PRIVATE_NAMESPACE
1065#ifdef _MSC_VER
1066# pragma warning(pop)
1067#endif
1068ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1069class MemoryPool;
1070class VariantData;
1071class VariantSlot;
1072class CollectionData {
1073 VariantSlot* head_;
1074 VariantSlot* tail_;
1075public:
1076 VariantData* addElement( MemoryPool* pool );
1077 VariantData* getElement( size_t index ) const;
1078 VariantData* getOrAddElement( size_t index, MemoryPool* pool );
1079 void removeElement( size_t index );
1080 template <typename TAdaptedString>
1081 VariantData* addMember( TAdaptedString key, MemoryPool* pool );
1082 template <typename TAdaptedString>
1083 VariantData* getMember( TAdaptedString key ) const;
1084 template <typename TAdaptedString>
1085 VariantData* getOrAddMember( TAdaptedString key, MemoryPool* pool );
1086 template <typename TAdaptedString>
1087 void removeMember( TAdaptedString key ) {
1088 removeSlot( getSlot( key ) );
1089 }
1090 template <typename TAdaptedString>
1091 bool containsKey( const TAdaptedString& key ) const;
1092 void clear();
1093 size_t memoryUsage() const;
1094 size_t size() const;
1095 VariantSlot* addSlot( MemoryPool* );
1096 void removeSlot( VariantSlot* slot );
1097 bool copyFrom( const CollectionData& src, MemoryPool* pool );
1098 VariantSlot* head() const {
1099 return head_;
1100 }
1101 void movePointers( ptrdiff_t stringDistance, ptrdiff_t variantDistance );
1102private:
1103 VariantSlot* getSlot( size_t index ) const;
1104 template <typename TAdaptedString>
1105 VariantSlot* getSlot( TAdaptedString key ) const;
1106 VariantSlot* getPreviousSlot( VariantSlot* ) const;
1107};
1108inline const VariantData* collectionToVariant(
1109 const CollectionData* collection ) {
1110 const void* data = collection; // prevent warning cast-align
1111 return reinterpret_cast<const VariantData*>(data);
1112}
1113inline VariantData* collectionToVariant( CollectionData* collection ) {
1114 void* data = collection; // prevent warning cast-align
1115 return reinterpret_cast<VariantData*>(data);
1116}
1117ARDUINOJSON_END_PRIVATE_NAMESPACE
1118ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
1119#if ARDUINOJSON_USE_DOUBLE
1120typedef double JsonFloat;
1121#else
1122typedef float JsonFloat;
1123#endif
1124#if ARDUINOJSON_USE_LONG_LONG
1125typedef int64_t JsonInteger;
1126typedef uint64_t JsonUInt;
1127#else
1128typedef long JsonInteger;
1129typedef unsigned long JsonUInt;
1130#endif
1131ARDUINOJSON_END_PUBLIC_NAMESPACE
1132#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \
1133 static_assert(sizeof(T) <= sizeof(ArduinoJson::JsonInteger), \
1134 "To use 64-bit integers with ArduinoJson, you must set " \
1135 "ARDUINOJSON_USE_LONG_LONG to 1. See " \
1136 "https://arduinojson.org/v6/api/config/use_long_long/");
1137ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1138enum {
1139 VALUE_MASK = 0x7F,
1140 OWNED_VALUE_BIT = 0x01,
1141 VALUE_IS_NULL = 0,
1142 VALUE_IS_LINKED_RAW = 0x02,
1143 VALUE_IS_OWNED_RAW = 0x03,
1144 VALUE_IS_LINKED_STRING = 0x04,
1145 VALUE_IS_OWNED_STRING = 0x05,
1146 VALUE_IS_BOOLEAN = 0x06,
1147 NUMBER_BIT = 0x08,
1148 VALUE_IS_UNSIGNED_INTEGER = 0x08,
1149 VALUE_IS_SIGNED_INTEGER = 0x0A,
1150 VALUE_IS_FLOAT = 0x0C,
1151 COLLECTION_MASK = 0x60,
1152 VALUE_IS_OBJECT = 0x20,
1153 VALUE_IS_ARRAY = 0x40,
1154 OWNED_KEY_BIT = 0x80
1155};
1156struct RawData {
1157 const char* data;
1158 size_t size;
1159};
1160union VariantContent {
1161 JsonFloat asFloat;
1162 bool asBoolean;
1163 JsonUInt asUnsignedInteger;
1164 JsonInteger asSignedInteger;
1165 CollectionData asCollection;
1166 struct {
1167 const char* data;
1168 size_t size;
1169 } asString;
1170};
1171typedef int_t<ARDUINOJSON_SLOT_OFFSET_SIZE * 8>::type VariantSlotDiff;
1172class VariantSlot {
1173 VariantContent content_;
1174 uint8_t flags_;
1175 VariantSlotDiff next_;
1176 const char* key_;
1177public:
1178 VariantData* data() {
1179 return reinterpret_cast<VariantData*>(&content_);
1180 }
1181 const VariantData* data() const {
1182 return reinterpret_cast<const VariantData*>(&content_);
1183 }
1184 VariantSlot* next() {
1185 return next_ ? this + next_ : 0;
1186 }
1187 const VariantSlot* next() const {
1188 return const_cast<VariantSlot*>(this)->next();
1189 }
1190 VariantSlot* next( size_t distance ) {
1191 VariantSlot* slot = this;
1192 while ( distance-- ) {
1193 if ( !slot->next_ )
1194 return 0;
1195 slot += slot->next_;
1196 }
1197 return slot;
1198 }
1199 const VariantSlot* next( size_t distance ) const {
1200 return const_cast<VariantSlot*>(this)->next( distance );
1201 }
1202 void setNext( VariantSlot* slot ) {
1203 ARDUINOJSON_ASSERT( !slot || slot - this >=
1204 numeric_limits<VariantSlotDiff>::lowest() );
1205 ARDUINOJSON_ASSERT( !slot || slot - this <=
1206 numeric_limits<VariantSlotDiff>::highest() );
1207 next_ = VariantSlotDiff( slot ? slot - this : 0 );
1208 }
1209 void setNextNotNull( VariantSlot* slot ) {
1210 ARDUINOJSON_ASSERT( slot != 0 );
1211 ARDUINOJSON_ASSERT( slot - this >=
1212 numeric_limits<VariantSlotDiff>::lowest() );
1213 ARDUINOJSON_ASSERT( slot - this <=
1214 numeric_limits<VariantSlotDiff>::highest() );
1215 next_ = VariantSlotDiff( slot - this );
1216 }
1217 void setKey( JsonString k ) {
1218 ARDUINOJSON_ASSERT( k );
1219 if ( k.isLinked() )
1220 flags_ &= VALUE_MASK;
1221 else
1222 flags_ |= OWNED_KEY_BIT;
1223 key_ = k.c_str();
1224 }
1225 const char* key() const {
1226 return key_;
1227 }
1228 bool ownsKey() const {
1229 return (flags_ & OWNED_KEY_BIT) != 0;
1230 }
1231 void clear() {
1232 next_ = 0;
1233 flags_ = 0;
1234 key_ = 0;
1235 }
1236 void movePointers( ptrdiff_t stringDistance, ptrdiff_t variantDistance ) {
1237 if ( flags_ & OWNED_KEY_BIT )
1238 key_ += stringDistance;
1239 if ( flags_ & OWNED_VALUE_BIT )
1240 content_.asString.data += stringDistance;
1241 if ( flags_ & COLLECTION_MASK )
1242 content_.asCollection.movePointers( stringDistance, variantDistance );
1243 }
1244};
1245ARDUINOJSON_END_PRIVATE_NAMESPACE
1246#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
1247#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
1248 ((NUMBER_OF_ELEMENTS) * sizeof(ArduinoJson::detail::VariantSlot))
1249#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
1250 ((NUMBER_OF_ELEMENTS) * sizeof(ArduinoJson::detail::VariantSlot))
1251ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1252class MemoryPool {
1253public:
1254 MemoryPool( char* buf, size_t capa )
1255 : begin_( buf ),
1256 left_( buf ),
1257 right_( buf ? buf + capa : 0 ),
1258 end_( buf ? buf + capa : 0 ),
1259 overflowed_( false ) {
1260 ARDUINOJSON_ASSERT( isAligned( begin_ ) );
1261 ARDUINOJSON_ASSERT( isAligned( right_ ) );
1262 ARDUINOJSON_ASSERT( isAligned( end_ ) );
1263 }
1264 void* buffer() {
1265 return begin_; // NOLINT(clang-analyzer-unix.Malloc)
1266 }
1267 size_t capacity() const {
1268 return size_t( end_ - begin_ );
1269 }
1270 size_t size() const {
1271 return size_t( left_ - begin_ + end_ - right_ );
1272 }
1273 bool overflowed() const {
1274 return overflowed_;
1275 }
1276 VariantSlot* allocVariant() {
1277 return allocRight<VariantSlot>();
1278 }
1279 template <typename TAdaptedString>
1280 const char* saveString( TAdaptedString str ) {
1281 if ( str.isNull() )
1282 return 0;
1283#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
1284 const char* existingCopy = findString( str );
1285 if ( existingCopy )
1286 return existingCopy;
1287#endif
1288 size_t n = str.size();
1289 char* newCopy = allocString( n + 1 );
1290 if ( newCopy ) {
1291 stringGetChars( str, newCopy, n );
1292 newCopy[n] = 0; // force null-terminator
1293 }
1294 return newCopy;
1295 }
1296 void getFreeZone( char** zoneStart, size_t* zoneSize ) const {
1297 *zoneStart = left_;
1298 *zoneSize = size_t( right_ - left_ );
1299 }
1300 const char* saveStringFromFreeZone( size_t len ) {
1301#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
1302 const char* dup = findString( adaptString( left_, len ) );
1303 if ( dup )
1304 return dup;
1305#endif
1306 const char* str = left_;
1307 left_ += len;
1308 *left_++ = 0;
1309 checkInvariants();
1310 return str;
1311 }
1312 void markAsOverflowed() {
1313 overflowed_ = true;
1314 }
1315 void clear() {
1316 left_ = begin_;
1317 right_ = end_;
1318 overflowed_ = false;
1319 }
1320 bool canAlloc( size_t bytes ) const {
1321 return left_ + bytes <= right_;
1322 }
1323 bool owns( void* p ) const {
1324 return begin_ <= p && p < end_;
1325 }
1326 void* operator new(size_t, void* p) {
1327 return p;
1328 }
1329 ptrdiff_t squash() {
1330 char* new_right = addPadding( left_ );
1331 if ( new_right >= right_ )
1332 return 0;
1333 size_t right_size = static_cast<size_t>(end_ - right_);
1334 memmove( new_right, right_, right_size );
1335 ptrdiff_t bytes_reclaimed = right_ - new_right;
1336 right_ = new_right;
1337 end_ = new_right + right_size;
1338 return bytes_reclaimed;
1339 }
1340 void movePointers( ptrdiff_t offset ) {
1341 begin_ += offset;
1342 left_ += offset;
1343 right_ += offset;
1344 end_ += offset;
1345 }
1346private:
1347 void checkInvariants() {
1348 ARDUINOJSON_ASSERT( begin_ <= left_ );
1349 ARDUINOJSON_ASSERT( left_ <= right_ );
1350 ARDUINOJSON_ASSERT( right_ <= end_ );
1351 ARDUINOJSON_ASSERT( isAligned( right_ ) );
1352 }
1353#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
1354 template <typename TAdaptedString>
1355 const char* findString( const TAdaptedString& str ) const {
1356 size_t n = str.size();
1357 for ( char* next = begin_; next + n < left_; ++next ) {
1358 if ( next[n] == '\0' && stringEquals( str, adaptString( next, n ) ) )
1359 return next;
1360 while ( *next )
1361 ++next;
1362 }
1363 return 0;
1364 }
1365#endif
1366 char* allocString( size_t n ) {
1367 if ( !canAlloc( n ) ) {
1368 overflowed_ = true;
1369 return 0;
1370 }
1371 char* s = left_;
1372 left_ += n;
1373 checkInvariants();
1374 return s;
1375 }
1376 template <typename T>
1377 T* allocRight() {
1378 return reinterpret_cast<T*>(allocRight( sizeof( T ) ));
1379 }
1380 void* allocRight( size_t bytes ) {
1381 if ( !canAlloc( bytes ) ) {
1382 overflowed_ = true;
1383 return 0;
1384 }
1385 right_ -= bytes;
1386 return right_;
1387 }
1388 char *begin_, *left_, *right_, *end_;
1389 bool overflowed_;
1390};
1391template <typename TAdaptedString, typename TCallback>
1392bool storeString( MemoryPool* pool, TAdaptedString str,
1393 StringStoragePolicy::Copy, TCallback callback ) {
1394 const char* copy = pool->saveString( str );
1395 JsonString storedString( copy, str.size(), JsonString::Copied );
1396 callback( storedString );
1397 return copy != 0;
1398}
1399template <typename TAdaptedString, typename TCallback>
1400bool storeString( MemoryPool*, TAdaptedString str, StringStoragePolicy::Link,
1401 TCallback callback ) {
1402 JsonString storedString( str.data(), str.size(), JsonString::Linked );
1403 callback( storedString );
1404 return !str.isNull();
1405}
1406template <typename TAdaptedString, typename TCallback>
1407bool storeString( MemoryPool* pool, TAdaptedString str,
1408 StringStoragePolicy::LinkOrCopy policy, TCallback callback ) {
1409 if ( policy.link )
1410 return storeString( pool, str, StringStoragePolicy::Link(), callback );
1411 else
1412 return storeString( pool, str, StringStoragePolicy::Copy(), callback );
1413}
1414template <typename TAdaptedString, typename TCallback>
1415bool storeString( MemoryPool* pool, TAdaptedString str, TCallback callback ) {
1416 return storeString( pool, str, str.storagePolicy(), callback );
1417}
1418template <typename T, typename Enable = void>
1419struct IsString : false_type {};
1420template <typename T>
1421struct IsString<
1422 T, typename make_void<typename StringAdapter<T>::AdaptedString>::type>
1423 : true_type {};
1424ARDUINOJSON_END_PRIVATE_NAMESPACE
1425ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
1426class JsonArray;
1427class JsonObject;
1428class JsonVariant;
1429ARDUINOJSON_END_PUBLIC_NAMESPACE
1430ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1431template <typename T>
1432struct VariantTo {};
1433template <>
1434struct VariantTo<JsonArray> {
1435 typedef JsonArray type;
1436};
1437template <>
1438struct VariantTo<JsonObject> {
1439 typedef JsonObject type;
1440};
1441template <>
1442struct VariantTo<JsonVariant> {
1443 typedef JsonVariant type;
1444};
1445class VariantAttorney {
1446 template <typename TClient>
1447 struct ResultOfGetData {
1448 protected: // <- to avoid GCC's "all member functions in class are private"
1449 static int probe( const VariantData* );
1450 static char probe( VariantData* );
1451 static TClient& client;
1452 public:
1453 typedef typename conditional<sizeof( probe( client.getData() ) ) == sizeof( int ),
1454 const VariantData*, VariantData*>::type type;
1455 };
1456public:
1457 template <typename TClient>
1458 FORCE_INLINE static MemoryPool* getPool( TClient& client ) {
1459 return client.getPool();
1460 }
1461 template <typename TClient>
1462 FORCE_INLINE static typename ResultOfGetData<TClient>::type getData(
1463 TClient& client ) {
1464 return client.getData();
1465 }
1466 template <typename TClient>
1467 FORCE_INLINE static VariantData* getOrCreateData( TClient& client ) {
1468 return client.getOrCreateData();
1469 }
1470};
1471ARDUINOJSON_END_PRIVATE_NAMESPACE
1472ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
1473template <typename T>
1474class SerializedValue {
1475public:
1476 explicit SerializedValue( T str ) : str_( str ) {}
1477 operator T() const {
1478 return str_;
1479 }
1480 const char* data() const {
1481 return str_.c_str();
1482 }
1483 size_t size() const {
1484 return str_.length();
1485 }
1486private:
1487 T str_;
1488};
1489template <typename TChar>
1490class SerializedValue<TChar*> {
1491public:
1492 explicit SerializedValue( TChar* p, size_t n ) : data_( p ), size_( n ) {}
1493 operator TChar*() const {
1494 return data_;
1495 }
1496 TChar* data() const {
1497 return data_;
1498 }
1499 size_t size() const {
1500 return size_;
1501 }
1502private:
1503 TChar* data_;
1504 size_t size_;
1505};
1506template <typename T>
1507inline SerializedValue<T> serialized( T str ) {
1508 return SerializedValue<T>( str );
1509}
1510template <typename TChar>
1511inline SerializedValue<TChar*> serialized( TChar* p ) {
1512 return SerializedValue<TChar*>( p, detail::adaptString( p ).size() );
1513}
1514template <typename TChar>
1515inline SerializedValue<TChar*> serialized( TChar* p, size_t n ) {
1516 return SerializedValue<TChar*>( p, n );
1517}
1518ARDUINOJSON_END_PUBLIC_NAMESPACE
1519#if defined(__clang__)
1520# pragma clang diagnostic push
1521# pragma clang diagnostic ignored "-Wconversion"
1522#elif defined(__GNUC__)
1523# pragma GCC diagnostic push
1524# pragma GCC diagnostic ignored "-Wconversion"
1525#endif
1526#include <stdlib.h>
1527ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1528#ifndef isnan
1529template <typename T>
1530bool isnan( T x ) {
1531 return x != x;
1532}
1533#endif
1534#ifndef isinf
1535template <typename T>
1536bool isinf( T x ) {
1537 return x != 0.0 && x * 2 == x;
1538}
1539#endif
1540template <typename T, typename F>
1541struct alias_cast_t {
1542 union {
1543 F raw;
1544 T data;
1545 };
1546};
1547template <typename T, typename F>
1548T alias_cast( F raw_data ) {
1549 alias_cast_t<T, F> ac;
1550 ac.raw = raw_data;
1551 return ac.data;
1552}
1553ARDUINOJSON_END_PRIVATE_NAMESPACE
1554#if ARDUINOJSON_ENABLE_PROGMEM
1555#endif
1556ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1557#if ARDUINOJSON_ENABLE_PROGMEM
1558# ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY
1559# define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, ...) \
1560 static type const name[] PROGMEM = __VA_ARGS__;
1561# endif
1562template <typename T>
1563inline const T* pgm_read( const T* const* p ) {
1564 return reinterpret_cast<const T*>(pgm_read_ptr( p ));
1565}
1566inline uint32_t pgm_read( const uint32_t* p ) {
1567 return pgm_read_dword( p );
1568}
1569inline double pgm_read( const double* p ) {
1570 return pgm_read_double( p );
1571}
1572inline float pgm_read( const float* p ) {
1573 return pgm_read_float( p );
1574}
1575#else
1576# ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY
1577# define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, ...) \
1578 static type const name[] = __VA_ARGS__;
1579# endif
1580template <typename T>
1581inline T pgm_read( const T* p ) {
1582 return *p;
1583}
1584#endif
1585template <typename T>
1586class pgm_ptr {
1587public:
1588 explicit pgm_ptr( const T* ptr ) : ptr_( ptr ) {}
1589 T operator[]( intptr_t index ) const {
1590 return pgm_read( ptr_ + index );
1591 }
1592private:
1593 const T* ptr_;
1594};
1595template <typename T, size_t = sizeof( T )>
1596struct FloatTraits {};
1597template <typename T>
1598struct FloatTraits<T, 8 /*64bits*/> {
1599 typedef uint64_t mantissa_type;
1600 static const short mantissa_bits = 52;
1601 static const mantissa_type mantissa_max =
1602 (mantissa_type( 1 ) << mantissa_bits) - 1;
1603 typedef int16_t exponent_type;
1604 static const exponent_type exponent_max = 308;
1605 static pgm_ptr<T> positiveBinaryPowersOfTen() {
1606 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( //
1607 uint64_t, factors,
1608 {
1609 0x4024000000000000, // 1e1
1610 0x4059000000000000, // 1e2
1611 0x40C3880000000000, // 1e4
1612 0x4197D78400000000, // 1e8
1613 0x4341C37937E08000, // 1e16
1614 0x4693B8B5B5056E17, // 1e32
1615 0x4D384F03E93FF9F5, // 1e64
1616 0x5A827748F9301D32, // 1e128
1617 0x75154FDD7F73BF3C, // 1e256
1618 } );
1619 return pgm_ptr<T>( reinterpret_cast<const T*>(factors) );
1620 }
1621 static pgm_ptr<T> negativeBinaryPowersOfTen() {
1622 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( //
1623 uint64_t, factors,
1624 {
1625 0x3FB999999999999A, // 1e-1
1626 0x3F847AE147AE147B, // 1e-2
1627 0x3F1A36E2EB1C432D, // 1e-4
1628 0x3E45798EE2308C3A, // 1e-8
1629 0x3C9CD2B297D889BC, // 1e-16
1630 0x3949F623D5A8A733, // 1e-32
1631 0x32A50FFD44F4A73D, // 1e-64
1632 0x255BBA08CF8C979D, // 1e-128
1633 0x0AC8062864AC6F43 // 1e-256
1634 } );
1635 return pgm_ptr<T>( reinterpret_cast<const T*>(factors) );
1636 }
1637 static T nan() {
1638 return forge( 0x7ff8000000000000 );
1639 }
1640 static T inf() {
1641 return forge( 0x7ff0000000000000 );
1642 }
1643 static T highest() {
1644 return forge( 0x7FEFFFFFFFFFFFFF );
1645 }
1646 template <typename TOut> // int64_t
1647 static T highest_for(
1648 typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
1649 sizeof( TOut ) == 8,
1650 signed>::type* = 0 ) {
1651 return forge( 0x43DFFFFFFFFFFFFF ); // 9.2233720368547748e+18
1652 }
1653 template <typename TOut> // uint64_t
1654 static T highest_for(
1655 typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
1656 sizeof( TOut ) == 8,
1657 unsigned>::type* = 0 ) {
1658 return forge( 0x43EFFFFFFFFFFFFF ); // 1.8446744073709549568e+19
1659 }
1660 static T lowest() {
1661 return forge( 0xFFEFFFFFFFFFFFFF );
1662 }
1663 static T forge( uint64_t bits ) {
1664 return alias_cast<T>(bits);
1665 }
1666};
1667template <typename T>
1668struct FloatTraits<T, 4 /*32bits*/> {
1669 typedef uint32_t mantissa_type;
1670 static const short mantissa_bits = 23;
1671 static const mantissa_type mantissa_max =
1672 (mantissa_type( 1 ) << mantissa_bits) - 1;
1673 typedef int8_t exponent_type;
1674 static const exponent_type exponent_max = 38;
1675 static pgm_ptr<T> positiveBinaryPowersOfTen() {
1676 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( uint32_t, factors,
1677 {
1678 0x41200000, // 1e1f
1679 0x42c80000, // 1e2f
1680 0x461c4000, // 1e4f
1681 0x4cbebc20, // 1e8f
1682 0x5a0e1bca, // 1e16f
1683 0x749dc5ae // 1e32f
1684 } );
1685 return pgm_ptr<T>( reinterpret_cast<const T*>(factors) );
1686 }
1687 static pgm_ptr<T> negativeBinaryPowersOfTen() {
1688 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( uint32_t, factors,
1689 {
1690 0x3dcccccd, // 1e-1f
1691 0x3c23d70a, // 1e-2f
1692 0x38d1b717, // 1e-4f
1693 0x322bcc77, // 1e-8f
1694 0x24e69595, // 1e-16f
1695 0x0a4fb11f // 1e-32f
1696 } );
1697 return pgm_ptr<T>( reinterpret_cast<const T*>(factors) );
1698 }
1699 static T forge( uint32_t bits ) {
1700 return alias_cast<T>(bits);
1701 }
1702 static T nan() {
1703 return forge( 0x7fc00000 );
1704 }
1705 static T inf() {
1706 return forge( 0x7f800000 );
1707 }
1708 static T highest() {
1709 return forge( 0x7f7fffff );
1710 }
1711 template <typename TOut> // int32_t
1712 static T highest_for(
1713 typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
1714 sizeof( TOut ) == 4,
1715 signed>::type* = 0 ) {
1716 return forge( 0x4EFFFFFF ); // 2.14748352E9
1717 }
1718 template <typename TOut> // uint32_t
1719 static T highest_for(
1720 typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
1721 sizeof( TOut ) == 4,
1722 unsigned>::type* = 0 ) {
1723 return forge( 0x4F7FFFFF ); // 4.29496704E9
1724 }
1725 template <typename TOut> // int64_t
1726 static T highest_for(
1727 typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
1728 sizeof( TOut ) == 8,
1729 signed>::type* = 0 ) {
1730 return forge( 0x5EFFFFFF ); // 9.22337148709896192E18
1731 }
1732 template <typename TOut> // uint64_t
1733 static T highest_for(
1734 typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
1735 sizeof( TOut ) == 8,
1736 unsigned>::type* = 0 ) {
1737 return forge( 0x5F7FFFFF ); // 1.844674297419792384E19
1738 }
1739 static T lowest() {
1740 return forge( 0xFf7fffff );
1741 }
1742};
1743template <typename TFloat, typename TExponent>
1744inline TFloat make_float( TFloat m, TExponent e ) {
1745 using traits = FloatTraits<TFloat>;
1746 auto powersOfTen = e > 0 ? traits::positiveBinaryPowersOfTen()
1747 : traits::negativeBinaryPowersOfTen();
1748 if ( e <= 0 )
1749 e = TExponent( -e );
1750 for ( uint8_t index = 0; e != 0; index++ ) {
1751 if ( e & 1 )
1752 m *= powersOfTen[index];
1753 e >>= 1;
1754 }
1755 return m;
1756}
1757template <typename TOut, typename TIn>
1758typename enable_if<is_integral<TIn>::value && is_unsigned<TIn>::value &&
1759 is_integral<TOut>::value && sizeof( TOut ) <= sizeof( TIn ),
1760 bool>::type
1761 canConvertNumber( TIn value ) {
1762 return value <= TIn( numeric_limits<TOut>::highest() );
1763}
1764template <typename TOut, typename TIn>
1765typename enable_if < is_integral<TIn>::value && is_unsigned<TIn>::value &&
1766 is_integral<TOut>::value && sizeof( TIn ) < sizeof( TOut ),
1767 bool > ::type
1768 canConvertNumber( TIn ) {
1769 return true;
1770}
1771template <typename TOut, typename TIn>
1772typename enable_if<is_integral<TIn>::value && is_floating_point<TOut>::value,
1773 bool>::type
1774 canConvertNumber( TIn ) {
1775 return true;
1776}
1777template <typename TOut, typename TIn>
1778typename enable_if < is_integral<TIn>::value && is_signed<TIn>::value &&
1779 is_integral<TOut>::value && is_signed<TOut>::value &&
1780 sizeof( TOut ) < sizeof( TIn ),
1781 bool > ::type
1782 canConvertNumber( TIn value ) {
1783 return value >= TIn( numeric_limits<TOut>::lowest() ) &&
1784 value <= TIn( numeric_limits<TOut>::highest() );
1785}
1786template <typename TOut, typename TIn>
1787typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
1788 is_integral<TOut>::value && is_signed<TOut>::value &&
1789 sizeof( TIn ) <= sizeof( TOut ),
1790 bool>::type
1791 canConvertNumber( TIn ) {
1792 return true;
1793}
1794template <typename TOut, typename TIn>
1795typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
1796 is_integral<TOut>::value && is_unsigned<TOut>::value &&
1797 sizeof( TOut ) >= sizeof( TIn ),
1798 bool>::type
1799 canConvertNumber( TIn value ) {
1800 if ( value < 0 )
1801 return false;
1802 return TOut( value ) <= numeric_limits<TOut>::highest();
1803}
1804template <typename TOut, typename TIn>
1805typename enable_if < is_integral<TIn>::value && is_signed<TIn>::value &&
1806 is_integral<TOut>::value && is_unsigned<TOut>::value &&
1807 sizeof( TOut ) < sizeof( TIn ),
1808 bool > ::type
1809 canConvertNumber( TIn value ) {
1810 if ( value < 0 )
1811 return false;
1812 return value <= TIn( numeric_limits<TOut>::highest() );
1813}
1814template <typename TOut, typename TIn>
1815typename enable_if < is_floating_point<TIn>::value && is_integral<TOut>::value &&
1816 sizeof( TOut ) < sizeof( TIn ),
1817 bool > ::type
1818 canConvertNumber( TIn value ) {
1819 return value >= numeric_limits<TOut>::lowest() &&
1820 value <= numeric_limits<TOut>::highest();
1821}
1822template <typename TOut, typename TIn>
1823typename enable_if<is_floating_point<TIn>::value && is_integral<TOut>::value &&
1824 sizeof( TOut ) >= sizeof( TIn ),
1825 bool>::type
1826 canConvertNumber( TIn value ) {
1827 return value >= numeric_limits<TOut>::lowest() &&
1828 value <= FloatTraits<TIn>::template highest_for<TOut>();
1829}
1830template <typename TOut, typename TIn>
1831TOut convertNumber( TIn value ) {
1832 return canConvertNumber<TOut>( value ) ? TOut( value ) : 0;
1833}
1834ARDUINOJSON_END_PRIVATE_NAMESPACE
1835#if defined(__clang__)
1836# pragma clang diagnostic pop
1837#elif defined(__GNUC__)
1838# pragma GCC diagnostic pop
1839#endif
1840ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1841class VariantData {
1842 VariantContent content_; // must be first to allow cast from array to variant
1843 uint8_t flags_;
1844public:
1845 VariantData() : flags_( VALUE_IS_NULL ) {}
1846 void operator=( const VariantData& src ) {
1847 content_ = src.content_;
1848 flags_ = uint8_t( (flags_ & OWNED_KEY_BIT) | (src.flags_ & ~OWNED_KEY_BIT) );
1849 }
1850 template <typename TVisitor>
1851 typename TVisitor::result_type accept( TVisitor& visitor ) const {
1852 switch ( type() ) {
1853 case VALUE_IS_FLOAT:
1854 return visitor.visitFloat( content_.asFloat );
1855 case VALUE_IS_ARRAY:
1856 return visitor.visitArray( content_.asCollection );
1857 case VALUE_IS_OBJECT:
1858 return visitor.visitObject( content_.asCollection );
1859 case VALUE_IS_LINKED_STRING:
1860 case VALUE_IS_OWNED_STRING:
1861 return visitor.visitString( content_.asString.data,
1862 content_.asString.size );
1863 case VALUE_IS_OWNED_RAW:
1864 case VALUE_IS_LINKED_RAW:
1865 return visitor.visitRawJson( content_.asString.data,
1866 content_.asString.size );
1867 case VALUE_IS_SIGNED_INTEGER:
1868 return visitor.visitSignedInteger( content_.asSignedInteger );
1869 case VALUE_IS_UNSIGNED_INTEGER:
1870 return visitor.visitUnsignedInteger( content_.asUnsignedInteger );
1871 case VALUE_IS_BOOLEAN:
1872 return visitor.visitBoolean( content_.asBoolean != 0 );
1873 default:
1874 return visitor.visitNull();
1875 }
1876 }
1877 template <typename T>
1878 T asIntegral() const;
1879 template <typename T>
1880 T asFloat() const;
1881 JsonString asString() const;
1882 bool asBoolean() const;
1883 CollectionData* asArray() {
1884 return isArray() ? &content_.asCollection : 0;
1885 }
1886 const CollectionData* asArray() const {
1887 return const_cast<VariantData*>(this)->asArray();
1888 }
1889 const CollectionData* asCollection() const {
1890 return isCollection() ? &content_.asCollection : 0;
1891 }
1892 CollectionData* asObject() {
1893 return isObject() ? &content_.asCollection : 0;
1894 }
1895 const CollectionData* asObject() const {
1896 return const_cast<VariantData*>(this)->asObject();
1897 }
1898 bool copyFrom( const VariantData& src, MemoryPool* pool );
1899 bool isArray() const {
1900 return (flags_ & VALUE_IS_ARRAY) != 0;
1901 }
1902 bool isBoolean() const {
1903 return type() == VALUE_IS_BOOLEAN;
1904 }
1905 bool isCollection() const {
1906 return (flags_ & COLLECTION_MASK) != 0;
1907 }
1908 template <typename T>
1909 bool isInteger() const {
1910 switch ( type() ) {
1911 case VALUE_IS_UNSIGNED_INTEGER:
1912 return canConvertNumber<T>( content_.asUnsignedInteger );
1913 case VALUE_IS_SIGNED_INTEGER:
1914 return canConvertNumber<T>( content_.asSignedInteger );
1915 default:
1916 return false;
1917 }
1918 }
1919 bool isFloat() const {
1920 return (flags_ & NUMBER_BIT) != 0;
1921 }
1922 bool isString() const {
1923 return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
1924 }
1925 bool isObject() const {
1926 return (flags_ & VALUE_IS_OBJECT) != 0;
1927 }
1928 bool isNull() const {
1929 return type() == VALUE_IS_NULL;
1930 }
1931 bool isEnclosed() const {
1932 return !isFloat();
1933 }
1934 void remove( size_t index ) {
1935 if ( isArray() )
1936 content_.asCollection.removeElement( index );
1937 }
1938 template <typename TAdaptedString>
1939 void remove( TAdaptedString key ) {
1940 if ( isObject() )
1941 content_.asCollection.removeMember( key );
1942 }
1943 void setBoolean( bool value ) {
1944 setType( VALUE_IS_BOOLEAN );
1945 content_.asBoolean = value;
1946 }
1947 void setFloat( JsonFloat value ) {
1948 setType( VALUE_IS_FLOAT );
1949 content_.asFloat = value;
1950 }
1951 void setLinkedRaw( SerializedValue<const char*> value ) {
1952 if ( value.data() ) {
1953 setType( VALUE_IS_LINKED_RAW );
1954 content_.asString.data = value.data();
1955 content_.asString.size = value.size();
1956 }
1957 else {
1958 setType( VALUE_IS_NULL );
1959 }
1960 }
1961 template <typename T>
1962 bool storeOwnedRaw( SerializedValue<T> value, MemoryPool* pool ) {
1963 const char* dup = pool->saveString( adaptString( value.data(), value.size() ) );
1964 if ( dup ) {
1965 setType( VALUE_IS_OWNED_RAW );
1966 content_.asString.data = dup;
1967 content_.asString.size = value.size();
1968 return true;
1969 }
1970 else {
1971 setType( VALUE_IS_NULL );
1972 return false;
1973 }
1974 }
1975 template <typename T>
1976 typename enable_if<is_unsigned<T>::value>::type setInteger( T value ) {
1977 setType( VALUE_IS_UNSIGNED_INTEGER );
1978 content_.asUnsignedInteger = static_cast<JsonUInt>(value);
1979 }
1980 template <typename T>
1981 typename enable_if<is_signed<T>::value>::type setInteger( T value ) {
1982 setType( VALUE_IS_SIGNED_INTEGER );
1983 content_.asSignedInteger = value;
1984 }
1985 void setNull() {
1986 setType( VALUE_IS_NULL );
1987 }
1988 void setString( JsonString s ) {
1989 ARDUINOJSON_ASSERT( s );
1990 if ( s.isLinked() )
1991 setType( VALUE_IS_LINKED_STRING );
1992 else
1993 setType( VALUE_IS_OWNED_STRING );
1994 content_.asString.data = s.c_str();
1995 content_.asString.size = s.size();
1996 }
1997 CollectionData& toArray() {
1998 setType( VALUE_IS_ARRAY );
1999 content_.asCollection.clear();
2000 return content_.asCollection;
2001 }
2002 CollectionData& toObject() {
2003 setType( VALUE_IS_OBJECT );
2004 content_.asCollection.clear();
2005 return content_.asCollection;
2006 }
2007 size_t memoryUsage() const {
2008 switch ( type() ) {
2009 case VALUE_IS_OWNED_STRING:
2010 case VALUE_IS_OWNED_RAW:
2011 return content_.asString.size + 1;
2012 case VALUE_IS_OBJECT:
2013 case VALUE_IS_ARRAY:
2014 return content_.asCollection.memoryUsage();
2015 default:
2016 return 0;
2017 }
2018 }
2019 size_t size() const {
2020 return isCollection() ? content_.asCollection.size() : 0;
2021 }
2022 VariantData* addElement( MemoryPool* pool ) {
2023 if ( isNull() )
2024 toArray();
2025 if ( !isArray() )
2026 return 0;
2027 return content_.asCollection.addElement( pool );
2028 }
2029 VariantData* getElement( size_t index ) const {
2030 const CollectionData* col = asArray();
2031 return col ? col->getElement( index ) : 0;
2032 }
2033 VariantData* getOrAddElement( size_t index, MemoryPool* pool ) {
2034 if ( isNull() )
2035 toArray();
2036 if ( !isArray() )
2037 return 0;
2038 return content_.asCollection.getOrAddElement( index, pool );
2039 }
2040 template <typename TAdaptedString>
2041 VariantData* getMember( TAdaptedString key ) const {
2042 const CollectionData* col = asObject();
2043 return col ? col->getMember( key ) : 0;
2044 }
2045 template <typename TAdaptedString>
2046 VariantData* getOrAddMember( TAdaptedString key, MemoryPool* pool ) {
2047 if ( isNull() )
2048 toObject();
2049 if ( !isObject() )
2050 return 0;
2051 return content_.asCollection.getOrAddMember( key, pool );
2052 }
2053 void movePointers( ptrdiff_t stringDistance, ptrdiff_t variantDistance ) {
2054 if ( flags_ & OWNED_VALUE_BIT )
2055 content_.asString.data += stringDistance;
2056 if ( flags_ & COLLECTION_MASK )
2057 content_.asCollection.movePointers( stringDistance, variantDistance );
2058 }
2059 uint8_t type() const {
2060 return flags_ & VALUE_MASK;
2061 }
2062 template <typename TAdaptedString>
2063 inline bool setString( TAdaptedString value, MemoryPool* pool ) {
2064 if ( value.isNull() ) {
2065 setNull();
2066 return true;
2067 }
2068 return storeString( pool, value, VariantStringSetter( this ) );
2069 }
2070private:
2071 void setType( uint8_t t ) {
2072 flags_ &= OWNED_KEY_BIT;
2073 flags_ |= t;
2074 }
2075 struct VariantStringSetter {
2076 VariantStringSetter( VariantData* instance ) : instance_( instance ) {}
2077 template <typename TStoredString>
2078 void operator()( TStoredString s ) {
2079 if ( s )
2080 instance_->setString( s );
2081 else
2082 instance_->setNull();
2083 }
2084 VariantData* instance_;
2085 };
2086};
2087template <typename TResult>
2088struct Visitor {
2089 typedef TResult result_type;
2090 TResult visitArray( const CollectionData& ) {
2091 return TResult();
2092 }
2093 TResult visitBoolean( bool ) {
2094 return TResult();
2095 }
2096 TResult visitFloat( JsonFloat ) {
2097 return TResult();
2098 }
2099 TResult visitSignedInteger( JsonInteger ) {
2100 return TResult();
2101 }
2102 TResult visitNull() {
2103 return TResult();
2104 }
2105 TResult visitObject( const CollectionData& ) {
2106 return TResult();
2107 }
2108 TResult visitUnsignedInteger( JsonUInt ) {
2109 return TResult();
2110 }
2111 TResult visitRawJson( const char*, size_t ) {
2112 return TResult();
2113 }
2114 TResult visitString( const char*, size_t ) {
2115 return TResult();
2116 }
2117};
2118template <typename TVisitor>
2119inline typename TVisitor::result_type variantAccept( const VariantData* var,
2120 TVisitor& visitor ) {
2121 if ( var != 0 )
2122 return var->accept( visitor );
2123 else
2124 return visitor.visitNull();
2125}
2126inline bool variantCopyFrom( VariantData* dst, const VariantData* src,
2127 MemoryPool* pool ) {
2128 if ( !dst )
2129 return false;
2130 if ( !src ) {
2131 dst->setNull();
2132 return true;
2133 }
2134 return dst->copyFrom( *src, pool );
2135}
2136inline void variantSetNull( VariantData* var ) {
2137 if ( !var )
2138 return;
2139 var->setNull();
2140}
2141template <typename TAdaptedString>
2142inline bool variantSetString( VariantData* var, TAdaptedString value,
2143 MemoryPool* pool ) {
2144 return var != 0 ? var->setString( value, pool ) : 0;
2145}
2146inline size_t variantSize( const VariantData* var ) {
2147 return var != 0 ? var->size() : 0;
2148}
2149inline CollectionData* variantToArray( VariantData* var ) {
2150 if ( !var )
2151 return 0;
2152 return &var->toArray();
2153}
2154inline CollectionData* variantToObject( VariantData* var ) {
2155 if ( !var )
2156 return 0;
2157 return &var->toObject();
2158}
2159inline VariantData* variantGetElement( const VariantData* var, size_t index ) {
2160 return var != 0 ? var->getElement( index ) : 0;
2161}
2162inline NO_INLINE VariantData* variantAddElement( VariantData* var,
2163 MemoryPool* pool ) {
2164 return var != 0 ? var->addElement( pool ) : 0;
2165}
2166inline NO_INLINE VariantData* variantGetOrAddElement( VariantData* var,
2167 size_t index,
2168 MemoryPool* pool ) {
2169 return var != 0 ? var->getOrAddElement( index, pool ) : 0;
2170}
2171template <typename TAdaptedString>
2172VariantData* variantGetMember( const VariantData* var, TAdaptedString key ) {
2173 if ( !var )
2174 return 0;
2175 return var->getMember( key );
2176}
2177template <typename TAdaptedString>
2178VariantData* variantGetOrAddMember( VariantData* var, TAdaptedString key,
2179 MemoryPool* pool ) {
2180 if ( !var )
2181 return 0;
2182 return var->getOrAddMember( key, pool );
2183}
2184inline bool variantIsNull( const VariantData* var ) {
2185 return var == 0 || var->isNull();
2186}
2187inline size_t variantNesting( const VariantData* var ) {
2188 if ( !var )
2189 return 0;
2190 const CollectionData* collection = var->asCollection();
2191 if ( !collection )
2192 return 0;
2193 size_t maxChildNesting = 0;
2194 for ( const VariantSlot* s = collection->head(); s; s = s->next() ) {
2195 size_t childNesting = variantNesting( s->data() );
2196 if ( childNesting > maxChildNesting )
2197 maxChildNesting = childNesting;
2198 }
2199 return maxChildNesting + 1;
2200}
2201enum CompareResult {
2202 COMPARE_RESULT_DIFFER = 0,
2203 COMPARE_RESULT_EQUAL = 1,
2204 COMPARE_RESULT_GREATER = 2,
2205 COMPARE_RESULT_LESS = 4,
2206 COMPARE_RESULT_GREATER_OR_EQUAL = 3,
2207 COMPARE_RESULT_LESS_OR_EQUAL = 5
2208};
2209template <typename T>
2210CompareResult arithmeticCompare( const T& lhs, const T& rhs ) {
2211 if ( lhs < rhs )
2212 return COMPARE_RESULT_LESS;
2213 else if ( lhs > rhs )
2214 return COMPARE_RESULT_GREATER;
2215 else
2216 return COMPARE_RESULT_EQUAL;
2217}
2218template <typename T1, typename T2>
2219CompareResult arithmeticCompare(
2220 const T1& lhs, const T2& rhs,
2221 typename enable_if < is_integral<T1>::value && is_integral<T2>::value &&
2222 sizeof( T1 ) < sizeof( T2 ) > ::type* = 0 ) {
2223 return arithmeticCompare<T2>( static_cast<T2>(lhs), rhs );
2224}
2225template <typename T1, typename T2>
2226CompareResult arithmeticCompare(
2227 const T1& lhs, const T2& rhs,
2228 typename enable_if < is_integral<T1>::value && is_integral<T2>::value &&
2229 sizeof( T2 ) < sizeof( T1 ) > ::type* = 0 ) {
2230 return arithmeticCompare<T1>( lhs, static_cast<T1>(rhs) );
2231}
2232template <typename T1, typename T2>
2233CompareResult arithmeticCompare(
2234 const T1& lhs, const T2& rhs,
2235 typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
2236 is_signed<T1>::value == is_signed<T2>::value &&
2237 sizeof( T2 ) == sizeof( T1 )>::type * = 0 ) {
2238 return arithmeticCompare<T1>( lhs, static_cast<T1>(rhs) );
2239}
2240template <typename T1, typename T2>
2241CompareResult arithmeticCompare(
2242 const T1& lhs, const T2& rhs,
2243 typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
2244 is_unsigned<T1>::value && is_signed<T2>::value &&
2245 sizeof( T2 ) == sizeof( T1 )>::type* = 0 ) {
2246 if ( rhs < 0 )
2247 return COMPARE_RESULT_GREATER;
2248 return arithmeticCompare<T1>( lhs, static_cast<T1>(rhs) );
2249}
2250template <typename T1, typename T2>
2251CompareResult arithmeticCompare(
2252 const T1& lhs, const T2& rhs,
2253 typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
2254 is_signed<T1>::value && is_unsigned<T2>::value &&
2255 sizeof( T2 ) == sizeof( T1 )>::type* = 0 ) {
2256 if ( lhs < 0 )
2257 return COMPARE_RESULT_LESS;
2258 return arithmeticCompare<T2>( static_cast<T2>(lhs), rhs );
2259}
2260template <typename T1, typename T2>
2261CompareResult arithmeticCompare(
2262 const T1& lhs, const T2& rhs,
2263 typename enable_if<is_floating_point<T1>::value ||
2264 is_floating_point<T2>::value>::type* = 0 ) {
2265 return arithmeticCompare<double>( static_cast<double>(lhs),
2266 static_cast<double>(rhs) );
2267}
2268template <typename T2>
2269CompareResult arithmeticCompareNegateLeft(
2270 JsonUInt, const T2&,
2271 typename enable_if<is_unsigned<T2>::value>::type* = 0 ) {
2272 return COMPARE_RESULT_LESS;
2273}
2274template <typename T2>
2275CompareResult arithmeticCompareNegateLeft(
2276 JsonUInt lhs, const T2& rhs,
2277 typename enable_if<is_signed<T2>::value>::type* = 0 ) {
2278 if ( rhs > 0 )
2279 return COMPARE_RESULT_LESS;
2280 return arithmeticCompare( -rhs, static_cast<T2>(lhs) );
2281}
2282template <typename T1>
2283CompareResult arithmeticCompareNegateRight(
2284 const T1&, JsonUInt,
2285 typename enable_if<is_unsigned<T1>::value>::type* = 0 ) {
2286 return COMPARE_RESULT_GREATER;
2287}
2288template <typename T1>
2289CompareResult arithmeticCompareNegateRight(
2290 const T1& lhs, JsonUInt rhs,
2291 typename enable_if<is_signed<T1>::value>::type* = 0 ) {
2292 if ( lhs > 0 )
2293 return COMPARE_RESULT_GREATER;
2294 return arithmeticCompare( static_cast<T1>(rhs), -lhs );
2295}
2296struct VariantTag {};
2297template <typename T>
2298struct IsVariant : is_base_of<VariantTag, T> {};
2299ARDUINOJSON_END_PRIVATE_NAMESPACE
2300ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2301class JsonVariantConst;
2302ARDUINOJSON_END_PUBLIC_NAMESPACE
2303ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
2304template <typename T>
2305CompareResult compare( JsonVariantConst lhs,
2306 const T& rhs ); // VariantCompare.cpp
2307struct VariantOperatorTag {};
2308template <typename TVariant>
2309struct VariantOperators : VariantOperatorTag {
2310 template <typename T>
2311 friend
2312 typename enable_if<!IsVariant<T>::value && !is_array<T>::value, T>::type
2313 operator|( const TVariant& variant, const T& defaultValue ) {
2314 if ( variant.template is<T>() )
2315 return variant.template as<T>();
2316 else
2317 return defaultValue;
2318 }
2319 friend const char* operator|( const TVariant& variant,
2320 const char* defaultValue ) {
2321 if ( variant.template is<const char*>() )
2322 return variant.template as<const char*>();
2323 else
2324 return defaultValue;
2325 }
2326 template <typename T>
2327 friend typename enable_if<IsVariant<T>::value, JsonVariantConst>::type
2328 operator|( const TVariant& variant, T defaultValue ) {
2329 if ( variant )
2330 return variant;
2331 else
2332 return defaultValue;
2333 }
2334 template <typename T>
2335 friend bool operator==( T* lhs, TVariant rhs ) {
2336 return compare( rhs, lhs ) == COMPARE_RESULT_EQUAL;
2337 }
2338 template <typename T>
2339 friend bool operator==( const T& lhs, TVariant rhs ) {
2340 return compare( rhs, lhs ) == COMPARE_RESULT_EQUAL;
2341 }
2342 template <typename T>
2343 friend bool operator==( TVariant lhs, T* rhs ) {
2344 return compare( lhs, rhs ) == COMPARE_RESULT_EQUAL;
2345 }
2346 template <typename T>
2347 friend
2348 typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
2349 operator==( TVariant lhs, const T& rhs ) {
2350 return compare( lhs, rhs ) == COMPARE_RESULT_EQUAL;
2351 }
2352 template <typename T>
2353 friend bool operator!=( T* lhs, TVariant rhs ) {
2354 return compare( rhs, lhs ) != COMPARE_RESULT_EQUAL;
2355 }
2356 template <typename T>
2357 friend bool operator!=( const T& lhs, TVariant rhs ) {
2358 return compare( rhs, lhs ) != COMPARE_RESULT_EQUAL;
2359 }
2360 template <typename T>
2361 friend bool operator!=( TVariant lhs, T* rhs ) {
2362 return compare( lhs, rhs ) != COMPARE_RESULT_EQUAL;
2363 }
2364 template <typename T>
2365 friend
2366 typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
2367 operator!=( TVariant lhs, const T& rhs ) {
2368 return compare( lhs, rhs ) != COMPARE_RESULT_EQUAL;
2369 }
2370 template <typename T>
2371 friend bool operator<( T* lhs, TVariant rhs ) {
2372 return compare( rhs, lhs ) == COMPARE_RESULT_GREATER;
2373 }
2374 template <typename T>
2375 friend bool operator<( const T& lhs, TVariant rhs ) {
2376 return compare( rhs, lhs ) == COMPARE_RESULT_GREATER;
2377 }
2378 template <typename T>
2379 friend bool operator<( TVariant lhs, T* rhs ) {
2380 return compare( lhs, rhs ) == COMPARE_RESULT_LESS;
2381 }
2382 template <typename T>
2383 friend
2384 typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
2385 operator<( TVariant lhs, const T& rhs ) {
2386 return compare( lhs, rhs ) == COMPARE_RESULT_LESS;
2387 }
2388 template <typename T>
2389 friend bool operator<=( T* lhs, TVariant rhs ) {
2390 return (compare( rhs, lhs ) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2391 }
2392 template <typename T>
2393 friend bool operator<=( const T& lhs, TVariant rhs ) {
2394 return (compare( rhs, lhs ) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2395 }
2396 template <typename T>
2397 friend bool operator<=( TVariant lhs, T* rhs ) {
2398 return (compare( lhs, rhs ) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2399 }
2400 template <typename T>
2401 friend
2402 typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
2403 operator<=( TVariant lhs, const T& rhs ) {
2404 return (compare( lhs, rhs ) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2405 }
2406 template <typename T>
2407 friend bool operator>( T* lhs, TVariant rhs ) {
2408 return compare( rhs, lhs ) == COMPARE_RESULT_LESS;
2409 }
2410 template <typename T>
2411 friend bool operator>( const T& lhs, TVariant rhs ) {
2412 return compare( rhs, lhs ) == COMPARE_RESULT_LESS;
2413 }
2414 template <typename T>
2415 friend bool operator>( TVariant lhs, T* rhs ) {
2416 return compare( lhs, rhs ) == COMPARE_RESULT_GREATER;
2417 }
2418 template <typename T>
2419 friend
2420 typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
2421 operator>( TVariant lhs, const T& rhs ) {
2422 return compare( lhs, rhs ) == COMPARE_RESULT_GREATER;
2423 }
2424 template <typename T>
2425 friend bool operator>=( T* lhs, TVariant rhs ) {
2426 return (compare( rhs, lhs ) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2427 }
2428 template <typename T>
2429 friend bool operator>=( const T& lhs, TVariant rhs ) {
2430 return (compare( rhs, lhs ) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2431 }
2432 template <typename T>
2433 friend bool operator>=( TVariant lhs, T* rhs ) {
2434 return (compare( lhs, rhs ) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2435 }
2436 template <typename T>
2437 friend
2438 typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
2439 operator>=( TVariant lhs, const T& rhs ) {
2440 return (compare( lhs, rhs ) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2441 }
2442};
2443ARDUINOJSON_END_PRIVATE_NAMESPACE
2444ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2445class JsonArray;
2446class JsonObject;
2447class JsonVariantConst : public detail::VariantTag,
2448 public detail::VariantOperators<JsonVariantConst> {
2449 friend class detail::VariantAttorney;
2450public:
2451 JsonVariantConst() : data_( 0 ) {}
2452 explicit JsonVariantConst( const detail::VariantData* data ) : data_( data ) {}
2453 FORCE_INLINE bool isNull() const {
2454 using namespace detail;
2455 return variantIsNull( data_ );
2456 }
2457 FORCE_INLINE bool isUnbound() const {
2458 return !data_;
2459 }
2460 FORCE_INLINE size_t memoryUsage() const {
2461 return data_ ? data_->memoryUsage() : 0;
2462 }
2463 FORCE_INLINE size_t nesting() const {
2464 return variantNesting( data_ );
2465 }
2466 size_t size() const {
2467 return variantSize( data_ );
2468 }
2469 template <typename T>
2470 FORCE_INLINE typename detail::enable_if<!detail::is_same<T, char*>::value &&
2471 !detail::is_same<T, char>::value,
2472 T>::type
2473 as() const {
2474 return Converter<T>::fromJson( *this );
2475 }
2476 template <typename T>
2477 FORCE_INLINE typename detail::enable_if<!detail::is_same<T, char*>::value &&
2478 !detail::is_same<T, char>::value,
2479 bool>::type
2480 is() const {
2481 return Converter<T>::checkJson( *this );
2482 }
2483 template <typename T>
2484 FORCE_INLINE operator T() const {
2485 return as<T>();
2486 }
2487 FORCE_INLINE JsonVariantConst operator[]( size_t index ) const {
2488 return JsonVariantConst( variantGetElement( data_, index ) );
2489 }
2490 template <typename TString>
2491 FORCE_INLINE typename detail::enable_if<detail::IsString<TString>::value,
2492 JsonVariantConst>::type
2493 operator[]( const TString& key ) const {
2494 return JsonVariantConst( variantGetMember( data_, detail::adaptString( key ) ) );
2495 }
2496 template <typename TChar>
2497 FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
2498 JsonVariantConst>::type
2499 operator[]( TChar* key ) const {
2500 return JsonVariantConst( variantGetMember( data_, detail::adaptString( key ) ) );
2501 }
2502 template <typename TString>
2503 FORCE_INLINE
2504 typename detail::enable_if<detail::IsString<TString>::value, bool>::type
2505 containsKey( const TString& key ) const {
2506 return variantGetMember( getData(), detail::adaptString( key ) ) != 0;
2507 }
2508 template <typename TChar>
2509 FORCE_INLINE
2510 typename detail::enable_if<detail::IsString<TChar*>::value, bool>::type
2511 containsKey( TChar* key ) const {
2512 return variantGetMember( getData(), detail::adaptString( key ) ) != 0;
2513 }
2514protected:
2515 const detail::VariantData* getData() const {
2516 return data_;
2517 }
2518private:
2519 const detail::VariantData* data_;
2520};
2521class JsonVariant;
2522ARDUINOJSON_END_PUBLIC_NAMESPACE
2523ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
2524template <typename>
2525class ElementProxy;
2526template <typename, typename>
2527class MemberProxy;
2528template <typename TDerived>
2529class VariantRefBase : public VariantTag {
2530 friend class VariantAttorney;
2531public:
2532 FORCE_INLINE void clear() const {
2533 variantSetNull( getData() );
2534 }
2535 FORCE_INLINE bool isNull() const {
2536 return variantIsNull( getData() );
2537 }
2538 FORCE_INLINE bool isUnbound() const {
2539 return !getData();
2540 }
2541 template <typename T>
2542 FORCE_INLINE
2543 typename enable_if<!ConverterNeedsWriteableRef<T>::value, T>::type
2544 as() const {
2545 return Converter<T>::fromJson( getVariantConst() );
2546 }
2547 template <typename T>
2548 FORCE_INLINE typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
2549 as() const;
2550 template <typename T,
2551 typename = typename enable_if<!is_same<T, TDerived>::value>::type>
2552 FORCE_INLINE operator T() const {
2553 return as<T>();
2554 }
2555 template <typename T>
2556 typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type to() const;
2557 template <typename T>
2558 typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type to()
2559 const;
2560 template <typename T>
2561 typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type to()
2562 const;
2563 template <typename T>
2564 FORCE_INLINE
2565 typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
2566 is() const;
2567 template <typename T>
2568 FORCE_INLINE typename enable_if<!ConverterNeedsWriteableRef<T>::value &&
2569 !is_same<T, char*>::value &&
2570 !is_same<T, char>::value,
2571 bool>::type
2572 is() const {
2573 return Converter<T>::checkJson( getVariantConst() );
2574 }
2575 FORCE_INLINE void shallowCopy( ArduinoJson::JsonVariantConst target ) {
2576 VariantData* data = getOrCreateData();
2577 if ( !data )
2578 return;
2579 const VariantData* targetData = VariantAttorney::getData( target );
2580 if ( targetData )
2581 *data = *targetData;
2582 else
2583 data->setNull();
2584 }
2585 template <typename T>
2586 FORCE_INLINE bool set( const T& value ) const;
2587 template <typename T>
2588 FORCE_INLINE bool set( T* value ) const;
2589 FORCE_INLINE size_t size() const {
2590 return variantSize( getData() );
2591 }
2592 FORCE_INLINE size_t memoryUsage() const {
2593 VariantData* data = getData();
2594 return data ? data->memoryUsage() : 0;
2595 }
2596 FORCE_INLINE size_t nesting() const {
2597 return variantNesting( getData() );
2598 }
2599 FORCE_INLINE JsonVariant add() const;
2600 template <typename T>
2601 FORCE_INLINE bool add( const T& value ) const {
2602 return add().set( value );
2603 }
2604 template <typename T>
2605 FORCE_INLINE bool add( T* value ) const {
2606 return add().set( value );
2607 }
2608 FORCE_INLINE void remove( size_t index ) const {
2609 VariantData* data = getData();
2610 if ( data )
2611 data->remove( index );
2612 }
2613 template <typename TChar>
2614 FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
2615 TChar* key ) const {
2616 VariantData* data = getData();
2617 if ( data )
2618 data->remove( adaptString( key ) );
2619 }
2620 template <typename TString>
2621 FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
2622 const TString& key ) const {
2623 VariantData* data = getData();
2624 if ( data )
2625 data->remove( adaptString( key ) );
2626 }
2627 FORCE_INLINE JsonArray createNestedArray() const;
2628 FORCE_INLINE JsonObject createNestedObject() const;
2629 FORCE_INLINE ElementProxy<TDerived> operator[]( size_t index ) const;
2630 template <typename TString>
2631 FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
2632 containsKey( const TString& key ) const;
2633 template <typename TChar>
2634 FORCE_INLINE typename enable_if<IsString<TChar*>::value, bool>::type
2635 containsKey( TChar* key ) const;
2636 template <typename TString>
2637 FORCE_INLINE typename enable_if<IsString<TString>::value,
2638 MemberProxy<TDerived, TString>>::type
2639 operator[]( const TString& key ) const;
2640 template <typename TChar>
2641 FORCE_INLINE typename enable_if<IsString<TChar*>::value,
2642 MemberProxy<TDerived, TChar*>>::type
2643 operator[]( TChar* key ) const;
2644 template <typename TString>
2645 FORCE_INLINE JsonArray createNestedArray( const TString& key ) const;
2646 template <typename TChar>
2647 FORCE_INLINE JsonArray createNestedArray( TChar* key ) const;
2648 template <typename TString>
2649 JsonObject createNestedObject( const TString& key ) const;
2650 template <typename TChar>
2651 JsonObject createNestedObject( TChar* key ) const;
2652private:
2653 TDerived& derived() {
2654 return static_cast<TDerived&>(*this);
2655 }
2656 const TDerived& derived() const {
2657 return static_cast<const TDerived&>(*this);
2658 }
2659 FORCE_INLINE MemoryPool* getPool() const {
2660 return VariantAttorney::getPool( derived() );
2661 }
2662 FORCE_INLINE VariantData* getData() const {
2663 return VariantAttorney::getData( derived() );
2664 }
2665 FORCE_INLINE VariantData* getOrCreateData() const {
2666 return VariantAttorney::getOrCreateData( derived() );
2667 }
2668private:
2669 FORCE_INLINE ArduinoJson::JsonVariant getVariant() const;
2670 FORCE_INLINE ArduinoJson::JsonVariantConst getVariantConst() const {
2671 return ArduinoJson::JsonVariantConst( getData() );
2672 }
2673 FORCE_INLINE ArduinoJson::JsonVariant getOrCreateVariant() const;
2674};
2675template <typename TUpstream>
2676class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
2677 public VariantOperators<ElementProxy<TUpstream>> {
2678 friend class VariantAttorney;
2679public:
2680 ElementProxy( TUpstream upstream, size_t index )
2681 : upstream_( upstream ), index_( index ) {}
2682 ElementProxy( const ElementProxy& src )
2683 : upstream_( src.upstream_ ), index_( src.index_ ) {}
2684 FORCE_INLINE ElementProxy& operator=( const ElementProxy& src ) {
2685 this->set( src );
2686 return *this;
2687 }
2688 template <typename T>
2689 FORCE_INLINE ElementProxy& operator=( const T& src ) {
2690 this->set( src );
2691 return *this;
2692 }
2693 template <typename T>
2694 FORCE_INLINE ElementProxy& operator=( T* src ) {
2695 this->set( src );
2696 return *this;
2697 }
2698private:
2699 FORCE_INLINE MemoryPool* getPool() const {
2700 return VariantAttorney::getPool( upstream_ );
2701 }
2702 FORCE_INLINE VariantData* getData() const {
2703 return variantGetElement( VariantAttorney::getData( upstream_ ), index_ );
2704 }
2705 FORCE_INLINE VariantData* getOrCreateData() const {
2706 return variantGetOrAddElement( VariantAttorney::getOrCreateData( upstream_ ),
2707 index_, VariantAttorney::getPool( upstream_ ) );
2708 }
2709 TUpstream upstream_;
2710 size_t index_;
2711};
2712ARDUINOJSON_END_PRIVATE_NAMESPACE
2713ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2714class JsonVariant : public detail::VariantRefBase<JsonVariant>,
2715 public detail::VariantOperators<JsonVariant> {
2716 friend class detail::VariantAttorney;
2717public:
2718 JsonVariant() : data_( 0 ), pool_( 0 ) {}
2719 JsonVariant( detail::MemoryPool* pool, detail::VariantData* data )
2720 : data_( data ), pool_( pool ) {}
2721private:
2722 FORCE_INLINE detail::MemoryPool* getPool() const {
2723 return pool_;
2724 }
2725 FORCE_INLINE detail::VariantData* getData() const {
2726 return data_;
2727 }
2728 FORCE_INLINE detail::VariantData* getOrCreateData() const {
2729 return data_;
2730 }
2731 detail::VariantData* data_;
2732 detail::MemoryPool* pool_;
2733};
2734template <>
2735struct Converter<JsonVariant> : private detail::VariantAttorney {
2736 static void toJson( JsonVariant src, JsonVariant dst ) {
2737 detail::variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
2738 }
2739 static JsonVariant fromJson( JsonVariant src ) {
2740 return src;
2741 }
2742 static detail::InvalidConversion<JsonVariantConst, JsonVariant> fromJson(
2743 JsonVariantConst );
2744 static bool checkJson( JsonVariant src ) {
2745 auto data = getData( src );
2746 return !!data;
2747 }
2748 static bool checkJson( JsonVariantConst ) {
2749 return false;
2750 }
2751};
2752template <>
2753struct Converter<JsonVariantConst> : private detail::VariantAttorney {
2754 static void toJson( JsonVariantConst src, JsonVariant dst ) {
2755 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
2756 }
2757 static JsonVariantConst fromJson( JsonVariantConst src ) {
2758 return JsonVariantConst( getData( src ) );
2759 }
2760 static bool checkJson( JsonVariantConst src ) {
2761 auto data = getData( src );
2762 return !!data;
2763 }
2764};
2765ARDUINOJSON_END_PUBLIC_NAMESPACE
2766ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
2767struct SlotKeySetter {
2768 SlotKeySetter( VariantSlot* instance ) : instance_( instance ) {}
2769 template <typename TStoredString>
2770 void operator()( TStoredString s ) {
2771 if ( !s )
2772 return;
2773 ARDUINOJSON_ASSERT( instance_ != 0 );
2774 instance_->setKey( s );
2775 }
2776 VariantSlot* instance_;
2777};
2778template <typename TAdaptedString>
2779inline bool slotSetKey( VariantSlot* var, TAdaptedString key, MemoryPool* pool ) {
2780 if ( !var )
2781 return false;
2782 return storeString( pool, key, SlotKeySetter( var ) );
2783}
2784inline size_t slotSize( const VariantSlot* var ) {
2785 size_t n = 0;
2786 while ( var ) {
2787 n++;
2788 var = var->next();
2789 }
2790 return n;
2791}
2792inline VariantData* slotData( VariantSlot* slot ) {
2793 return reinterpret_cast<VariantData*>(slot);
2794}
2795ARDUINOJSON_END_PRIVATE_NAMESPACE
2796ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2797class VariantPtr {
2798public:
2799 VariantPtr( detail::MemoryPool* pool, detail::VariantData* data )
2800 : variant_( pool, data ) {}
2801 JsonVariant* operator->() {
2802 return &variant_;
2803 }
2804 JsonVariant& operator*() {
2805 return variant_;
2806 }
2807private:
2808 JsonVariant variant_;
2809};
2810class JsonArrayIterator {
2811 friend class JsonArray;
2812public:
2813 JsonArrayIterator() : slot_( 0 ) {}
2814 explicit JsonArrayIterator( detail::MemoryPool* pool,
2815 detail::VariantSlot* slot )
2816 : pool_( pool ), slot_( slot ) {}
2817 JsonVariant operator*() const {
2818 return JsonVariant( pool_, slot_->data() );
2819 }
2820 VariantPtr operator->() {
2821 return VariantPtr( pool_, slot_->data() );
2822 }
2823 bool operator==( const JsonArrayIterator& other ) const {
2824 return slot_ == other.slot_;
2825 }
2826 bool operator!=( const JsonArrayIterator& other ) const {
2827 return slot_ != other.slot_;
2828 }
2829 JsonArrayIterator& operator++() {
2830 slot_ = slot_->next();
2831 return *this;
2832 }
2833 JsonArrayIterator& operator+=( size_t distance ) {
2834 slot_ = slot_->next( distance );
2835 return *this;
2836 }
2837private:
2838 detail::MemoryPool* pool_;
2839 detail::VariantSlot* slot_;
2840};
2841class VariantConstPtr {
2842public:
2843 VariantConstPtr( const detail::VariantData* data ) : variant_( data ) {}
2844 JsonVariantConst* operator->() {
2845 return &variant_;
2846 }
2847 JsonVariantConst& operator*() {
2848 return variant_;
2849 }
2850private:
2851 JsonVariantConst variant_;
2852};
2853class JsonArrayConstIterator {
2854 friend class JsonArray;
2855public:
2856 JsonArrayConstIterator() : slot_( 0 ) {}
2857 explicit JsonArrayConstIterator( const detail::VariantSlot* slot )
2858 : slot_( slot ) {}
2859 JsonVariantConst operator*() const {
2860 return JsonVariantConst( slot_->data() );
2861 }
2862 VariantConstPtr operator->() {
2863 return VariantConstPtr( slot_->data() );
2864 }
2865 bool operator==( const JsonArrayConstIterator& other ) const {
2866 return slot_ == other.slot_;
2867 }
2868 bool operator!=( const JsonArrayConstIterator& other ) const {
2869 return slot_ != other.slot_;
2870 }
2871 JsonArrayConstIterator& operator++() {
2872 slot_ = slot_->next();
2873 return *this;
2874 }
2875 JsonArrayConstIterator& operator+=( size_t distance ) {
2876 slot_ = slot_->next( distance );
2877 return *this;
2878 }
2879private:
2880 const detail::VariantSlot* slot_;
2881};
2882class JsonObject;
2883class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
2884 friend class JsonArray;
2885 friend class detail::VariantAttorney;
2886public:
2887 typedef JsonArrayConstIterator iterator;
2888 FORCE_INLINE iterator begin() const {
2889 if ( !data_ )
2890 return iterator();
2891 return iterator( data_->head() );
2892 }
2893 FORCE_INLINE iterator end() const {
2894 return iterator();
2895 }
2896 FORCE_INLINE JsonArrayConst() : data_( 0 ) {}
2897 FORCE_INLINE JsonArrayConst( const detail::CollectionData* data )
2898 : data_( data ) {}
2899 FORCE_INLINE bool operator==( JsonArrayConst rhs ) const {
2900 if ( data_ == rhs.data_ )
2901 return true;
2902 if ( !data_ || !rhs.data_ )
2903 return false;
2904 iterator it1 = begin();
2905 iterator it2 = rhs.begin();
2906 for ( ;;) {
2907 bool end1 = it1 == end();
2908 bool end2 = it2 == rhs.end();
2909 if ( end1 && end2 )
2910 return true;
2911 if ( end1 || end2 )
2912 return false;
2913 if ( *it1 != *it2 )
2914 return false;
2915 ++it1;
2916 ++it2;
2917 }
2918 }
2919 FORCE_INLINE JsonVariantConst operator[]( size_t index ) const {
2920 return JsonVariantConst( data_ ? data_->getElement( index ) : 0 );
2921 }
2922 operator JsonVariantConst() const {
2923 return JsonVariantConst( collectionToVariant( data_ ) );
2924 }
2925 FORCE_INLINE bool isNull() const {
2926 return data_ == 0;
2927 }
2928 FORCE_INLINE operator bool() const {
2929 return data_ != 0;
2930 }
2931 FORCE_INLINE size_t memoryUsage() const {
2932 return data_ ? data_->memoryUsage() : 0;
2933 }
2934 FORCE_INLINE size_t nesting() const {
2935 return variantNesting( collectionToVariant( data_ ) );
2936 }
2937 FORCE_INLINE size_t size() const {
2938 return data_ ? data_->size() : 0;
2939 }
2940private:
2941 const detail::VariantData* getData() const {
2942 return collectionToVariant( data_ );
2943 }
2944 const detail::CollectionData* data_;
2945};
2946template <>
2947struct Converter<JsonArrayConst> : private detail::VariantAttorney {
2948 static void toJson( JsonVariantConst src, JsonVariant dst ) {
2949 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
2950 }
2951 static JsonArrayConst fromJson( JsonVariantConst src ) {
2952 auto data = getData( src );
2953 return data ? data->asArray() : 0;
2954 }
2955 static bool checkJson( JsonVariantConst src ) {
2956 auto data = getData( src );
2957 return data && data->isArray();
2958 }
2959};
2960class JsonObject;
2961class JsonArray : public detail::VariantOperators<JsonArray> {
2962 friend class detail::VariantAttorney;
2963public:
2964 typedef JsonArrayIterator iterator;
2965 FORCE_INLINE JsonArray() : data_( 0 ), pool_( 0 ) {}
2966 FORCE_INLINE JsonArray( detail::MemoryPool* pool, detail::CollectionData* data )
2967 : data_( data ), pool_( pool ) {}
2968 operator JsonVariant() {
2969 void* data = data_; // prevent warning cast-align
2970 return JsonVariant( pool_, reinterpret_cast<detail::VariantData*>(data) );
2971 }
2972 operator JsonArrayConst() const {
2973 return JsonArrayConst( data_ );
2974 }
2975 JsonVariant add() const {
2976 if ( !data_ )
2977 return JsonVariant();
2978 return JsonVariant( pool_, data_->addElement( pool_ ) );
2979 }
2980 template <typename T>
2981 FORCE_INLINE bool add( const T& value ) const {
2982 return add().set( value );
2983 }
2984 template <typename T>
2985 FORCE_INLINE bool add( T* value ) const {
2986 return add().set( value );
2987 }
2988 FORCE_INLINE iterator begin() const {
2989 if ( !data_ )
2990 return iterator();
2991 return iterator( pool_, data_->head() );
2992 }
2993 FORCE_INLINE iterator end() const {
2994 return iterator();
2995 }
2996 FORCE_INLINE bool set( JsonArrayConst src ) const {
2997 if ( !data_ || !src.data_ )
2998 return false;
2999 return data_->copyFrom( *src.data_, pool_ );
3000 }
3001 FORCE_INLINE bool operator==( JsonArray rhs ) const {
3002 return JsonArrayConst( data_ ) == JsonArrayConst( rhs.data_ );
3003 }
3004 FORCE_INLINE void remove( iterator it ) const {
3005 if ( !data_ )
3006 return;
3007 data_->removeSlot( it.slot_ );
3008 }
3009 FORCE_INLINE void remove( size_t index ) const {
3010 if ( !data_ )
3011 return;
3012 data_->removeElement( index );
3013 }
3014 void clear() const {
3015 if ( !data_ )
3016 return;
3017 data_->clear();
3018 }
3019 FORCE_INLINE detail::ElementProxy<JsonArray> operator[]( size_t index ) const {
3020 return { *this, index };
3021 }
3022 FORCE_INLINE JsonObject createNestedObject() const;
3023 FORCE_INLINE JsonArray createNestedArray() const {
3024 return add().to<JsonArray>();
3025 }
3026 operator JsonVariantConst() const {
3027 return JsonVariantConst( collectionToVariant( data_ ) );
3028 }
3029 FORCE_INLINE bool isNull() const {
3030 return data_ == 0;
3031 }
3032 FORCE_INLINE operator bool() const {
3033 return data_ != 0;
3034 }
3035 FORCE_INLINE size_t memoryUsage() const {
3036 return data_ ? data_->memoryUsage() : 0;
3037 }
3038 FORCE_INLINE size_t nesting() const {
3039 return variantNesting( collectionToVariant( data_ ) );
3040 }
3041 FORCE_INLINE size_t size() const {
3042 return data_ ? data_->size() : 0;
3043 }
3044private:
3045 detail::MemoryPool* getPool() const {
3046 return pool_;
3047 }
3048 detail::VariantData* getData() const {
3049 return collectionToVariant( data_ );
3050 }
3051 detail::VariantData* getOrCreateData() const {
3052 return collectionToVariant( data_ );
3053 }
3054 detail::CollectionData* data_;
3055 detail::MemoryPool* pool_;
3056};
3057template <>
3058struct Converter<JsonArray> : private detail::VariantAttorney {
3059 static void toJson( JsonVariantConst src, JsonVariant dst ) {
3060 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
3061 }
3062 static JsonArray fromJson( JsonVariant src ) {
3063 auto data = getData( src );
3064 auto pool = getPool( src );
3065 return JsonArray( pool, data != 0 ? data->asArray() : 0 );
3066 }
3067 static detail::InvalidConversion<JsonVariantConst, JsonArray> fromJson(
3068 JsonVariantConst );
3069 static bool checkJson( JsonVariantConst ) {
3070 return false;
3071 }
3072 static bool checkJson( JsonVariant src ) {
3073 auto data = getData( src );
3074 return data && data->isArray();
3075 }
3076};
3077class JsonPair {
3078public:
3079 JsonPair( detail::MemoryPool* pool, detail::VariantSlot* slot ) {
3080 if ( slot ) {
3081 key_ = JsonString( slot->key(), slot->ownsKey() ? JsonString::Copied
3082 : JsonString::Linked );
3083 value_ = JsonVariant( pool, slot->data() );
3084 }
3085 }
3086 JsonString key() const {
3087 return key_;
3088 }
3089 JsonVariant value() const {
3090 return value_;
3091 }
3092private:
3093 JsonString key_;
3094 JsonVariant value_;
3095};
3096class JsonPairConst {
3097public:
3098 JsonPairConst( const detail::VariantSlot* slot ) {
3099 if ( slot ) {
3100 key_ = JsonString( slot->key(), slot->ownsKey() ? JsonString::Copied
3101 : JsonString::Linked );
3102 value_ = JsonVariantConst( slot->data() );
3103 }
3104 }
3105 JsonString key() const {
3106 return key_;
3107 }
3108 JsonVariantConst value() const {
3109 return value_;
3110 }
3111private:
3112 JsonString key_;
3113 JsonVariantConst value_;
3114};
3115class JsonPairPtr {
3116public:
3117 JsonPairPtr( detail::MemoryPool* pool, detail::VariantSlot* slot )
3118 : pair_( pool, slot ) {}
3119 const JsonPair* operator->() const {
3120 return &pair_;
3121 }
3122 const JsonPair& operator*() const {
3123 return pair_;
3124 }
3125private:
3126 JsonPair pair_;
3127};
3128class JsonObjectIterator {
3129 friend class JsonObject;
3130public:
3131 JsonObjectIterator() : slot_( 0 ) {}
3132 explicit JsonObjectIterator( detail::MemoryPool* pool,
3133 detail::VariantSlot* slot )
3134 : pool_( pool ), slot_( slot ) {}
3135 JsonPair operator*() const {
3136 return JsonPair( pool_, slot_ );
3137 }
3138 JsonPairPtr operator->() {
3139 return JsonPairPtr( pool_, slot_ );
3140 }
3141 bool operator==( const JsonObjectIterator& other ) const {
3142 return slot_ == other.slot_;
3143 }
3144 bool operator!=( const JsonObjectIterator& other ) const {
3145 return slot_ != other.slot_;
3146 }
3147 JsonObjectIterator& operator++() {
3148 slot_ = slot_->next();
3149 return *this;
3150 }
3151 JsonObjectIterator& operator+=( size_t distance ) {
3152 slot_ = slot_->next( distance );
3153 return *this;
3154 }
3155private:
3156 detail::MemoryPool* pool_;
3157 detail::VariantSlot* slot_;
3158};
3159class JsonPairConstPtr {
3160public:
3161 JsonPairConstPtr( const detail::VariantSlot* slot ) : pair_( slot ) {}
3162 const JsonPairConst* operator->() const {
3163 return &pair_;
3164 }
3165 const JsonPairConst& operator*() const {
3166 return pair_;
3167 }
3168private:
3169 JsonPairConst pair_;
3170};
3171class JsonObjectConstIterator {
3172 friend class JsonObject;
3173public:
3174 JsonObjectConstIterator() : slot_( 0 ) {}
3175 explicit JsonObjectConstIterator( const detail::VariantSlot* slot )
3176 : slot_( slot ) {}
3177 JsonPairConst operator*() const {
3178 return JsonPairConst( slot_ );
3179 }
3180 JsonPairConstPtr operator->() {
3181 return JsonPairConstPtr( slot_ );
3182 }
3183 bool operator==( const JsonObjectConstIterator& other ) const {
3184 return slot_ == other.slot_;
3185 }
3186 bool operator!=( const JsonObjectConstIterator& other ) const {
3187 return slot_ != other.slot_;
3188 }
3189 JsonObjectConstIterator& operator++() {
3190 slot_ = slot_->next();
3191 return *this;
3192 }
3193 JsonObjectConstIterator& operator+=( size_t distance ) {
3194 slot_ = slot_->next( distance );
3195 return *this;
3196 }
3197private:
3198 const detail::VariantSlot* slot_;
3199};
3200class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
3201 friend class JsonObject;
3202 friend class detail::VariantAttorney;
3203public:
3204 typedef JsonObjectConstIterator iterator;
3205 JsonObjectConst() : data_( 0 ) {}
3206 JsonObjectConst( const detail::CollectionData* data ) : data_( data ) {}
3207 operator JsonVariantConst() const {
3208 return JsonVariantConst( collectionToVariant( data_ ) );
3209 }
3210 FORCE_INLINE bool isNull() const {
3211 return data_ == 0;
3212 }
3213 FORCE_INLINE operator bool() const {
3214 return data_ != 0;
3215 }
3216 FORCE_INLINE size_t memoryUsage() const {
3217 return data_ ? data_->memoryUsage() : 0;
3218 }
3219 FORCE_INLINE size_t nesting() const {
3220 return variantNesting( collectionToVariant( data_ ) );
3221 }
3222 FORCE_INLINE size_t size() const {
3223 return data_ ? data_->size() : 0;
3224 }
3225 FORCE_INLINE iterator begin() const {
3226 if ( !data_ )
3227 return iterator();
3228 return iterator( data_->head() );
3229 }
3230 FORCE_INLINE iterator end() const {
3231 return iterator();
3232 }
3233 template <typename TString>
3234 FORCE_INLINE bool containsKey( const TString& key ) const {
3235 return getMember( detail::adaptString( key ) ) != 0;
3236 }
3237 template <typename TChar>
3238 FORCE_INLINE bool containsKey( TChar* key ) const {
3239 return getMember( detail::adaptString( key ) ) != 0;
3240 }
3241 template <typename TString>
3242 FORCE_INLINE typename detail::enable_if<detail::IsString<TString>::value,
3243 JsonVariantConst>::type
3244 operator[]( const TString& key ) const {
3245 return JsonVariantConst( getMember( detail::adaptString( key ) ) );
3246 }
3247 template <typename TChar>
3248 FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
3249 JsonVariantConst>::type
3250 operator[]( TChar* key ) const {
3251 return JsonVariantConst( getMember( detail::adaptString( key ) ) );
3252 }
3253 FORCE_INLINE bool operator==( JsonObjectConst rhs ) const {
3254 if ( data_ == rhs.data_ )
3255 return true;
3256 if ( !data_ || !rhs.data_ )
3257 return false;
3258 size_t count = 0;
3259 for ( iterator it = begin(); it != end(); ++it ) {
3260 if ( it->value() != rhs[it->key()] )
3261 return false;
3262 count++;
3263 }
3264 return count == rhs.size();
3265 }
3266private:
3267 const detail::VariantData* getData() const {
3268 return collectionToVariant( data_ );
3269 }
3270 template <typename TAdaptedString>
3271 const detail::VariantData* getMember( TAdaptedString key ) const {
3272 if ( !data_ )
3273 return 0;
3274 return data_->getMember( key );
3275 }
3276 const detail::CollectionData* data_;
3277};
3278template <>
3279struct Converter<JsonObjectConst> : private detail::VariantAttorney {
3280 static void toJson( JsonVariantConst src, JsonVariant dst ) {
3281 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
3282 }
3283 static JsonObjectConst fromJson( JsonVariantConst src ) {
3284 auto data = getData( src );
3285 return data != 0 ? data->asObject() : 0;
3286 }
3287 static bool checkJson( JsonVariantConst src ) {
3288 auto data = getData( src );
3289 return data && data->isObject();
3290 }
3291};
3292ARDUINOJSON_END_PUBLIC_NAMESPACE
3293ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
3294template <typename TUpstream, typename TStringRef>
3295class MemberProxy
3296 : public VariantRefBase<MemberProxy<TUpstream, TStringRef>>,
3297 public VariantOperators<MemberProxy<TUpstream, TStringRef>> {
3298 friend class VariantAttorney;
3299public:
3300 FORCE_INLINE MemberProxy( TUpstream upstream, TStringRef key )
3301 : upstream_( upstream ), key_( key ) {}
3302 MemberProxy( const MemberProxy& src )
3303 : upstream_( src.upstream_ ), key_( src.key_ ) {}
3304 FORCE_INLINE MemberProxy& operator=( const MemberProxy& src ) {
3305 this->set( src );
3306 return *this;
3307 }
3308 template <typename T>
3309 FORCE_INLINE MemberProxy& operator=( const T& src ) {
3310 this->set( src );
3311 return *this;
3312 }
3313 template <typename T>
3314 FORCE_INLINE MemberProxy& operator=( T* src ) {
3315 this->set( src );
3316 return *this;
3317 }
3318private:
3319 FORCE_INLINE MemoryPool* getPool() const {
3320 return VariantAttorney::getPool( upstream_ );
3321 }
3322 FORCE_INLINE VariantData* getData() const {
3323 return variantGetMember( VariantAttorney::getData( upstream_ ),
3324 adaptString( key_ ) );
3325 }
3326 FORCE_INLINE VariantData* getOrCreateData() const {
3327 return variantGetOrAddMember( VariantAttorney::getOrCreateData( upstream_ ),
3328 adaptString( key_ ),
3329 VariantAttorney::getPool( upstream_ ) );
3330 }
3331private:
3332 TUpstream upstream_;
3333 TStringRef key_;
3334};
3335ARDUINOJSON_END_PRIVATE_NAMESPACE
3336ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
3337class JsonArray;
3338class JsonObject : public detail::VariantOperators<JsonObject> {
3339 friend class detail::VariantAttorney;
3340public:
3341 typedef JsonObjectIterator iterator;
3342 FORCE_INLINE JsonObject() : data_( 0 ), pool_( 0 ) {}
3343 FORCE_INLINE JsonObject( detail::MemoryPool* buf, detail::CollectionData* data )
3344 : data_( data ), pool_( buf ) {}
3345 operator JsonVariant() const {
3346 void* data = data_; // prevent warning cast-align
3347 return JsonVariant( pool_, reinterpret_cast<detail::VariantData*>(data) );
3348 }
3349 operator JsonObjectConst() const {
3350 return JsonObjectConst( data_ );
3351 }
3352 operator JsonVariantConst() const {
3353 return JsonVariantConst( collectionToVariant( data_ ) );
3354 }
3355 FORCE_INLINE bool isNull() const {
3356 return data_ == 0;
3357 }
3358 FORCE_INLINE operator bool() const {
3359 return data_ != 0;
3360 }
3361 FORCE_INLINE size_t memoryUsage() const {
3362 return data_ ? data_->memoryUsage() : 0;
3363 }
3364 FORCE_INLINE size_t nesting() const {
3365 return variantNesting( collectionToVariant( data_ ) );
3366 }
3367 FORCE_INLINE size_t size() const {
3368 return data_ ? data_->size() : 0;
3369 }
3370 FORCE_INLINE iterator begin() const {
3371 if ( !data_ )
3372 return iterator();
3373 return iterator( pool_, data_->head() );
3374 }
3375 FORCE_INLINE iterator end() const {
3376 return iterator();
3377 }
3378 void clear() const {
3379 if ( !data_ )
3380 return;
3381 data_->clear();
3382 }
3383 FORCE_INLINE bool set( JsonObjectConst src ) {
3384 if ( !data_ || !src.data_ )
3385 return false;
3386 return data_->copyFrom( *src.data_, pool_ );
3387 }
3388 FORCE_INLINE bool operator==( JsonObject rhs ) const {
3389 return JsonObjectConst( data_ ) == JsonObjectConst( rhs.data_ );
3390 }
3391 template <typename TString>
3392 FORCE_INLINE
3393 typename detail::enable_if<detail::IsString<TString>::value,
3394 detail::MemberProxy<JsonObject, TString>>::type
3395 operator[]( const TString& key ) const {
3396 return { *this, key };
3397 }
3398 template <typename TChar>
3399 FORCE_INLINE
3400 typename detail::enable_if<detail::IsString<TChar*>::value,
3401 detail::MemberProxy<JsonObject, TChar*>>::type
3402 operator[]( TChar* key ) const {
3403 return { *this, key };
3404 }
3405 FORCE_INLINE void remove( iterator it ) const {
3406 if ( !data_ )
3407 return;
3408 data_->removeSlot( it.slot_ );
3409 }
3410 template <typename TString>
3411 FORCE_INLINE void remove( const TString& key ) const {
3412 removeMember( detail::adaptString( key ) );
3413 }
3414 template <typename TChar>
3415 FORCE_INLINE void remove( TChar* key ) const {
3416 removeMember( detail::adaptString( key ) );
3417 }
3418 template <typename TString>
3419 FORCE_INLINE
3420 typename detail::enable_if<detail::IsString<TString>::value, bool>::type
3421 containsKey( const TString& key ) const {
3422 return getMember( detail::adaptString( key ) ) != 0;
3423 }
3424 template <typename TChar>
3425 FORCE_INLINE
3426 typename detail::enable_if<detail::IsString<TChar*>::value, bool>::type
3427 containsKey( TChar* key ) const {
3428 return getMember( detail::adaptString( key ) ) != 0;
3429 }
3430 template <typename TString>
3431 FORCE_INLINE JsonArray createNestedArray( const TString& key ) const;
3432 template <typename TChar>
3433 FORCE_INLINE JsonArray createNestedArray( TChar* key ) const;
3434 template <typename TString>
3435 JsonObject createNestedObject( const TString& key ) const {
3436 return operator[]( key ).template to<JsonObject>();
3437 }
3438 template <typename TChar>
3439 JsonObject createNestedObject( TChar* key ) const {
3440 return operator[]( key ).template to<JsonObject>();
3441 }
3442private:
3443 detail::MemoryPool* getPool() const {
3444 return pool_;
3445 }
3446 detail::VariantData* getData() const {
3447 return detail::collectionToVariant( data_ );
3448 }
3449 detail::VariantData* getOrCreateData() const {
3450 return detail::collectionToVariant( data_ );
3451 }
3452 template <typename TAdaptedString>
3453 inline detail::VariantData* getMember( TAdaptedString key ) const {
3454 if ( !data_ )
3455 return 0;
3456 return data_->getMember( key );
3457 }
3458 template <typename TAdaptedString>
3459 void removeMember( TAdaptedString key ) const {
3460 if ( !data_ )
3461 return;
3462 data_->removeMember( key );
3463 }
3464 detail::CollectionData* data_;
3465 detail::MemoryPool* pool_;
3466};
3467template <>
3468struct Converter<JsonObject> : private detail::VariantAttorney {
3469 static void toJson( JsonVariantConst src, JsonVariant dst ) {
3470 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
3471 }
3472 static JsonObject fromJson( JsonVariant src ) {
3473 auto data = getData( src );
3474 auto pool = getPool( src );
3475 return JsonObject( pool, data != 0 ? data->asObject() : 0 );
3476 }
3477 static detail::InvalidConversion<JsonVariantConst, JsonObject> fromJson(
3478 JsonVariantConst );
3479 static bool checkJson( JsonVariantConst ) {
3480 return false;
3481 }
3482 static bool checkJson( JsonVariant src ) {
3483 auto data = getData( src );
3484 return data && data->isObject();
3485 }
3486};
3487class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
3488 friend class detail::VariantAttorney;
3489public:
3490 JsonDocument( const JsonDocument& ) = delete;
3491 JsonDocument& operator=( const JsonDocument& ) = delete;
3492 template <typename T>
3493 T as() {
3494 return getVariant().template as<T>();
3495 }
3496 template <typename T>
3497 T as() const {
3498 return getVariant().template as<T>();
3499 }
3500 void clear() {
3501 pool_.clear();
3502 data_.setNull();
3503 }
3504 template <typename T>
3505 bool is() {
3506 return getVariant().template is<T>();
3507 }
3508 template <typename T>
3509 bool is() const {
3510 return getVariant().template is<T>();
3511 }
3512 bool isNull() const {
3513 return getVariant().isNull();
3514 }
3515 size_t memoryUsage() const {
3516 return pool_.size();
3517 }
3518 bool overflowed() const {
3519 return pool_.overflowed();
3520 }
3521 size_t nesting() const {
3522 return variantNesting( &data_ );
3523 }
3524 size_t capacity() const {
3525 return pool_.capacity();
3526 }
3527 size_t size() const {
3528 return data_.size();
3529 }
3530 bool set( const JsonDocument& src ) {
3531 return to<JsonVariant>().set( src.as<JsonVariantConst>() );
3532 }
3533 template <typename T>
3534 typename detail::enable_if<!detail::is_base_of<JsonDocument, T>::value,
3535 bool>::type
3536 set( const T& src ) {
3537 return to<JsonVariant>().set( src );
3538 }
3539 template <typename T>
3540 typename detail::VariantTo<T>::type to() {
3541 clear();
3542 return getVariant().template to<T>();
3543 }
3544 JsonArray createNestedArray() {
3545 return add().to<JsonArray>();
3546 }
3547 template <typename TChar>
3548 JsonArray createNestedArray( TChar* key ) {
3549 return operator[]( key ).template to<JsonArray>();
3550 }
3551 template <typename TString>
3552 JsonArray createNestedArray( const TString& key ) {
3553 return operator[]( key ).template to<JsonArray>();
3554 }
3555 JsonObject createNestedObject() {
3556 return add().to<JsonObject>();
3557 }
3558 template <typename TChar>
3559 JsonObject createNestedObject( TChar* key ) {
3560 return operator[]( key ).template to<JsonObject>();
3561 }
3562 template <typename TString>
3563 JsonObject createNestedObject( const TString& key ) {
3564 return operator[]( key ).template to<JsonObject>();
3565 }
3566 template <typename TChar>
3567 bool containsKey( TChar* key ) const {
3568 return data_.getMember( detail::adaptString( key ) ) != 0;
3569 }
3570 template <typename TString>
3571 bool containsKey( const TString& key ) const {
3572 return data_.getMember( detail::adaptString( key ) ) != 0;
3573 }
3574 template <typename TString>
3575 FORCE_INLINE typename detail::enable_if<
3576 detail::IsString<TString>::value,
3577 detail::MemberProxy<JsonDocument&, TString>>::type
3578 operator[]( const TString& key ) {
3579 return { *this, key };
3580 }
3581 template <typename TChar>
3582 FORCE_INLINE typename detail::enable_if<
3583 detail::IsString<TChar*>::value,
3584 detail::MemberProxy<JsonDocument&, TChar*>>::type
3585 operator[]( TChar* key ) {
3586 return { *this, key };
3587 }
3588 template <typename TString>
3589 FORCE_INLINE typename detail::enable_if<detail::IsString<TString>::value,
3590 JsonVariantConst>::type
3591 operator[]( const TString& key ) const {
3592 return JsonVariantConst( data_.getMember( detail::adaptString( key ) ) );
3593 }
3594 template <typename TChar>
3595 FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
3596 JsonVariantConst>::type
3597 operator[]( TChar* key ) const {
3598 return JsonVariantConst( data_.getMember( detail::adaptString( key ) ) );
3599 }
3600 FORCE_INLINE detail::ElementProxy<JsonDocument&> operator[]( size_t index ) {
3601 return { *this, index };
3602 }
3603 FORCE_INLINE JsonVariantConst operator[]( size_t index ) const {
3604 return JsonVariantConst( data_.getElement( index ) );
3605 }
3606 FORCE_INLINE JsonVariant add() {
3607 return JsonVariant( &pool_, data_.addElement( &pool_ ) );
3608 }
3609 template <typename TValue>
3610 FORCE_INLINE bool add( const TValue& value ) {
3611 return add().set( value );
3612 }
3613 template <typename TChar>
3614 FORCE_INLINE bool add( TChar* value ) {
3615 return add().set( value );
3616 }
3617 FORCE_INLINE void remove( size_t index ) {
3618 data_.remove( index );
3619 }
3620 template <typename TChar>
3621 FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value>::type
3622 remove( TChar* key ) {
3623 data_.remove( detail::adaptString( key ) );
3624 }
3625 template <typename TString>
3626 FORCE_INLINE
3627 typename detail::enable_if<detail::IsString<TString>::value>::type
3628 remove( const TString& key ) {
3629 data_.remove( detail::adaptString( key ) );
3630 }
3631 FORCE_INLINE operator JsonVariant() {
3632 return getVariant();
3633 }
3634 FORCE_INLINE operator JsonVariantConst() const {
3635 return getVariant();
3636 }
3637protected:
3638 JsonDocument() : pool_( 0, 0 ) {}
3639 JsonDocument( detail::MemoryPool pool ) : pool_( pool ) {}
3640 JsonDocument( char* buf, size_t capa ) : pool_( buf, capa ) {}
3641 ~JsonDocument() {}
3642 void replacePool( detail::MemoryPool pool ) {
3643 pool_ = pool;
3644 }
3645 JsonVariant getVariant() {
3646 return JsonVariant( &pool_, &data_ );
3647 }
3648 JsonVariantConst getVariant() const {
3649 return JsonVariantConst( &data_ );
3650 }
3651 detail::MemoryPool pool_;
3652 detail::VariantData data_;
3653protected:
3654 detail::MemoryPool* getPool() {
3655 return &pool_;
3656 }
3657 detail::VariantData* getData() {
3658 return &data_;
3659 }
3660 const detail::VariantData* getData() const {
3661 return &data_;
3662 }
3663 detail::VariantData* getOrCreateData() {
3664 return &data_;
3665 }
3666};
3667inline void convertToJson( const JsonDocument& src, JsonVariant dst ) {
3668 dst.set( src.as<JsonVariantConst>() );
3669}
3670template <typename TAllocator>
3671class AllocatorOwner {
3672public:
3673 AllocatorOwner() {}
3674 AllocatorOwner( TAllocator a ) : allocator_( a ) {}
3675 void* allocate( size_t size ) {
3676 return allocator_.allocate( size );
3677 }
3678 void deallocate( void* ptr ) {
3679 if ( ptr )
3680 allocator_.deallocate( ptr );
3681 }
3682 void* reallocate( void* ptr, size_t new_size ) {
3683 return allocator_.reallocate( ptr, new_size );
3684 }
3685 TAllocator& allocator() {
3686 return allocator_;
3687 }
3688private:
3689 TAllocator allocator_;
3690};
3691template <typename TAllocator>
3692class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
3693public:
3694 explicit BasicJsonDocument( size_t capa, TAllocator alloc = TAllocator() )
3695 : AllocatorOwner<TAllocator>( alloc ), JsonDocument( allocPool( capa ) ) {}
3696 BasicJsonDocument( const BasicJsonDocument& src )
3697 : AllocatorOwner<TAllocator>( src ), JsonDocument() {
3698 copyAssignFrom( src );
3699 }
3700 BasicJsonDocument( BasicJsonDocument&& src ) : AllocatorOwner<TAllocator>( src ) {
3701 moveAssignFrom( src );
3702 }
3703 BasicJsonDocument( const JsonDocument& src ) {
3704 copyAssignFrom( src );
3705 }
3706 template <typename T>
3707 BasicJsonDocument( const T& src,
3708 typename detail::enable_if<
3709 detail::is_same<T, JsonVariant>::value ||
3710 detail::is_same<T, JsonVariantConst>::value ||
3711 detail::is_same<T, JsonArray>::value ||
3712 detail::is_same<T, JsonArrayConst>::value ||
3713 detail::is_same<T, JsonObject>::value ||
3714 detail::is_same<T, JsonObjectConst>::value>::type* = 0 )
3715 : JsonDocument( allocPool( src.memoryUsage() ) ) {
3716 set( src );
3717 }
3718 BasicJsonDocument( JsonVariant src )
3719 : JsonDocument( allocPool( src.memoryUsage() ) ) {
3720 set( src );
3721 }
3722 ~BasicJsonDocument() {
3723 freePool();
3724 }
3725 BasicJsonDocument& operator=( const BasicJsonDocument& src ) {
3726 copyAssignFrom( src );
3727 return *this;
3728 }
3729 BasicJsonDocument& operator=( BasicJsonDocument&& src ) {
3730 moveAssignFrom( src );
3731 return *this;
3732 }
3733 template <typename T>
3734 BasicJsonDocument& operator=( const T& src ) {
3735 size_t requiredSize = src.memoryUsage();
3736 if ( requiredSize > capacity() )
3737 reallocPool( requiredSize );
3738 set( src );
3739 return *this;
3740 }
3741 void shrinkToFit() {
3742 ptrdiff_t bytes_reclaimed = pool_.squash();
3743 if ( bytes_reclaimed == 0 )
3744 return;
3745 void* old_ptr = pool_.buffer();
3746 void* new_ptr = this->reallocate( old_ptr, pool_.capacity() );
3747 ptrdiff_t ptr_offset =
3748 static_cast<char*>(new_ptr) - static_cast<char*>(old_ptr);
3749 pool_.movePointers( ptr_offset );
3750 data_.movePointers( ptr_offset, ptr_offset - bytes_reclaimed );
3751 }
3752 bool garbageCollect() {
3753 BasicJsonDocument tmp( *this );
3754 if ( !tmp.capacity() )
3755 return false;
3756 moveAssignFrom( tmp );
3757 return true;
3758 }
3759 using AllocatorOwner<TAllocator>::allocator;
3760private:
3761 detail::MemoryPool allocPool( size_t requiredSize ) {
3762 size_t capa = detail::addPadding( requiredSize );
3763 return { reinterpret_cast<char*>(this->allocate( capa )), capa };
3764 }
3765 void reallocPool( size_t requiredSize ) {
3766 size_t capa = detail::addPadding( requiredSize );
3767 if ( capa == pool_.capacity() )
3768 return;
3769 freePool();
3770 replacePool( allocPool( detail::addPadding( requiredSize ) ) );
3771 }
3772 void freePool() {
3773 this->deallocate( getPool()->buffer() );
3774 }
3775 void copyAssignFrom( const JsonDocument& src ) {
3776 reallocPool( src.capacity() );
3777 set( src );
3778 }
3779 void moveAssignFrom( BasicJsonDocument& src ) {
3780 freePool();
3781 data_ = src.data_;
3782 pool_ = src.pool_;
3783 src.data_.setNull();
3784 src.pool_ ={ 0, 0 };
3785 }
3786};
3787struct DefaultAllocator {
3788 void* allocate( size_t size ) {
3789 return malloc( size );
3790 }
3791 void deallocate( void* ptr ) {
3792 free( ptr );
3793 }
3794 void* reallocate( void* ptr, size_t new_size ) {
3795 return realloc( ptr, new_size );
3796 }
3797};
3798typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
3799template <size_t desiredCapacity>
3800class StaticJsonDocument : public JsonDocument {
3801 static const size_t capacity_ =
3802 detail::AddPadding<detail::Max<1, desiredCapacity>::value>::value;
3803public:
3804 StaticJsonDocument() : JsonDocument( buffer_, capacity_ ) {}
3805 StaticJsonDocument( const StaticJsonDocument& src )
3806 : JsonDocument( buffer_, capacity_ ) {
3807 set( src );
3808 }
3809 template <typename T>
3810 StaticJsonDocument(
3811 const T& src,
3812 typename detail::enable_if<
3813 detail::is_convertible<T, JsonVariantConst>::value>::type* = 0 )
3814 : JsonDocument( buffer_, capacity_ ) {
3815 set( src );
3816 }
3817 StaticJsonDocument( JsonVariant src ) : JsonDocument( buffer_, capacity_ ) {
3818 set( src );
3819 }
3820 StaticJsonDocument& operator=( const StaticJsonDocument& src ) {
3821 set( src );
3822 return *this;
3823 }
3824 template <typename T>
3825 StaticJsonDocument& operator=( const T& src ) {
3826 set( src );
3827 return *this;
3828 }
3829 void garbageCollect() {
3830 StaticJsonDocument tmp( *this );
3831 set( tmp );
3832 }
3833private:
3834 char buffer_[capacity_];
3835};
3836inline JsonObject JsonArray::createNestedObject() const {
3837 return add().to<JsonObject>();
3838}
3839ARDUINOJSON_END_PUBLIC_NAMESPACE
3840ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
3841template <typename TDerived>
3842inline JsonArray VariantRefBase<TDerived>::createNestedArray() const {
3843 return add().template to<JsonArray>();
3844}
3845template <typename TDerived>
3846inline JsonObject VariantRefBase<TDerived>::createNestedObject() const {
3847 return add().template to<JsonObject>();
3848}
3849template <typename TDerived>
3850inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
3851 size_t index ) const {
3852 return ElementProxy<TDerived>( derived(), index );
3853}
3854ARDUINOJSON_END_PRIVATE_NAMESPACE
3855ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
3856template <typename T>
3857inline typename detail::enable_if<!detail::is_array<T>::value, bool>::type
3858copyArray( const T& src, JsonVariant dst ) {
3859 return dst.set( src );
3860}
3861template <typename T, size_t N, typename TDestination>
3862inline typename detail::enable_if<
3863 !detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
3864 copyArray( T( &src )[N], const TDestination& dst ) {
3865 return copyArray( src, N, dst );
3866}
3867template <typename T, typename TDestination>
3868inline typename detail::enable_if<
3869 !detail::is_base_of<JsonDocument, TDestination>::value, bool>::type
3870 copyArray( const T* src, size_t len, const TDestination& dst ) {
3871 bool ok = true;
3872 for ( size_t i = 0; i < len; i++ ) {
3873 ok &= copyArray( src[i], dst.add() );
3874 }
3875 return ok;
3876}
3877template <typename TDestination>
3878inline bool copyArray( const char* src, size_t, const TDestination& dst ) {
3879 return dst.set( src );
3880}
3881template <typename T>
3882inline bool copyArray( const T& src, JsonDocument& dst ) {
3883 return copyArray( src, dst.to<JsonArray>() );
3884}
3885template <typename T>
3886inline bool copyArray( const T* src, size_t len, JsonDocument& dst ) {
3887 return copyArray( src, len, dst.to<JsonArray>() );
3888}
3889template <typename T>
3890inline typename detail::enable_if<!detail::is_array<T>::value, size_t>::type
3891copyArray( JsonVariantConst src, T& dst ) {
3892 dst = src.as<T>();
3893 return 1;
3894}
3895template <typename T, size_t N>
3896inline size_t copyArray( JsonArrayConst src, T( &dst )[N] ) {
3897 return copyArray( src, dst, N );
3898}
3899template <typename T>
3900inline size_t copyArray( JsonArrayConst src, T* dst, size_t len ) {
3901 size_t i = 0;
3902 for ( JsonArrayConst::iterator it = src.begin(); it != src.end() && i < len;
3903 ++it )
3904 copyArray( *it, dst[i++] );
3905 return i;
3906}
3907template <size_t N>
3908inline size_t copyArray( JsonVariantConst src, char( &dst )[N] ) {
3909 JsonString s = src;
3910 size_t len = N - 1;
3911 if ( len > s.size() )
3912 len = s.size();
3913 memcpy( dst, s.c_str(), len );
3914 dst[len] = 0;
3915 return 1;
3916}
3917template <typename TSource, typename T>
3918inline typename detail::enable_if<
3919 detail::is_array<T>::value &&
3920 detail::is_base_of<JsonDocument, TSource>::value,
3921 size_t>::type
3922 copyArray( const TSource& src, T& dst ) {
3923 return copyArray( src.template as<JsonArrayConst>(), dst );
3924}
3925ARDUINOJSON_END_PUBLIC_NAMESPACE
3926ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
3927inline VariantSlot* CollectionData::addSlot( MemoryPool* pool ) {
3928 VariantSlot* slot = pool->allocVariant();
3929 if ( !slot )
3930 return 0;
3931 if ( tail_ ) {
3932 ARDUINOJSON_ASSERT( pool->owns( tail_ ) ); // Can't alter a linked array/object
3933 tail_->setNextNotNull( slot );
3934 tail_ = slot;
3935 }
3936 else {
3937 head_ = slot;
3938 tail_ = slot;
3939 }
3940 slot->clear();
3941 return slot;
3942}
3943inline VariantData* CollectionData::addElement( MemoryPool* pool ) {
3944 return slotData( addSlot( pool ) );
3945}
3946template <typename TAdaptedString>
3947inline VariantData* CollectionData::addMember( TAdaptedString key,
3948 MemoryPool* pool ) {
3949 VariantSlot* slot = addSlot( pool );
3950 if ( !slotSetKey( slot, key, pool ) ) {
3951 removeSlot( slot );
3952 return 0;
3953 }
3954 return slot->data();
3955}
3956inline void CollectionData::clear() {
3957 head_ = 0;
3958 tail_ = 0;
3959}
3960template <typename TAdaptedString>
3961inline bool CollectionData::containsKey( const TAdaptedString& key ) const {
3962 return getSlot( key ) != 0;
3963}
3964inline bool CollectionData::copyFrom( const CollectionData& src,
3965 MemoryPool* pool ) {
3966 clear();
3967 for ( VariantSlot* s = src.head_; s; s = s->next() ) {
3968 VariantData* var;
3969 if ( s->key() != 0 ) {
3970 JsonString key( s->key(),
3971 s->ownsKey() ? JsonString::Copied : JsonString::Linked );
3972 var = addMember( adaptString( key ), pool );
3973 }
3974 else {
3975 var = addElement( pool );
3976 }
3977 if ( !var )
3978 return false;
3979 if ( !var->copyFrom( *s->data(), pool ) )
3980 return false;
3981 }
3982 return true;
3983}
3984template <typename TAdaptedString>
3985inline VariantSlot* CollectionData::getSlot( TAdaptedString key ) const {
3986 if ( key.isNull() )
3987 return 0;
3988 VariantSlot* slot = head_;
3989 while ( slot ) {
3990 if ( stringEquals( key, adaptString( slot->key() ) ) )
3991 break;
3992 slot = slot->next();
3993 }
3994 return slot;
3995}
3996inline VariantSlot* CollectionData::getSlot( size_t index ) const {
3997 if ( !head_ )
3998 return 0;
3999 return head_->next( index );
4000}
4001inline VariantSlot* CollectionData::getPreviousSlot( VariantSlot* target ) const {
4002 VariantSlot* current = head_;
4003 while ( current ) {
4004 VariantSlot* next = current->next();
4005 if ( next == target )
4006 return current;
4007 current = next;
4008 }
4009 return 0;
4010}
4011template <typename TAdaptedString>
4012inline VariantData* CollectionData::getMember( TAdaptedString key ) const {
4013 VariantSlot* slot = getSlot( key );
4014 return slot ? slot->data() : 0;
4015}
4016template <typename TAdaptedString>
4017inline VariantData* CollectionData::getOrAddMember( TAdaptedString key,
4018 MemoryPool* pool ) {
4019 if ( key.isNull() )
4020 return 0;
4021 VariantSlot* slot = getSlot( key );
4022 if ( slot )
4023 return slot->data();
4024 return addMember( key, pool );
4025}
4026inline VariantData* CollectionData::getElement( size_t index ) const {
4027 VariantSlot* slot = getSlot( index );
4028 return slot ? slot->data() : 0;
4029}
4030inline VariantData* CollectionData::getOrAddElement( size_t index,
4031 MemoryPool* pool ) {
4032 VariantSlot* slot = head_;
4033 while ( slot && index > 0 ) {
4034 slot = slot->next();
4035 index--;
4036 }
4037 if ( !slot )
4038 index++;
4039 while ( index > 0 ) {
4040 slot = addSlot( pool );
4041 index--;
4042 }
4043 return slotData( slot );
4044}
4045inline void CollectionData::removeSlot( VariantSlot* slot ) {
4046 if ( !slot )
4047 return;
4048 VariantSlot* prev = getPreviousSlot( slot );
4049 VariantSlot* next = slot->next();
4050 if ( prev )
4051 prev->setNext( next );
4052 else
4053 head_ = next;
4054 if ( !next )
4055 tail_ = prev;
4056}
4057inline void CollectionData::removeElement( size_t index ) {
4058 removeSlot( getSlot( index ) );
4059}
4060inline size_t CollectionData::memoryUsage() const {
4061 size_t total = 0;
4062 for ( VariantSlot* s = head_; s; s = s->next() ) {
4063 total += sizeof( VariantSlot ) + s->data()->memoryUsage();
4064 if ( s->ownsKey() )
4065 total += strlen( s->key() ) + 1;
4066 }
4067 return total;
4068}
4069inline size_t CollectionData::size() const {
4070 return slotSize( head_ );
4071}
4072template <typename T>
4073inline void movePointer( T*& p, ptrdiff_t offset ) {
4074 if ( !p )
4075 return;
4076 p = reinterpret_cast<T*>(
4077 reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset));
4078 ARDUINOJSON_ASSERT( isAligned( p ) );
4079}
4080inline void CollectionData::movePointers( ptrdiff_t stringDistance,
4081 ptrdiff_t variantDistance ) {
4082 movePointer( head_, variantDistance );
4083 movePointer( tail_, variantDistance );
4084 for ( VariantSlot* slot = head_; slot; slot = slot->next() )
4085 slot->movePointers( stringDistance, variantDistance );
4086}
4087ARDUINOJSON_END_PRIVATE_NAMESPACE
4088ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
4089template <typename TString>
4090inline JsonArray JsonObject::createNestedArray( const TString& key ) const {
4091 return operator[]( key ).template to<JsonArray>();
4092}
4093template <typename TChar>
4094inline JsonArray JsonObject::createNestedArray( TChar* key ) const {
4095 return operator[]( key ).template to<JsonArray>();
4096}
4097ARDUINOJSON_END_PUBLIC_NAMESPACE
4098ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4099template <typename TDerived>
4100template <typename TString>
4101inline JsonArray VariantRefBase<TDerived>::createNestedArray(
4102 const TString& key ) const {
4103 return operator[]( key ).template to<JsonArray>();
4104}
4105template <typename TDerived>
4106template <typename TChar>
4107inline JsonArray VariantRefBase<TDerived>::createNestedArray( TChar* key ) const {
4108 return operator[]( key ).template to<JsonArray>();
4109}
4110template <typename TDerived>
4111template <typename TString>
4112inline JsonObject VariantRefBase<TDerived>::createNestedObject(
4113 const TString& key ) const {
4114 return operator[]( key ).template to<JsonObject>();
4115}
4116template <typename TDerived>
4117template <typename TChar>
4118inline JsonObject VariantRefBase<TDerived>::createNestedObject(
4119 TChar* key ) const {
4120 return operator[]( key ).template to<JsonObject>();
4121}
4122template <typename TDerived>
4123template <typename TString>
4124inline typename enable_if<IsString<TString>::value, bool>::type
4125VariantRefBase<TDerived>::containsKey( const TString& key ) const {
4126 return variantGetMember( VariantAttorney::getData( derived() ),
4127 adaptString( key ) ) != 0;
4128}
4129template <typename TDerived>
4130template <typename TChar>
4131inline typename enable_if<IsString<TChar*>::value, bool>::type
4132VariantRefBase<TDerived>::containsKey( TChar* key ) const {
4133 return variantGetMember( VariantAttorney::getData( derived() ),
4134 adaptString( key ) ) != 0;
4135}
4136template <typename TDerived>
4137template <typename TString>
4138inline typename enable_if<IsString<TString*>::value,
4139 MemberProxy<TDerived, TString*>>::type
4140 VariantRefBase<TDerived>::operator[]( TString* key ) const {
4141 return MemberProxy<TDerived, TString*>( derived(), key );
4142}
4143template <typename TDerived>
4144template <typename TString>
4145inline typename enable_if<IsString<TString>::value,
4146 MemberProxy<TDerived, TString>>::type
4147 VariantRefBase<TDerived>::operator[]( const TString& key ) const {
4148 return MemberProxy<TDerived, TString>( derived(), key );
4149}
4150class EscapeSequence {
4151public:
4152 static char escapeChar( char c ) {
4153 const char* p = escapeTable( true );
4154 while ( p[0] && p[1] != c ) {
4155 p += 2;
4156 }
4157 return p[0];
4158 }
4159 static char unescapeChar( char c ) {
4160 const char* p = escapeTable( false );
4161 for ( ;;) {
4162 if ( p[0] == '\0' )
4163 return 0;
4164 if ( p[0] == c )
4165 return p[1];
4166 p += 2;
4167 }
4168 }
4169private:
4170 static const char* escapeTable( bool excludeSolidus ) {
4171 return &"//\"\"\\\\b\bf\fn\nr\rt\t"[excludeSolidus ? 2 : 0];
4172 }
4173};
4174template <typename TFloat>
4175struct FloatParts {
4176 uint32_t integral;
4177 uint32_t decimal;
4178 int16_t exponent;
4179 int8_t decimalPlaces;
4180 FloatParts( TFloat value ) {
4181 uint32_t maxDecimalPart = sizeof( TFloat ) >= 8 ? 1000000000 : 1000000;
4182 decimalPlaces = sizeof( TFloat ) >= 8 ? 9 : 6;
4183 exponent = normalize( value );
4184 integral = uint32_t( value );
4185 for ( uint32_t tmp = integral; tmp >= 10; tmp /= 10 ) {
4186 maxDecimalPart /= 10;
4187 decimalPlaces--;
4188 }
4189 TFloat remainder = (value - TFloat( integral )) * TFloat( maxDecimalPart );
4190 decimal = uint32_t( remainder );
4191 remainder = remainder - TFloat( decimal );
4192 decimal += uint32_t( remainder * 2 );
4193 if ( decimal >= maxDecimalPart ) {
4194 decimal = 0;
4195 integral++;
4196 if ( exponent && integral >= 10 ) {
4197 exponent++;
4198 integral = 1;
4199 }
4200 }
4201 while ( decimal % 10 == 0 && decimalPlaces > 0 ) {
4202 decimal /= 10;
4203 decimalPlaces--;
4204 }
4205 }
4206 static int16_t normalize( TFloat& value ) {
4207 typedef FloatTraits<TFloat> traits;
4208 int16_t powersOf10 = 0;
4209 int8_t index = sizeof( TFloat ) == 8 ? 8 : 5;
4210 int bit = 1 << index;
4211 if ( value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD ) {
4212 for ( ; index >= 0; index-- ) {
4213 if ( value >= traits::positiveBinaryPowersOfTen()[index] ) {
4214 value *= traits::negativeBinaryPowersOfTen()[index];
4215 powersOf10 = int16_t( powersOf10 + bit );
4216 }
4217 bit >>= 1;
4218 }
4219 }
4220 if ( value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD ) {
4221 for ( ; index >= 0; index-- ) {
4222 if ( value < traits::negativeBinaryPowersOfTen()[index] * 10 ) {
4223 value *= traits::positiveBinaryPowersOfTen()[index];
4224 powersOf10 = int16_t( powersOf10 - bit );
4225 }
4226 bit >>= 1;
4227 }
4228 }
4229 return powersOf10;
4230 }
4231};
4232template <typename TWriter>
4233class CountingDecorator {
4234public:
4235 explicit CountingDecorator( TWriter& writer ) : writer_( writer ), count_( 0 ) {}
4236 void write( uint8_t c ) {
4237 count_ += writer_.write( c );
4238 }
4239 void write( const uint8_t* s, size_t n ) {
4240 count_ += writer_.write( s, n );
4241 }
4242 size_t count() const {
4243 return count_;
4244 }
4245private:
4246 TWriter writer_;
4247 size_t count_;
4248};
4249template <typename TWriter>
4250class TextFormatter {
4251public:
4252 explicit TextFormatter( TWriter writer ) : writer_( writer ) {}
4253 TextFormatter& operator=( const TextFormatter& ) = delete;
4254 size_t bytesWritten() const {
4255 return writer_.count();
4256 }
4257 void writeBoolean( bool value ) {
4258 if ( value )
4259 writeRaw( "true" );
4260 else
4261 writeRaw( "false" );
4262 }
4263 void writeString( const char* value ) {
4264 ARDUINOJSON_ASSERT( value != NULL );
4265 writeRaw( '\"' );
4266 while ( *value )
4267 writeChar( *value++ );
4268 writeRaw( '\"' );
4269 }
4270 void writeString( const char* value, size_t n ) {
4271 ARDUINOJSON_ASSERT( value != NULL );
4272 writeRaw( '\"' );
4273 while ( n-- )
4274 writeChar( *value++ );
4275 writeRaw( '\"' );
4276 }
4277 void writeChar( char c ) {
4278 char specialChar = EscapeSequence::escapeChar( c );
4279 if ( specialChar ) {
4280 writeRaw( '\\' );
4281 writeRaw( specialChar );
4282 }
4283 else if ( c ) {
4284 writeRaw( c );
4285 }
4286 else {
4287 writeRaw( "\\u0000" );
4288 }
4289 }
4290 template <typename T>
4291 void writeFloat( T value ) {
4292 if ( isnan( value ) )
4293 return writeRaw( ARDUINOJSON_ENABLE_NAN ? "NaN" : "null" );
4294#if ARDUINOJSON_ENABLE_INFINITY
4295 if ( value < 0.0 ) {
4296 writeRaw( '-' );
4297 value = -value;
4298 }
4299 if ( isinf( value ) )
4300 return writeRaw( "Infinity" );
4301#else
4302 if ( isinf( value ) )
4303 return writeRaw( "null" );
4304 if ( value < 0.0 ) {
4305 writeRaw( '-' );
4306 value = -value;
4307 }
4308#endif
4309 FloatParts<T> parts( value );
4310 writeInteger( parts.integral );
4311 if ( parts.decimalPlaces )
4312 writeDecimals( parts.decimal, parts.decimalPlaces );
4313 if ( parts.exponent ) {
4314 writeRaw( 'e' );
4315 writeInteger( parts.exponent );
4316 }
4317 }
4318 template <typename T>
4319 typename enable_if<is_signed<T>::value>::type writeInteger( T value ) {
4320 typedef typename make_unsigned<T>::type unsigned_type;
4321 unsigned_type unsigned_value;
4322 if ( value < 0 ) {
4323 writeRaw( '-' );
4324 unsigned_value = unsigned_type( unsigned_type( ~value ) + 1 );
4325 }
4326 else {
4327 unsigned_value = unsigned_type( value );
4328 }
4329 writeInteger( unsigned_value );
4330 }
4331 template <typename T>
4332 typename enable_if<is_unsigned<T>::value>::type writeInteger( T value ) {
4333 char buffer[22];
4334 char* end = buffer + sizeof( buffer );
4335 char* begin = end;
4336 do {
4337 *--begin = char( value % 10 + '0' );
4338 value = T( value / 10 );
4339 } while ( value );
4340 writeRaw( begin, end );
4341 }
4342 void writeDecimals( uint32_t value, int8_t width ) {
4343 char buffer[16];
4344 char* end = buffer + sizeof( buffer );
4345 char* begin = end;
4346 while ( width-- ) {
4347 *--begin = char( value % 10 + '0' );
4348 value /= 10;
4349 }
4350 *--begin = '.';
4351 writeRaw( begin, end );
4352 }
4353 void writeRaw( const char* s ) {
4354 writer_.write( reinterpret_cast<const uint8_t*>(s), strlen( s ) );
4355 }
4356 void writeRaw( const char* s, size_t n ) {
4357 writer_.write( reinterpret_cast<const uint8_t*>(s), n );
4358 }
4359 void writeRaw( const char* begin, const char* end ) {
4360 writer_.write( reinterpret_cast<const uint8_t*>(begin),
4361 static_cast<size_t>(end - begin) );
4362 }
4363 template <size_t N>
4364 void writeRaw( const char( &s )[N] ) {
4365 writer_.write( reinterpret_cast<const uint8_t*>(s), N - 1 );
4366 }
4367 void writeRaw( char c ) {
4368 writer_.write( static_cast<uint8_t>(c) );
4369 }
4370protected:
4371 CountingDecorator<TWriter> writer_;
4372};
4373class DummyWriter {
4374public:
4375 size_t write( uint8_t ) {
4376 return 1;
4377 }
4378 size_t write( const uint8_t*, size_t n ) {
4379 return n;
4380 }
4381};
4382template <template <typename> class TSerializer>
4383size_t measure( ArduinoJson::JsonVariantConst source ) {
4384 DummyWriter dp;
4385 TSerializer<DummyWriter> serializer( dp );
4386 return variantAccept( VariantAttorney::getData( source ), serializer );
4387}
4388template <typename TDestination, typename Enable = void>
4389class Writer {
4390public:
4391 explicit Writer( TDestination& dest ) : dest_( &dest ) {}
4392 size_t write( uint8_t c ) {
4393 return dest_->write( c );
4394 }
4395 size_t write( const uint8_t* s, size_t n ) {
4396 return dest_->write( s, n );
4397 }
4398private:
4399 TDestination* dest_;
4400};
4401class StaticStringWriter {
4402public:
4403 StaticStringWriter( char* buf, size_t size ) : end( buf + size ), p( buf ) {}
4404 size_t write( uint8_t c ) {
4405 if ( p >= end )
4406 return 0;
4407 *p++ = static_cast<char>(c);
4408 return 1;
4409 }
4410 size_t write( const uint8_t* s, size_t n ) {
4411 char* begin = p;
4412 while ( p < end && n > 0 ) {
4413 *p++ = static_cast<char>(*s++);
4414 n--;
4415 }
4416 return size_t( p - begin );
4417 }
4418private:
4419 char* end;
4420 char* p;
4421};
4422ARDUINOJSON_END_PRIVATE_NAMESPACE
4423#if ARDUINOJSON_ENABLE_STD_STRING
4424ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4425template <class...>
4426using void_t = void;
4427template <class T, typename = void>
4428struct is_std_string : false_type {};
4429template <class T>
4430struct is_std_string<
4431 T, void_t<decltype(T().push_back( 'a' )), decltype(T().append( "" ))>>
4432 : true_type {};
4433template <typename TDestination>
4434class Writer<TDestination,
4435 typename enable_if<is_std_string<TDestination>::value>::type> {
4436public:
4437 Writer( TDestination& str ) : str_( &str ) {}
4438 size_t write( uint8_t c ) {
4439 str_->push_back( static_cast<char>(c) );
4440 return 1;
4441 }
4442 size_t write( const uint8_t* s, size_t n ) {
4443 str_->append( reinterpret_cast<const char*>(s), n );
4444 return n;
4445 }
4446private:
4447 TDestination* str_;
4448};
4449ARDUINOJSON_END_PRIVATE_NAMESPACE
4450#endif
4451#if ARDUINOJSON_ENABLE_ARDUINO_STRING
4452ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4453template <>
4454class Writer<::String, void> {
4455 static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
4456public:
4457 explicit Writer( ::String& str ) : destination_( &str ) {
4458 size_ = 0;
4459 }
4460 ~Writer() {
4461 flush();
4462 }
4463 size_t write( uint8_t c ) {
4464 if ( size_ + 1 >= bufferCapacity )
4465 if ( flush() != 0 )
4466 return 0;
4467 buffer_[size_++] = static_cast<char>(c);
4468 return 1;
4469 }
4470 size_t write( const uint8_t* s, size_t n ) {
4471 for ( size_t i = 0; i < n; i++ ) {
4472 write( s[i] );
4473 }
4474 return n;
4475 }
4476 size_t flush() {
4477 ARDUINOJSON_ASSERT( size_ < bufferCapacity );
4478 buffer_[size_] = 0;
4479 if ( destination_->concat( buffer_ ) )
4480 size_ = 0;
4481 return size_;
4482 }
4483private:
4484 ::String* destination_;
4485 char buffer_[bufferCapacity];
4486 size_t size_;
4487};
4488ARDUINOJSON_END_PRIVATE_NAMESPACE
4489#endif
4490#if ARDUINOJSON_ENABLE_STD_STREAM
4491ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4492template <typename TDestination>
4493class Writer<
4494 TDestination,
4495 typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
4496public:
4497 explicit Writer( std::ostream& os ) : os_( &os ) {}
4498 size_t write( uint8_t c ) {
4499 os_->put( static_cast<char>(c) );
4500 return 1;
4501 }
4502 size_t write( const uint8_t* s, size_t n ) {
4503 os_->write( reinterpret_cast<const char*>(s),
4504 static_cast<std::streamsize>(n) );
4505 return n;
4506 }
4507private:
4508 std::ostream* os_;
4509};
4510ARDUINOJSON_END_PRIVATE_NAMESPACE
4511#endif
4512#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
4513ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4514template <typename TDestination>
4515class Writer<
4516 TDestination,
4517 typename enable_if<is_base_of<::Print, TDestination>::value>::type> {
4518public:
4519 explicit Writer( ::Print& print ) : print_( &print ) {}
4520 size_t write( uint8_t c ) {
4521 return print_->write( c );
4522 }
4523 size_t write( const uint8_t* s, size_t n ) {
4524 return print_->write( s, n );
4525 }
4526private:
4527 ::Print* print_;
4528};
4529ARDUINOJSON_END_PRIVATE_NAMESPACE
4530#endif
4531ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4532template <template <typename> class TSerializer, typename TWriter>
4533size_t doSerialize( ArduinoJson::JsonVariantConst source, TWriter writer ) {
4534 TSerializer<TWriter> serializer( writer );
4535 return variantAccept( VariantAttorney::getData( source ), serializer );
4536}
4537template <template <typename> class TSerializer, typename TDestination>
4538size_t serialize( ArduinoJson::JsonVariantConst source,
4539 TDestination& destination ) {
4540 Writer<TDestination> writer( destination );
4541 return doSerialize<TSerializer>( source, writer );
4542}
4543template <template <typename> class TSerializer>
4544typename enable_if<!TSerializer<StaticStringWriter>::producesText, size_t>::type
4545serialize( ArduinoJson::JsonVariantConst source, void* buffer,
4546 size_t bufferSize ) {
4547 StaticStringWriter writer( reinterpret_cast<char*>(buffer), bufferSize );
4548 return doSerialize<TSerializer>( source, writer );
4549}
4550template <template <typename> class TSerializer>
4551typename enable_if<TSerializer<StaticStringWriter>::producesText, size_t>::type
4552serialize( ArduinoJson::JsonVariantConst source, void* buffer,
4553 size_t bufferSize ) {
4554 StaticStringWriter writer( reinterpret_cast<char*>(buffer), bufferSize );
4555 size_t n = doSerialize<TSerializer>( source, writer );
4556 if ( n < bufferSize )
4557 reinterpret_cast<char*>(buffer)[n] = 0;
4558 return n;
4559}
4560template <template <typename> class TSerializer, typename TChar, size_t N>
4561typename enable_if<IsChar<TChar>::value, size_t>::type serialize(
4562 ArduinoJson::JsonVariantConst source, TChar( &buffer )[N] ) {
4563 return serialize<TSerializer>( source, buffer, N );
4564}
4565template <typename TWriter>
4566class JsonSerializer : public Visitor<size_t> {
4567public:
4568 static const bool producesText = true;
4569 JsonSerializer( TWriter writer ) : formatter_( writer ) {}
4570 FORCE_INLINE size_t visitArray( const CollectionData& array ) {
4571 write( '[' );
4572 const VariantSlot* slot = array.head();
4573 while ( slot != 0 ) {
4574 slot->data()->accept( *this );
4575 slot = slot->next();
4576 if ( slot == 0 )
4577 break;
4578 write( ',' );
4579 }
4580 write( ']' );
4581 return bytesWritten();
4582 }
4583 size_t visitObject( const CollectionData& object ) {
4584 write( '{' );
4585 const VariantSlot* slot = object.head();
4586 while ( slot != 0 ) {
4587 formatter_.writeString( slot->key() );
4588 write( ':' );
4589 slot->data()->accept( *this );
4590 slot = slot->next();
4591 if ( slot == 0 )
4592 break;
4593 write( ',' );
4594 }
4595 write( '}' );
4596 return bytesWritten();
4597 }
4598 size_t visitFloat( JsonFloat value ) {
4599 formatter_.writeFloat( value );
4600 return bytesWritten();
4601 }
4602 size_t visitString( const char* value ) {
4603 formatter_.writeString( value );
4604 return bytesWritten();
4605 }
4606 size_t visitString( const char* value, size_t n ) {
4607 formatter_.writeString( value, n );
4608 return bytesWritten();
4609 }
4610 size_t visitRawJson( const char* data, size_t n ) {
4611 formatter_.writeRaw( data, n );
4612 return bytesWritten();
4613 }
4614 size_t visitSignedInteger( JsonInteger value ) {
4615 formatter_.writeInteger( value );
4616 return bytesWritten();
4617 }
4618 size_t visitUnsignedInteger( JsonUInt value ) {
4619 formatter_.writeInteger( value );
4620 return bytesWritten();
4621 }
4622 size_t visitBoolean( bool value ) {
4623 formatter_.writeBoolean( value );
4624 return bytesWritten();
4625 }
4626 size_t visitNull() {
4627 formatter_.writeRaw( "null" );
4628 return bytesWritten();
4629 }
4630protected:
4631 size_t bytesWritten() const {
4632 return formatter_.bytesWritten();
4633 }
4634 void write( char c ) {
4635 formatter_.writeRaw( c );
4636 }
4637 void write( const char* s ) {
4638 formatter_.writeRaw( s );
4639 }
4640private:
4641 TextFormatter<TWriter> formatter_;
4642};
4643ARDUINOJSON_END_PRIVATE_NAMESPACE
4644ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
4645template <typename TDestination>
4646size_t serializeJson( JsonVariantConst source, TDestination& destination ) {
4647 using namespace detail;
4648 return serialize<JsonSerializer>( source, destination );
4649}
4650inline size_t serializeJson( JsonVariantConst source, void* buffer,
4651 size_t bufferSize ) {
4652 using namespace detail;
4653 return serialize<JsonSerializer>( source, buffer, bufferSize );
4654}
4655inline size_t measureJson( JsonVariantConst source ) {
4656 using namespace detail;
4657 return measure<JsonSerializer>( source );
4658}
4659#if ARDUINOJSON_ENABLE_STD_STREAM
4660template <typename T>
4661inline typename detail::enable_if<
4662 detail::is_convertible<T, JsonVariantConst>::value, std::ostream&>::type
4663 operator<<( std::ostream& os, const T& source ) {
4664 serializeJson( source, os );
4665 return os;
4666}
4667#endif
4668ARDUINOJSON_END_PUBLIC_NAMESPACE
4669#if ARDUINOJSON_ENABLE_STD_STRING
4670#include <string>
4671#endif
4672#if ARDUINOJSON_ENABLE_STRING_VIEW
4673#include <string_view>
4674#endif
4675ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
4676template <typename T, typename Enable>
4677struct Converter {
4678 static void toJson( const T& src, JsonVariant dst ) {
4679 convertToJson( src, dst ); // Error here? See https://arduinojson.org/v6/unsupported-set/
4680 }
4681 static T fromJson( JsonVariantConst src ) {
4682 T result; // Error here? See https://arduinojson.org/v6/non-default-constructible/
4683 convertFromJson( src, result ); // Error here? See https://arduinojson.org/v6/unsupported-as/
4684 return result;
4685 }
4686 static bool checkJson( JsonVariantConst src ) {
4687 T dummy = T();
4688 return canConvertFromJson( src, dummy ); // Error here? See https://arduinojson.org/v6/unsupported-is/
4689 }
4690};
4691template <typename T>
4692struct Converter<
4693 T, typename detail::enable_if<detail::is_integral<T>::value &&
4694 !detail::is_same<bool, T>::value &&
4695 !detail::is_same<char, T>::value>::type>
4696 : private detail::VariantAttorney {
4697 static void toJson( T src, JsonVariant dst ) {
4698 auto data = getData( dst );
4699 ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED( T );
4700 if ( data )
4701 data->setInteger( src );
4702 }
4703 static T fromJson( JsonVariantConst src ) {
4704 ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED( T );
4705 auto data = getData( src );
4706 return data ? data->template asIntegral<T>() : T();
4707 }
4708 static bool checkJson( JsonVariantConst src ) {
4709 auto data = getData( src );
4710 return data && data->template isInteger<T>();
4711 }
4712};
4713template <typename T>
4714struct Converter<T, typename detail::enable_if<detail::is_enum<T>::value>::type>
4715 : private detail::VariantAttorney {
4716 static void toJson( T src, JsonVariant dst ) {
4717 dst.set( static_cast<JsonInteger>(src) );
4718 }
4719 static T fromJson( JsonVariantConst src ) {
4720 auto data = getData( src );
4721 return data ? static_cast<T>(data->template asIntegral<int>()) : T();
4722 }
4723 static bool checkJson( JsonVariantConst src ) {
4724 auto data = getData( src );
4725 return data && data->template isInteger<int>();
4726 }
4727};
4728template <>
4729struct Converter<bool> : private detail::VariantAttorney {
4730 static void toJson( bool src, JsonVariant dst ) {
4731 auto data = getData( dst );
4732 if ( data )
4733 data->setBoolean( src );
4734 }
4735 static bool fromJson( JsonVariantConst src ) {
4736 auto data = getData( src );
4737 return data ? data->asBoolean() : false;
4738 }
4739 static bool checkJson( JsonVariantConst src ) {
4740 auto data = getData( src );
4741 return data && data->isBoolean();
4742 }
4743};
4744template <typename T>
4745struct Converter<
4746 T, typename detail::enable_if<detail::is_floating_point<T>::value>::type>
4747 : private detail::VariantAttorney {
4748 static void toJson( T src, JsonVariant dst ) {
4749 auto data = getData( dst );
4750 if ( data )
4751 data->setFloat( static_cast<JsonFloat>(src) );
4752 }
4753 static T fromJson( JsonVariantConst src ) {
4754 auto data = getData( src );
4755 return data ? data->template asFloat<T>() : 0;
4756 }
4757 static bool checkJson( JsonVariantConst src ) {
4758 auto data = getData( src );
4759 return data && data->isFloat();
4760 }
4761};
4762template <>
4763struct Converter<const char*> : private detail::VariantAttorney {
4764 static void toJson( const char* src, JsonVariant dst ) {
4765 variantSetString( getData( dst ), detail::adaptString( src ), getPool( dst ) );
4766 }
4767 static const char* fromJson( JsonVariantConst src ) {
4768 auto data = getData( src );
4769 return data ? data->asString().c_str() : 0;
4770 }
4771 static bool checkJson( JsonVariantConst src ) {
4772 auto data = getData( src );
4773 return data && data->isString();
4774 }
4775};
4776template <>
4777struct Converter<JsonString> : private detail::VariantAttorney {
4778 static void toJson( JsonString src, JsonVariant dst ) {
4779 variantSetString( getData( dst ), detail::adaptString( src ), getPool( dst ) );
4780 }
4781 static JsonString fromJson( JsonVariantConst src ) {
4782 auto data = getData( src );
4783 return data ? data->asString() : 0;
4784 }
4785 static bool checkJson( JsonVariantConst src ) {
4786 auto data = getData( src );
4787 return data && data->isString();
4788 }
4789};
4790template <typename T>
4791inline typename detail::enable_if<detail::IsString<T>::value, bool>::type
4792convertToJson( const T& src, JsonVariant dst ) {
4793 using namespace detail;
4794 auto data = VariantAttorney::getData( dst );
4795 auto pool = VariantAttorney::getPool( dst );
4796 return variantSetString( data, adaptString( src ), pool );
4797}
4798template <>
4799struct Converter<SerializedValue<const char*>>
4800 : private detail::VariantAttorney {
4801 static void toJson( SerializedValue<const char*> src, JsonVariant dst ) {
4802 auto data = getData( dst );
4803 if ( data )
4804 data->setLinkedRaw( src );
4805 }
4806};
4807template <typename T>
4808struct Converter<
4809 SerializedValue<T>,
4810 typename detail::enable_if<!detail::is_same<const char*, T>::value>::type>
4811 : private detail::VariantAttorney {
4812 static void toJson( SerializedValue<T> src, JsonVariant dst ) {
4813 auto data = getData( dst );
4814 auto pool = getPool( dst );
4815 if ( data )
4816 data->storeOwnedRaw( src, pool );
4817 }
4818};
4819template <>
4820struct Converter<decltype(nullptr)> : private detail::VariantAttorney {
4821 static void toJson( decltype(nullptr), JsonVariant dst ) {
4822 variantSetNull( getData( dst ) );
4823 }
4824 static decltype(nullptr) fromJson( JsonVariantConst ) {
4825 return nullptr;
4826 }
4827 static bool checkJson( JsonVariantConst src ) {
4828 auto data = getData( src );
4829 return data == 0 || data->isNull();
4830 }
4831};
4832#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
4833namespace detail {
4834class MemoryPoolPrint : public Print {
4835public:
4836 MemoryPoolPrint( MemoryPool* pool ) : pool_( pool ), size_( 0 ) {
4837 pool->getFreeZone( &string_, &capacity_ );
4838 }
4839 JsonString str() {
4840 ARDUINOJSON_ASSERT( size_ < capacity_ );
4841 return JsonString( pool_->saveStringFromFreeZone( size_ ), size_,
4842 JsonString::Copied );
4843 }
4844 size_t write( uint8_t c ) {
4845 if ( size_ >= capacity_ )
4846 return 0;
4847 string_[size_++] = char( c );
4848 return 1;
4849 }
4850 size_t write( const uint8_t* buffer, size_t size ) {
4851 if ( size_ + size >= capacity_ ) {
4852 size_ = capacity_; // mark as overflowed
4853 return 0;
4854 }
4855 memcpy( &string_[size_], buffer, size );
4856 size_ += size;
4857 return size;
4858 }
4859 bool overflowed() const {
4860 return size_ >= capacity_;
4861 }
4862private:
4863 MemoryPool* pool_;
4864 size_t size_;
4865 char* string_;
4866 size_t capacity_;
4867};
4868} // namespace detail
4869inline void convertToJson( const ::Printable& src, JsonVariant dst ) {
4870 auto pool = detail::VariantAttorney::getPool( dst );
4871 auto data = detail::VariantAttorney::getData( dst );
4872 if ( !pool || !data )
4873 return;
4874 detail::MemoryPoolPrint print( pool );
4875 src.printTo( print );
4876 if ( print.overflowed() ) {
4877 pool->markAsOverflowed();
4878 data->setNull();
4879 return;
4880 }
4881 data->setString( print.str() );
4882}
4883#endif
4884#if ARDUINOJSON_ENABLE_ARDUINO_STRING
4885inline void convertFromJson( JsonVariantConst src, ::String& dst ) {
4886 JsonString str = src.as<JsonString>();
4887 if ( str )
4888 dst = str.c_str();
4889 else
4890 serializeJson( src, dst );
4891}
4892inline bool canConvertFromJson( JsonVariantConst src, const ::String& ) {
4893 return src.is<JsonString>();
4894}
4895#endif
4896#if ARDUINOJSON_ENABLE_STD_STRING
4897inline void convertFromJson( JsonVariantConst src, std::string& dst ) {
4898 JsonString str = src.as<JsonString>();
4899 if ( str )
4900 dst.assign( str.c_str(), str.size() );
4901 else
4902 serializeJson( src, dst );
4903}
4904inline bool canConvertFromJson( JsonVariantConst src, const std::string& ) {
4905 return src.is<JsonString>();
4906}
4907#endif
4908#if ARDUINOJSON_ENABLE_STRING_VIEW
4909inline void convertFromJson( JsonVariantConst src, std::string_view& dst ) {
4910 JsonString str = src.as<JsonString>();
4911 if ( str ) // the standard doesn't allow passing null to the constructor
4912 dst = std::string_view( str.c_str(), str.size() );
4913}
4914inline bool canConvertFromJson( JsonVariantConst src, const std::string_view& ) {
4915 return src.is<JsonString>();
4916}
4917#endif
4918namespace detail {
4919template <typename T>
4920struct ConverterNeedsWriteableRef {
4921protected: // <- to avoid GCC's "all member functions in class are private"
4922 static int probe( T( *f )(ArduinoJson::JsonVariant) );
4923 static char probe( T( *f )(ArduinoJson::JsonVariantConst) );
4924public:
4925 static const bool value =
4926 sizeof( probe( Converter<T>::fromJson ) ) == sizeof( int );
4927};
4928} // namespace detail
4929ARDUINOJSON_END_PUBLIC_NAMESPACE
4930ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4931class CollectionData;
4932struct ComparerBase : Visitor<CompareResult> {};
4933template <typename T, typename Enable = void>
4934struct Comparer;
4935template <typename T>
4936struct Comparer<T, typename enable_if<IsString<T>::value>::type>
4937 : ComparerBase {
4938 T rhs; // TODO: store adapted string?
4939 explicit Comparer( T value ) : rhs( value ) {}
4940 CompareResult visitString( const char* lhs, size_t n ) {
4941 int i = stringCompare( adaptString( rhs ), adaptString( lhs, n ) );
4942 if ( i < 0 )
4943 return COMPARE_RESULT_GREATER;
4944 else if ( i > 0 )
4945 return COMPARE_RESULT_LESS;
4946 else
4947 return COMPARE_RESULT_EQUAL;
4948 }
4949 CompareResult visitNull() {
4950 if ( adaptString( rhs ).isNull() )
4951 return COMPARE_RESULT_EQUAL;
4952 else
4953 return COMPARE_RESULT_DIFFER;
4954 }
4955};
4956template <typename T>
4957struct Comparer<T, typename enable_if<is_integral<T>::value ||
4958 is_floating_point<T>::value>::type>
4959 : ComparerBase {
4960 T rhs;
4961 explicit Comparer( T value ) : rhs( value ) {}
4962 CompareResult visitFloat( JsonFloat lhs ) {
4963 return arithmeticCompare( lhs, rhs );
4964 }
4965 CompareResult visitSignedInteger( JsonInteger lhs ) {
4966 return arithmeticCompare( lhs, rhs );
4967 }
4968 CompareResult visitUnsignedInteger( JsonUInt lhs ) {
4969 return arithmeticCompare( lhs, rhs );
4970 }
4971 CompareResult visitBoolean( bool lhs ) {
4972 return visitUnsignedInteger( static_cast<JsonUInt>(lhs) );
4973 }
4974};
4975struct NullComparer : ComparerBase {
4976 CompareResult visitNull() {
4977 return COMPARE_RESULT_EQUAL;
4978 }
4979};
4980template <>
4981struct Comparer<decltype(nullptr), void> : NullComparer {
4982 explicit Comparer( decltype(nullptr) ) : NullComparer() {}
4983};
4984struct ArrayComparer : ComparerBase {
4985 const CollectionData* rhs_;
4986 explicit ArrayComparer( const CollectionData& rhs ) : rhs_( &rhs ) {}
4987 CompareResult visitArray( const CollectionData& lhs ) {
4988 if ( JsonArrayConst( &lhs ) == JsonArrayConst( rhs_ ) )
4989 return COMPARE_RESULT_EQUAL;
4990 else
4991 return COMPARE_RESULT_DIFFER;
4992 }
4993};
4994struct ObjectComparer : ComparerBase {
4995 const CollectionData* rhs_;
4996 explicit ObjectComparer( const CollectionData& rhs ) : rhs_( &rhs ) {}
4997 CompareResult visitObject( const CollectionData& lhs ) {
4998 if ( JsonObjectConst( &lhs ) == JsonObjectConst( rhs_ ) )
4999 return COMPARE_RESULT_EQUAL;
5000 else
5001 return COMPARE_RESULT_DIFFER;
5002 }
5003};
5004struct RawComparer : ComparerBase {
5005 const char* rhsData_;
5006 size_t rhsSize_;
5007 explicit RawComparer( const char* rhsData, size_t rhsSize )
5008 : rhsData_( rhsData ), rhsSize_( rhsSize ) {}
5009 CompareResult visitRawJson( const char* lhsData, size_t lhsSize ) {
5010 size_t size = rhsSize_ < lhsSize ? rhsSize_ : lhsSize;
5011 int n = memcmp( lhsData, rhsData_, size );
5012 if ( n < 0 )
5013 return COMPARE_RESULT_LESS;
5014 else if ( n > 0 )
5015 return COMPARE_RESULT_GREATER;
5016 else
5017 return COMPARE_RESULT_EQUAL;
5018 }
5019};
5020struct VariantComparer : ComparerBase {
5021 const VariantData* rhs;
5022 explicit VariantComparer( const VariantData* value ) : rhs( value ) {}
5023 CompareResult visitArray( const CollectionData& lhs ) {
5024 ArrayComparer comparer( lhs );
5025 return accept( comparer );
5026 }
5027 CompareResult visitObject( const CollectionData& lhs ) {
5028 ObjectComparer comparer( lhs );
5029 return accept( comparer );
5030 }
5031 CompareResult visitFloat( JsonFloat lhs ) {
5032 Comparer<JsonFloat> comparer( lhs );
5033 return accept( comparer );
5034 }
5035 CompareResult visitString( const char* lhs, size_t ) {
5036 Comparer<const char*> comparer( lhs );
5037 return accept( comparer );
5038 }
5039 CompareResult visitRawJson( const char* lhsData, size_t lhsSize ) {
5040 RawComparer comparer( lhsData, lhsSize );
5041 return accept( comparer );
5042 }
5043 CompareResult visitSignedInteger( JsonInteger lhs ) {
5044 Comparer<JsonInteger> comparer( lhs );
5045 return accept( comparer );
5046 }
5047 CompareResult visitUnsignedInteger( JsonUInt lhs ) {
5048 Comparer<JsonUInt> comparer( lhs );
5049 return accept( comparer );
5050 }
5051 CompareResult visitBoolean( bool lhs ) {
5052 Comparer<bool> comparer( lhs );
5053 return accept( comparer );
5054 }
5055 CompareResult visitNull() {
5056 NullComparer comparer;
5057 return accept( comparer );
5058 }
5059private:
5060 template <typename TComparer>
5061 CompareResult accept( TComparer& comparer ) {
5062 CompareResult reversedResult = variantAccept( rhs, comparer );
5063 switch ( reversedResult ) {
5064 case COMPARE_RESULT_GREATER:
5065 return COMPARE_RESULT_LESS;
5066 case COMPARE_RESULT_LESS:
5067 return COMPARE_RESULT_GREATER;
5068 default:
5069 return reversedResult;
5070 }
5071 }
5072};
5073template <typename T>
5074struct Comparer<T, typename enable_if<is_convertible<
5075 T, ArduinoJson::JsonVariantConst>::value>::type>
5076 : VariantComparer {
5077 explicit Comparer( const T& value )
5078 : VariantComparer( VariantAttorney::getData( value ) ) {}
5079};
5080template <typename T>
5081CompareResult compare( ArduinoJson::JsonVariantConst lhs, const T& rhs ) {
5082 Comparer<T> comparer( rhs );
5083 return variantAccept( VariantAttorney::getData( lhs ), comparer );
5084}
5085#ifndef isdigit
5086inline bool isdigit( char c ) {
5087 return '0' <= c && c <= '9';
5088}
5089#endif
5090inline bool issign( char c ) {
5091 return '-' == c || c == '+';
5092}
5093template <typename A, typename B>
5094struct choose_largest : conditional<(sizeof( A ) > sizeof( B )), A, B>{};
5095inline bool parseNumber( const char* s, VariantData& result ) {
5096 typedef FloatTraits<JsonFloat> traits;
5097 typedef choose_largest<traits::mantissa_type, JsonUInt>::type mantissa_t;
5098 typedef traits::exponent_type exponent_t;
5099 ARDUINOJSON_ASSERT( s != 0 );
5100 bool is_negative = false;
5101 switch ( *s ) {
5102 case '-':
5103 is_negative = true;
5104 s++;
5105 break;
5106 case '+':
5107 s++;
5108 break;
5109 }
5110#if ARDUINOJSON_ENABLE_NAN
5111 if ( *s == 'n' || *s == 'N' ) {
5112 result.setFloat( traits::nan() );
5113 return true;
5114 }
5115#endif
5116#if ARDUINOJSON_ENABLE_INFINITY
5117 if ( *s == 'i' || *s == 'I' ) {
5118 result.setFloat( is_negative ? -traits::inf() : traits::inf() );
5119 return true;
5120 }
5121#endif
5122 if ( !isdigit( *s ) && *s != '.' )
5123 return false;
5124 mantissa_t mantissa = 0;
5125 exponent_t exponent_offset = 0;
5126 const mantissa_t maxUint = JsonUInt( -1 );
5127 while ( isdigit( *s ) ) {
5128 uint8_t digit = uint8_t( *s - '0' );
5129 if ( mantissa > maxUint / 10 )
5130 break;
5131 mantissa *= 10;
5132 if ( mantissa > maxUint - digit )
5133 break;
5134 mantissa += digit;
5135 s++;
5136 }
5137 if ( *s == '\0' ) {
5138 if ( is_negative ) {
5139 const mantissa_t sintMantissaMax = mantissa_t( 1 )
5140 << (sizeof( JsonInteger ) * 8 - 1);
5141 if ( mantissa <= sintMantissaMax ) {
5142 result.setInteger( JsonInteger( ~mantissa + 1 ) );
5143 return true;
5144 }
5145 }
5146 else {
5147 result.setInteger( JsonUInt( mantissa ) );
5148 return true;
5149 }
5150 }
5151 while ( mantissa > traits::mantissa_max ) {
5152 mantissa /= 10;
5153 exponent_offset++;
5154 }
5155 while ( isdigit( *s ) ) {
5156 exponent_offset++;
5157 s++;
5158 }
5159 if ( *s == '.' ) {
5160 s++;
5161 while ( isdigit( *s ) ) {
5162 if ( mantissa < traits::mantissa_max / 10 ) {
5163 mantissa = mantissa * 10 + uint8_t( *s - '0' );
5164 exponent_offset--;
5165 }
5166 s++;
5167 }
5168 }
5169 int exponent = 0;
5170 if ( *s == 'e' || *s == 'E' ) {
5171 s++;
5172 bool negative_exponent = false;
5173 if ( *s == '-' ) {
5174 negative_exponent = true;
5175 s++;
5176 }
5177 else if ( *s == '+' ) {
5178 s++;
5179 }
5180 while ( isdigit( *s ) ) {
5181 exponent = exponent * 10 + (*s - '0');
5182 if ( exponent + exponent_offset > traits::exponent_max ) {
5183 if ( negative_exponent )
5184 result.setFloat( is_negative ? -0.0f : 0.0f );
5185 else
5186 result.setFloat( is_negative ? -traits::inf() : traits::inf() );
5187 return true;
5188 }
5189 s++;
5190 }
5191 if ( negative_exponent )
5192 exponent = -exponent;
5193 }
5194 exponent += exponent_offset;
5195 if ( *s != '\0' )
5196 return false;
5197 JsonFloat final_result =
5198 make_float( static_cast<JsonFloat>(mantissa), exponent );
5199 result.setFloat( is_negative ? -final_result : final_result );
5200 return true;
5201}
5202template <typename T>
5203inline T parseNumber( const char* s ) {
5204 VariantData value;
5205 parseNumber( s, value );
5206 return Converter<T>::fromJson( JsonVariantConst( &value ) );
5207}
5208template <typename T>
5209inline T VariantData::asIntegral() const {
5210 switch ( type() ) {
5211 case VALUE_IS_BOOLEAN:
5212 return content_.asBoolean;
5213 case VALUE_IS_UNSIGNED_INTEGER:
5214 return convertNumber<T>( content_.asUnsignedInteger );
5215 case VALUE_IS_SIGNED_INTEGER:
5216 return convertNumber<T>( content_.asSignedInteger );
5217 case VALUE_IS_LINKED_STRING:
5218 case VALUE_IS_OWNED_STRING:
5219 return parseNumber<T>( content_.asString.data );
5220 case VALUE_IS_FLOAT:
5221 return convertNumber<T>( content_.asFloat );
5222 default:
5223 return 0;
5224 }
5225}
5226inline bool VariantData::asBoolean() const {
5227 switch ( type() ) {
5228 case VALUE_IS_BOOLEAN:
5229 return content_.asBoolean;
5230 case VALUE_IS_SIGNED_INTEGER:
5231 case VALUE_IS_UNSIGNED_INTEGER:
5232 return content_.asUnsignedInteger != 0;
5233 case VALUE_IS_FLOAT:
5234 return content_.asFloat != 0;
5235 case VALUE_IS_NULL:
5236 return false;
5237 default:
5238 return true;
5239 }
5240}
5241template <typename T>
5242inline T VariantData::asFloat() const {
5243 switch ( type() ) {
5244 case VALUE_IS_BOOLEAN:
5245 return static_cast<T>(content_.asBoolean);
5246 case VALUE_IS_UNSIGNED_INTEGER:
5247 return static_cast<T>(content_.asUnsignedInteger);
5248 case VALUE_IS_SIGNED_INTEGER:
5249 return static_cast<T>(content_.asSignedInteger);
5250 case VALUE_IS_LINKED_STRING:
5251 case VALUE_IS_OWNED_STRING:
5252 return parseNumber<T>( content_.asString.data );
5253 case VALUE_IS_FLOAT:
5254 return static_cast<T>(content_.asFloat);
5255 default:
5256 return 0;
5257 }
5258}
5259inline JsonString VariantData::asString() const {
5260 switch ( type() ) {
5261 case VALUE_IS_LINKED_STRING:
5262 return JsonString( content_.asString.data, content_.asString.size,
5263 JsonString::Linked );
5264 case VALUE_IS_OWNED_STRING:
5265 return JsonString( content_.asString.data, content_.asString.size,
5266 JsonString::Copied );
5267 default:
5268 return JsonString();
5269 }
5270}
5271inline bool VariantData::copyFrom( const VariantData& src, MemoryPool* pool ) {
5272 switch ( src.type() ) {
5273 case VALUE_IS_ARRAY:
5274 return toArray().copyFrom( src.content_.asCollection, pool );
5275 case VALUE_IS_OBJECT:
5276 return toObject().copyFrom( src.content_.asCollection, pool );
5277 case VALUE_IS_OWNED_STRING: {
5278 JsonString value = src.asString();
5279 return setString( adaptString( value ), pool );
5280 }
5281 case VALUE_IS_OWNED_RAW:
5282 return storeOwnedRaw(
5283 serialized( src.content_.asString.data, src.content_.asString.size ),
5284 pool );
5285 default:
5286 setType( src.type() );
5287 content_ = src.content_;
5288 return true;
5289 }
5290}
5291template <typename TDerived>
5292inline JsonVariant VariantRefBase<TDerived>::add() const {
5293 return JsonVariant( getPool(),
5294 variantAddElement( getOrCreateData(), getPool() ) );
5295}
5296template <typename TDerived>
5297template <typename T>
5298inline typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
5299VariantRefBase<TDerived>::as() const {
5300 return Converter<T>::fromJson( getVariant() );
5301}
5302template <typename TDerived>
5303inline JsonVariant VariantRefBase<TDerived>::getVariant() const {
5304 return JsonVariant( getPool(), getData() );
5305}
5306template <typename TDerived>
5307inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant() const {
5308 return JsonVariant( getPool(), getOrCreateData() );
5309}
5310template <typename TDerived>
5311template <typename T>
5312inline typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
5313VariantRefBase<TDerived>::is() const {
5314 return Converter<T>::checkJson( getVariant() );
5315}
5316template <typename TDerived>
5317template <typename T>
5318inline bool VariantRefBase<TDerived>::set( const T& value ) const {
5319 Converter<typename detail::remove_cv<T>::type>::toJson( value,
5320 getOrCreateVariant() );
5321 MemoryPool* pool = getPool();
5322 return pool && !pool->overflowed();
5323}
5324template <typename TDerived>
5325template <typename T>
5326inline bool VariantRefBase<TDerived>::set( T* value ) const {
5327 Converter<T*>::toJson( value, getOrCreateVariant() );
5328 MemoryPool* pool = getPool();
5329 return pool && !pool->overflowed();
5330}
5331template <typename TDerived>
5332template <typename T>
5333inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type
5334VariantRefBase<TDerived>::to() const {
5335 return JsonArray( getPool(), variantToArray( getOrCreateData() ) );
5336}
5337template <typename TDerived>
5338template <typename T>
5339typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type
5340VariantRefBase<TDerived>::to() const {
5341 return JsonObject( getPool(), variantToObject( getOrCreateData() ) );
5342}
5343template <typename TDerived>
5344template <typename T>
5345typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type
5346VariantRefBase<TDerived>::to() const {
5347 auto data = getOrCreateData();
5348 variantSetNull( data );
5349 return JsonVariant( getPool(), data );
5350}
5351template <typename TDerived>
5352inline void convertToJson( const VariantRefBase<TDerived>& src,
5353 JsonVariant dst ) {
5354 dst.set( src.template as<JsonVariantConst>() );
5355}
5356ARDUINOJSON_END_PRIVATE_NAMESPACE
5357#if ARDUINOJSON_ENABLE_STD_STREAM
5358#endif
5359ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
5360class DeserializationError {
5361public:
5362 enum Code {
5363 Ok,
5364 EmptyInput,
5365 IncompleteInput,
5366 InvalidInput,
5367 NoMemory,
5368 TooDeep
5369 };
5370 DeserializationError() {}
5371 DeserializationError( Code c ) : code_( c ) {}
5372 friend bool operator==( const DeserializationError& lhs,
5373 const DeserializationError& rhs ) {
5374 return lhs.code_ == rhs.code_;
5375 }
5376 friend bool operator!=( const DeserializationError& lhs,
5377 const DeserializationError& rhs ) {
5378 return lhs.code_ != rhs.code_;
5379 }
5380 friend bool operator==( const DeserializationError& lhs, Code rhs ) {
5381 return lhs.code_ == rhs;
5382 }
5383 friend bool operator==( Code lhs, const DeserializationError& rhs ) {
5384 return lhs == rhs.code_;
5385 }
5386 friend bool operator!=( const DeserializationError& lhs, Code rhs ) {
5387 return lhs.code_ != rhs;
5388 }
5389 friend bool operator!=( Code lhs, const DeserializationError& rhs ) {
5390 return lhs != rhs.code_;
5391 }
5392 explicit operator bool() const {
5393 return code_ != Ok;
5394 }
5395 Code code() const {
5396 return code_;
5397 }
5398 const char* c_str() const {
5399 static const char* messages[] ={
5400 "Ok", "EmptyInput", "IncompleteInput",
5401 "InvalidInput", "NoMemory", "TooDeep" };
5402 ARDUINOJSON_ASSERT( static_cast<size_t>(code_) <
5403 sizeof( messages ) / sizeof( messages[0] ) );
5404 return messages[code_];
5405 }
5406#if ARDUINOJSON_ENABLE_PROGMEM
5407 const __FlashStringHelper* f_str() const {
5408 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( char, s0, "Ok" );
5409 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( char, s1, "EmptyInput" );
5410 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( char, s2, "IncompleteInput" );
5411 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( char, s3, "InvalidInput" );
5412 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( char, s4, "NoMemory" );
5413 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( char, s5, "TooDeep" );
5414 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( const char*, messages,
5415 { s0, s1, s2, s3, s4, s5 } );
5416 return reinterpret_cast<const __FlashStringHelper*>(
5417 detail::pgm_read( messages + code_ ));
5418 }
5419#endif
5420private:
5421 Code code_;
5422};
5423#if ARDUINOJSON_ENABLE_STD_STREAM
5424inline std::ostream& operator<<( std::ostream& s,
5425 const DeserializationError& e ) {
5426 s << e.c_str();
5427 return s;
5428}
5429inline std::ostream& operator<<( std::ostream& s, DeserializationError::Code c ) {
5430 s << DeserializationError( c ).c_str();
5431 return s;
5432}
5433#endif
5434namespace DeserializationOption {
5435class Filter {
5436public:
5437 explicit Filter( JsonVariantConst v ) : variant_( v ) {}
5438 bool allow() const {
5439 return variant_;
5440 }
5441 bool allowArray() const {
5442 return variant_ == true || variant_.is<JsonArrayConst>();
5443 }
5444 bool allowObject() const {
5445 return variant_ == true || variant_.is<JsonObjectConst>();
5446 }
5447 bool allowValue() const {
5448 return variant_ == true;
5449 }
5450 template <typename TKey>
5451 Filter operator[]( const TKey& key ) const {
5452 if ( variant_ == true ) // "true" means "allow recursively"
5453 return *this;
5454 JsonVariantConst member = variant_[key];
5455 return Filter( member.isNull() ? variant_["*"] : member );
5456 }
5457private:
5458 JsonVariantConst variant_;
5459};
5460} // namespace DeserializationOption
5461namespace detail {
5462struct AllowAllFilter {
5463 bool allow() const {
5464 return true;
5465 }
5466 bool allowArray() const {
5467 return true;
5468 }
5469 bool allowObject() const {
5470 return true;
5471 }
5472 bool allowValue() const {
5473 return true;
5474 }
5475 template <typename TKey>
5476 AllowAllFilter operator[]( const TKey& ) const {
5477 return AllowAllFilter();
5478 }
5479};
5480} // namespace detail
5481namespace DeserializationOption {
5482class NestingLimit {
5483public:
5484 NestingLimit() : value_( ARDUINOJSON_DEFAULT_NESTING_LIMIT ) {}
5485 explicit NestingLimit( uint8_t n ) : value_( n ) {}
5486 NestingLimit decrement() const {
5487 ARDUINOJSON_ASSERT( value_ > 0 );
5488 return NestingLimit( static_cast<uint8_t>(value_ - 1) );
5489 }
5490 bool reached() const {
5491 return value_ == 0;
5492 }
5493private:
5494 uint8_t value_;
5495};
5496} // namespace DeserializationOption
5497ARDUINOJSON_END_PUBLIC_NAMESPACE
5498ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5499template <typename TFilter>
5500struct DeserializationOptions {
5501 TFilter filter;
5502 DeserializationOption::NestingLimit nestingLimit;
5503};
5504template <typename TFilter>
5505inline DeserializationOptions<TFilter> makeDeserializationOptions(
5506 TFilter filter, DeserializationOption::NestingLimit nestingLimit ={} ) {
5507 return { filter, nestingLimit };
5508}
5509template <typename TFilter>
5510inline DeserializationOptions<TFilter> makeDeserializationOptions(
5511 DeserializationOption::NestingLimit nestingLimit, TFilter filter ) {
5512 return { filter, nestingLimit };
5513}
5514inline DeserializationOptions<AllowAllFilter> makeDeserializationOptions(
5515 DeserializationOption::NestingLimit nestingLimit ={} ) {
5516 return { {}, nestingLimit };
5517}
5518template <class T>
5519T&& forward( typename remove_reference<T>::type& t ) noexcept {
5520 return static_cast<T&&>(t);
5521}
5522template <typename TSource, typename Enable = void>
5523struct Reader {
5524public:
5525 Reader( TSource& source ) : source_( &source ) {}
5526 int read() {
5527 return source_->read(); // Error here? See https://arduinojson.org/v6/invalid-input/
5528 }
5529 size_t readBytes( char* buffer, size_t length ) {
5530 return source_->readBytes( buffer, length );
5531 }
5532private:
5533 TSource* source_;
5534};
5535template <typename TSource, typename Enable = void>
5536struct BoundedReader {
5537};
5538template <typename TIterator>
5539class IteratorReader {
5540 TIterator ptr_, end_;
5541public:
5542 explicit IteratorReader( TIterator begin, TIterator end )
5543 : ptr_( begin ), end_( end ) {}
5544 int read() {
5545 if ( ptr_ < end_ )
5546 return static_cast<unsigned char>(*ptr_++);
5547 else
5548 return -1;
5549 }
5550 size_t readBytes( char* buffer, size_t length ) {
5551 size_t i = 0;
5552 while ( i < length && ptr_ < end_ )
5553 buffer[i++] = *ptr_++;
5554 return i;
5555 }
5556};
5557template <typename T>
5558struct void_ {
5559 typedef void type;
5560};
5561template <typename TSource>
5562struct Reader<TSource, typename void_<typename TSource::const_iterator>::type>
5563 : IteratorReader<typename TSource::const_iterator> {
5564 explicit Reader( const TSource& source )
5565 : IteratorReader<typename TSource::const_iterator>( source.begin(),
5566 source.end() ) {}
5567};
5568template <typename T>
5569struct IsCharOrVoid {
5570 static const bool value =
5571 is_same<T, void>::value || is_same<T, char>::value ||
5572 is_same<T, unsigned char>::value || is_same<T, signed char>::value;
5573};
5574template <typename T>
5575struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
5576template <typename TSource>
5577struct Reader<TSource*,
5578 typename enable_if<IsCharOrVoid<TSource>::value>::type> {
5579 const char* ptr_;
5580public:
5581 explicit Reader( const void* ptr )
5582 : ptr_( ptr ? reinterpret_cast<const char*>(ptr) : "" ) {}
5583 int read() {
5584 return static_cast<unsigned char>(*ptr_++);
5585 }
5586 size_t readBytes( char* buffer, size_t length ) {
5587 for ( size_t i = 0; i < length; i++ )
5588 buffer[i] = *ptr_++;
5589 return length;
5590 }
5591};
5592template <typename TSource>
5593struct BoundedReader<TSource*,
5594 typename enable_if<IsCharOrVoid<TSource>::value>::type>
5595 : public IteratorReader<const char*> {
5596public:
5597 explicit BoundedReader( const void* ptr, size_t len )
5598 : IteratorReader<const char*>( reinterpret_cast<const char*>(ptr),
5599 reinterpret_cast<const char*>(ptr) + len ) {}
5600};
5601template <typename TVariant>
5602struct Reader<TVariant, typename enable_if<IsVariant<TVariant>::value>::type>
5603 : Reader<char*, void> {
5604 explicit Reader( const TVariant& x )
5605 : Reader<char*, void>( x.template as<const char*>() ) {}
5606};
5607ARDUINOJSON_END_PRIVATE_NAMESPACE
5608#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
5609ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5610template <typename TSource>
5611struct Reader<TSource,
5612 typename enable_if<is_base_of<Stream, TSource>::value>::type> {
5613public:
5614 explicit Reader( Stream& stream ) : stream_( &stream ) {}
5615 int read() {
5616 char c;
5617 return stream_->readBytes( &c, 1 ) ? static_cast<unsigned char>(c) : -1;
5618 }
5619 size_t readBytes( char* buffer, size_t length ) {
5620 return stream_->readBytes( buffer, length );
5621 }
5622private:
5623 Stream* stream_;
5624};
5625ARDUINOJSON_END_PRIVATE_NAMESPACE
5626#endif
5627#if ARDUINOJSON_ENABLE_ARDUINO_STRING
5628ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5629template <typename TSource>
5630struct Reader<TSource,
5631 typename enable_if<is_base_of<::String, TSource>::value>::type>
5632 : BoundedReader<const char*> {
5633 explicit Reader( const ::String& s )
5634 : BoundedReader<const char*>( s.c_str(), s.length() ) {}
5635};
5636ARDUINOJSON_END_PRIVATE_NAMESPACE
5637#endif
5638#if ARDUINOJSON_ENABLE_PROGMEM
5639ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5640template <>
5641struct Reader<const __FlashStringHelper*, void> {
5642 const char* ptr_;
5643public:
5644 explicit Reader( const __FlashStringHelper* ptr )
5645 : ptr_( reinterpret_cast<const char*>(ptr) ) {}
5646 int read() {
5647 return pgm_read_byte( ptr_++ );
5648 }
5649 size_t readBytes( char* buffer, size_t length ) {
5650 memcpy_P( buffer, ptr_, length );
5651 ptr_ += length;
5652 return length;
5653 }
5654};
5655template <>
5656struct BoundedReader<const __FlashStringHelper*, void> {
5657 const char* ptr_;
5658 const char* end_;
5659public:
5660 explicit BoundedReader( const __FlashStringHelper* ptr, size_t size )
5661 : ptr_( reinterpret_cast<const char*>(ptr) ), end_( ptr_ + size ) {}
5662 int read() {
5663 if ( ptr_ < end_ )
5664 return pgm_read_byte( ptr_++ );
5665 else
5666 return -1;
5667 }
5668 size_t readBytes( char* buffer, size_t length ) {
5669 size_t available = static_cast<size_t>(end_ - ptr_);
5670 if ( available < length )
5671 length = available;
5672 memcpy_P( buffer, ptr_, length );
5673 ptr_ += length;
5674 return length;
5675 }
5676};
5677ARDUINOJSON_END_PRIVATE_NAMESPACE
5678#endif
5679#if ARDUINOJSON_ENABLE_STD_STREAM
5680#include <istream>
5681ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5682template <typename TSource>
5683struct Reader<TSource, typename enable_if<
5684 is_base_of<std::istream, TSource>::value>::type> {
5685public:
5686 explicit Reader( std::istream& stream ) : stream_( &stream ) {}
5687 int read() {
5688 return stream_->get();
5689 }
5690 size_t readBytes( char* buffer, size_t length ) {
5691 stream_->read( buffer, static_cast<std::streamsize>(length) );
5692 return static_cast<size_t>(stream_->gcount());
5693 }
5694private:
5695 std::istream* stream_;
5696};
5697ARDUINOJSON_END_PRIVATE_NAMESPACE
5698#endif
5699ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5700template <typename TInput>
5701Reader<typename remove_reference<TInput>::type> makeReader( TInput&& input ) {
5702 return Reader<typename remove_reference<TInput>::type>{
5703 detail::forward<TInput>( input )};
5704}
5705template <typename TChar>
5706BoundedReader<TChar*> makeReader( TChar* input, size_t inputSize ) {
5707 return BoundedReader<TChar*>{input, inputSize};
5708}
5709class StringCopier {
5710public:
5711 StringCopier( MemoryPool* pool ) : pool_( pool ) {}
5712 void startString() {
5713 pool_->getFreeZone( &ptr_, &capacity_ );
5714 size_ = 0;
5715 if ( capacity_ == 0 )
5716 pool_->markAsOverflowed();
5717 }
5718 JsonString save() {
5719 ARDUINOJSON_ASSERT( ptr_ );
5720 ARDUINOJSON_ASSERT( size_ < capacity_ ); // needs room for the terminator
5721 return JsonString( pool_->saveStringFromFreeZone( size_ ), size_,
5722 JsonString::Copied );
5723 }
5724 void append( const char* s ) {
5725 while ( *s )
5726 append( *s++ );
5727 }
5728 void append( const char* s, size_t n ) {
5729 while ( n-- > 0 )
5730 append( *s++ );
5731 }
5732 void append( char c ) {
5733 if ( size_ + 1 < capacity_ )
5734 ptr_[size_++] = c;
5735 else
5736 pool_->markAsOverflowed();
5737 }
5738 bool isValid() const {
5739 return !pool_->overflowed();
5740 }
5741 size_t size() const {
5742 return size_;
5743 }
5744 JsonString str() const {
5745 ARDUINOJSON_ASSERT( ptr_ );
5746 ARDUINOJSON_ASSERT( size_ < capacity_ );
5747 ptr_[size_] = 0;
5748 return JsonString( ptr_, size_, JsonString::Copied );
5749 }
5750private:
5751 MemoryPool* pool_;
5752 char* ptr_;
5753 size_t size_, capacity_;
5754};
5755class StringMover {
5756public:
5757 StringMover( char* ptr ) : writePtr_( ptr ) {}
5758 void startString() {
5759 startPtr_ = writePtr_;
5760 }
5761 FORCE_INLINE JsonString save() {
5762 JsonString s = str();
5763 writePtr_++;
5764 return s;
5765 }
5766 void append( char c ) {
5767 *writePtr_++ = c;
5768 }
5769 bool isValid() const {
5770 return true;
5771 }
5772 JsonString str() const {
5773 writePtr_[0] = 0; // terminator
5774 return JsonString( startPtr_, size(), JsonString::Linked );
5775 }
5776 size_t size() const {
5777 return size_t( writePtr_ - startPtr_ );
5778 }
5779private:
5780 char* writePtr_;
5781 char* startPtr_;
5782};
5783template <typename TInput>
5784StringCopier makeStringStorage( TInput&, MemoryPool* pool ) {
5785 ARDUINOJSON_ASSERT( pool != 0 );
5786 return StringCopier( pool );
5787}
5788template <typename TChar>
5789StringMover makeStringStorage(
5790 TChar* input, MemoryPool*,
5791 typename enable_if<!is_const<TChar>::value>::type* = 0 ) {
5792 return StringMover( reinterpret_cast<char*>(input) );
5793}
5794template <typename...>
5795struct first_or_void {
5796 using type = void;
5797};
5798template <typename T, typename... Rest>
5799struct first_or_void<T, Rest...> {
5800 using type = T;
5801};
5802template <template <typename, typename> class TDeserializer, typename TReader,
5803 typename TWriter>
5804TDeserializer<TReader, TWriter> makeDeserializer( MemoryPool* pool,
5805 TReader reader,
5806 TWriter writer ) {
5807 ARDUINOJSON_ASSERT( pool != 0 );
5808 return TDeserializer<TReader, TWriter>( pool, reader, writer );
5809}
5810template <template <typename, typename> class TDeserializer, typename TStream,
5811 typename... Args,
5812 typename = typename enable_if< // issue #1897
5813 !is_integral<typename first_or_void<Args...>::type>::value>::type>
5814DeserializationError deserialize( JsonDocument& doc, TStream&& input,
5815 Args... args ) {
5816 auto reader = makeReader( detail::forward<TStream>( input ) );
5817 auto data = VariantAttorney::getData( doc );
5818 auto pool = VariantAttorney::getPool( doc );
5819 auto options = makeDeserializationOptions( args... );
5820 doc.clear();
5821 return makeDeserializer<TDeserializer>( pool, reader,
5822 makeStringStorage( input, pool ) )
5823 .parse( *data, options.filter, options.nestingLimit );
5824}
5825template <template <typename, typename> class TDeserializer, typename TChar,
5826 typename Size, typename... Args,
5827 typename = typename enable_if<is_integral<Size>::value>::type>
5828DeserializationError deserialize( JsonDocument& doc, TChar* input,
5829 Size inputSize, Args... args ) {
5830 auto reader = makeReader( input, size_t( inputSize ) );
5831 auto data = VariantAttorney::getData( doc );
5832 auto pool = VariantAttorney::getPool( doc );
5833 auto options = makeDeserializationOptions( args... );
5834 doc.clear();
5835 return makeDeserializer<TDeserializer>( pool, reader,
5836 makeStringStorage( input, pool ) )
5837 .parse( *data, options.filter, options.nestingLimit );
5838}
5839template <typename TReader>
5840class Latch {
5841public:
5842 Latch( TReader reader ) : reader_( reader ), loaded_( false ) {
5843#if ARDUINOJSON_DEBUG
5844 ended_ = false;
5845#endif
5846 }
5847 void clear() {
5848 loaded_ = false;
5849 }
5850 int last() const {
5851 return current_;
5852 }
5853 FORCE_INLINE char current() {
5854 if ( !loaded_ ) {
5855 load();
5856 }
5857 return current_;
5858 }
5859private:
5860 void load() {
5861 ARDUINOJSON_ASSERT( !ended_ );
5862 int c = reader_.read();
5863#if ARDUINOJSON_DEBUG
5864 if ( c <= 0 )
5865 ended_ = true;
5866#endif
5867 current_ = static_cast<char>(c > 0 ? c : 0);
5868 loaded_ = true;
5869 }
5870 TReader reader_;
5871 char current_; // NOLINT(clang-analyzer-optin.cplusplus.UninitializedObject)
5872 bool loaded_;
5873#if ARDUINOJSON_DEBUG
5874 bool ended_;
5875#endif
5876};
5877ARDUINOJSON_END_PRIVATE_NAMESPACE
5878#if defined(__GNUC__)
5879# if __GNUC__ >= 7
5880# pragma GCC diagnostic push
5881# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
5882# endif
5883#endif
5884ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5885namespace Utf16 {
5886inline bool isHighSurrogate( uint16_t codeunit ) {
5887 return codeunit >= 0xD800 && codeunit < 0xDC00;
5888}
5889inline bool isLowSurrogate( uint16_t codeunit ) {
5890 return codeunit >= 0xDC00 && codeunit < 0xE000;
5891}
5892class Codepoint {
5893public:
5894 Codepoint() : highSurrogate_( 0 ), codepoint_( 0 ) {}
5895 bool append( uint16_t codeunit ) {
5896 if ( isHighSurrogate( codeunit ) ) {
5897 highSurrogate_ = codeunit & 0x3FF;
5898 return false;
5899 }
5900 if ( isLowSurrogate( codeunit ) ) {
5901 codepoint_ =
5902 uint32_t( 0x10000 + ((highSurrogate_ << 10) | (codeunit & 0x3FF)) );
5903 return true;
5904 }
5905 codepoint_ = codeunit;
5906 return true;
5907 }
5908 uint32_t value() const {
5909 return codepoint_;
5910 }
5911private:
5912 uint16_t highSurrogate_;
5913 uint32_t codepoint_;
5914};
5915} // namespace Utf16
5916ARDUINOJSON_END_PRIVATE_NAMESPACE
5917#if defined(__GNUC__)
5918# if __GNUC__ >= 8
5919# pragma GCC diagnostic pop
5920# endif
5921#endif
5922ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5923namespace Utf8 {
5924template <typename TStringBuilder>
5925inline void encodeCodepoint( uint32_t codepoint32, TStringBuilder& str ) {
5926 if ( codepoint32 < 0x80 ) {
5927 str.append( char( codepoint32 ) );
5928 }
5929 else {
5930 char buf[5];
5931 char* p = buf;
5932 *(p++) = 0;
5933 *(p++) = char( (codepoint32 | 0x80) & 0xBF );
5934 uint16_t codepoint16 = uint16_t( codepoint32 >> 6 );
5935 if ( codepoint16 < 0x20 ) { // 0x800
5936 *(p++) = char( codepoint16 | 0xC0 );
5937 }
5938 else {
5939 *(p++) = char( (codepoint16 | 0x80) & 0xBF );
5940 codepoint16 = uint16_t( codepoint16 >> 6 );
5941 if ( codepoint16 < 0x10 ) { // 0x10000
5942 *(p++) = char( codepoint16 | 0xE0 );
5943 }
5944 else {
5945 *(p++) = char( (codepoint16 | 0x80) & 0xBF );
5946 codepoint16 = uint16_t( codepoint16 >> 6 );
5947 *(p++) = char( codepoint16 | 0xF0 );
5948 }
5949 }
5950 while ( *(--p) ) {
5951 str.append( *p );
5952 }
5953 }
5954}
5955} // namespace Utf8
5956template <typename TReader, typename TStringStorage>
5957class JsonDeserializer {
5958public:
5959 JsonDeserializer( MemoryPool* pool, TReader reader,
5960 TStringStorage stringStorage )
5961 : stringStorage_( stringStorage ),
5962 foundSomething_( false ),
5963 latch_( reader ),
5964 pool_( pool ) {}
5965 template <typename TFilter>
5966 DeserializationError parse( VariantData& variant, TFilter filter,
5967 DeserializationOption::NestingLimit nestingLimit ) {
5968 DeserializationError::Code err;
5969 err = parseVariant( variant, filter, nestingLimit );
5970 if ( !err && latch_.last() != 0 && !variant.isEnclosed() ) {
5971 return DeserializationError::InvalidInput;
5972 }
5973 return err;
5974 }
5975private:
5976 char current() {
5977 return latch_.current();
5978 }
5979 void move() {
5980 latch_.clear();
5981 }
5982 bool eat( char charToSkip ) {
5983 if ( current() != charToSkip )
5984 return false;
5985 move();
5986 return true;
5987 }
5988 template <typename TFilter>
5989 DeserializationError::Code parseVariant(
5990 VariantData& variant, TFilter filter,
5991 DeserializationOption::NestingLimit nestingLimit ) {
5992 DeserializationError::Code err;
5993 err = skipSpacesAndComments();
5994 if ( err )
5995 return err;
5996 switch ( current() ) {
5997 case '[':
5998 if ( filter.allowArray() )
5999 return parseArray( variant.toArray(), filter, nestingLimit );
6000 else
6001 return skipArray( nestingLimit );
6002 case '{':
6003 if ( filter.allowObject() )
6004 return parseObject( variant.toObject(), filter, nestingLimit );
6005 else
6006 return skipObject( nestingLimit );
6007 case '\"':
6008 case '\'':
6009 if ( filter.allowValue() )
6010 return parseStringValue( variant );
6011 else
6012 return skipQuotedString();
6013 case 't':
6014 if ( filter.allowValue() )
6015 variant.setBoolean( true );
6016 return skipKeyword( "true" );
6017 case 'f':
6018 if ( filter.allowValue() )
6019 variant.setBoolean( false );
6020 return skipKeyword( "false" );
6021 case 'n':
6022 return skipKeyword( "null" );
6023 default:
6024 if ( filter.allowValue() )
6025 return parseNumericValue( variant );
6026 else
6027 return skipNumericValue();
6028 }
6029 }
6030 DeserializationError::Code skipVariant(
6031 DeserializationOption::NestingLimit nestingLimit ) {
6032 DeserializationError::Code err;
6033 err = skipSpacesAndComments();
6034 if ( err )
6035 return err;
6036 switch ( current() ) {
6037 case '[':
6038 return skipArray( nestingLimit );
6039 case '{':
6040 return skipObject( nestingLimit );
6041 case '\"':
6042 case '\'':
6043 return skipQuotedString();
6044 case 't':
6045 return skipKeyword( "true" );
6046 case 'f':
6047 return skipKeyword( "false" );
6048 case 'n':
6049 return skipKeyword( "null" );
6050 default:
6051 return skipNumericValue();
6052 }
6053 }
6054 template <typename TFilter>
6055 DeserializationError::Code parseArray(
6056 CollectionData& array, TFilter filter,
6057 DeserializationOption::NestingLimit nestingLimit ) {
6058 DeserializationError::Code err;
6059 if ( nestingLimit.reached() )
6060 return DeserializationError::TooDeep;
6061 ARDUINOJSON_ASSERT( current() == '[' );
6062 move();
6063 err = skipSpacesAndComments();
6064 if ( err )
6065 return err;
6066 if ( eat( ']' ) )
6067 return DeserializationError::Ok;
6068 TFilter memberFilter = filter[0UL];
6069 for ( ;;) {
6070 if ( memberFilter.allow() ) {
6071 VariantData* value = array.addElement( pool_ );
6072 if ( !value )
6073 return DeserializationError::NoMemory;
6074 err = parseVariant( *value, memberFilter, nestingLimit.decrement() );
6075 if ( err )
6076 return err;
6077 }
6078 else {
6079 err = skipVariant( nestingLimit.decrement() );
6080 if ( err )
6081 return err;
6082 }
6083 err = skipSpacesAndComments();
6084 if ( err )
6085 return err;
6086 if ( eat( ']' ) )
6087 return DeserializationError::Ok;
6088 if ( !eat( ',' ) )
6089 return DeserializationError::InvalidInput;
6090 }
6091 }
6092 DeserializationError::Code skipArray(
6093 DeserializationOption::NestingLimit nestingLimit ) {
6094 DeserializationError::Code err;
6095 if ( nestingLimit.reached() )
6096 return DeserializationError::TooDeep;
6097 ARDUINOJSON_ASSERT( current() == '[' );
6098 move();
6099 for ( ;;) {
6100 err = skipVariant( nestingLimit.decrement() );
6101 if ( err )
6102 return err;
6103 err = skipSpacesAndComments();
6104 if ( err )
6105 return err;
6106 if ( eat( ']' ) )
6107 return DeserializationError::Ok;
6108 if ( !eat( ',' ) )
6109 return DeserializationError::InvalidInput;
6110 }
6111 }
6112 template <typename TFilter>
6113 DeserializationError::Code parseObject(
6114 CollectionData& object, TFilter filter,
6115 DeserializationOption::NestingLimit nestingLimit ) {
6116 DeserializationError::Code err;
6117 if ( nestingLimit.reached() )
6118 return DeserializationError::TooDeep;
6119 ARDUINOJSON_ASSERT( current() == '{' );
6120 move();
6121 err = skipSpacesAndComments();
6122 if ( err )
6123 return err;
6124 if ( eat( '}' ) )
6125 return DeserializationError::Ok;
6126 for ( ;;) {
6127 err = parseKey();
6128 if ( err )
6129 return err;
6130 err = skipSpacesAndComments();
6131 if ( err )
6132 return err;
6133 if ( !eat( ':' ) )
6134 return DeserializationError::InvalidInput;
6135 JsonString key = stringStorage_.str();
6136 TFilter memberFilter = filter[key.c_str()];
6137 if ( memberFilter.allow() ) {
6138 VariantData* variant = object.getMember( adaptString( key.c_str() ) );
6139 if ( !variant ) {
6140 key = stringStorage_.save();
6141 VariantSlot* slot = object.addSlot( pool_ );
6142 if ( !slot )
6143 return DeserializationError::NoMemory;
6144 slot->setKey( key );
6145 variant = slot->data();
6146 }
6147 err = parseVariant( *variant, memberFilter, nestingLimit.decrement() );
6148 if ( err )
6149 return err;
6150 }
6151 else {
6152 err = skipVariant( nestingLimit.decrement() );
6153 if ( err )
6154 return err;
6155 }
6156 err = skipSpacesAndComments();
6157 if ( err )
6158 return err;
6159 if ( eat( '}' ) )
6160 return DeserializationError::Ok;
6161 if ( !eat( ',' ) )
6162 return DeserializationError::InvalidInput;
6163 err = skipSpacesAndComments();
6164 if ( err )
6165 return err;
6166 }
6167 }
6168 DeserializationError::Code skipObject(
6169 DeserializationOption::NestingLimit nestingLimit ) {
6170 DeserializationError::Code err;
6171 if ( nestingLimit.reached() )
6172 return DeserializationError::TooDeep;
6173 ARDUINOJSON_ASSERT( current() == '{' );
6174 move();
6175 err = skipSpacesAndComments();
6176 if ( err )
6177 return err;
6178 if ( eat( '}' ) )
6179 return DeserializationError::Ok;
6180 for ( ;;) {
6181 err = skipKey();
6182 if ( err )
6183 return err;
6184 err = skipSpacesAndComments();
6185 if ( err )
6186 return err;
6187 if ( !eat( ':' ) )
6188 return DeserializationError::InvalidInput;
6189 err = skipVariant( nestingLimit.decrement() );
6190 if ( err )
6191 return err;
6192 err = skipSpacesAndComments();
6193 if ( err )
6194 return err;
6195 if ( eat( '}' ) )
6196 return DeserializationError::Ok;
6197 if ( !eat( ',' ) )
6198 return DeserializationError::InvalidInput;
6199 err = skipSpacesAndComments();
6200 if ( err )
6201 return err;
6202 }
6203 }
6204 DeserializationError::Code parseKey() {
6205 stringStorage_.startString();
6206 if ( isQuote( current() ) ) {
6207 return parseQuotedString();
6208 }
6209 else {
6210 return parseNonQuotedString();
6211 }
6212 }
6213 DeserializationError::Code parseStringValue( VariantData& variant ) {
6214 DeserializationError::Code err;
6215 stringStorage_.startString();
6216 err = parseQuotedString();
6217 if ( err )
6218 return err;
6219 variant.setString( stringStorage_.save() );
6220 return DeserializationError::Ok;
6221 }
6222 DeserializationError::Code parseQuotedString() {
6223#if ARDUINOJSON_DECODE_UNICODE
6224 Utf16::Codepoint codepoint;
6225 DeserializationError::Code err;
6226#endif
6227 const char stopChar = current();
6228 move();
6229 for ( ;;) {
6230 char c = current();
6231 move();
6232 if ( c == stopChar )
6233 break;
6234 if ( c == '\0' )
6235 return DeserializationError::IncompleteInput;
6236 if ( c == '\\' ) {
6237 c = current();
6238 if ( c == '\0' )
6239 return DeserializationError::IncompleteInput;
6240 if ( c == 'u' ) {
6241#if ARDUINOJSON_DECODE_UNICODE
6242 move();
6243 uint16_t codeunit;
6244 err = parseHex4( codeunit );
6245 if ( err )
6246 return err;
6247 if ( codepoint.append( codeunit ) )
6248 Utf8::encodeCodepoint( codepoint.value(), stringStorage_ );
6249#else
6250 stringStorage_.append( '\\' );
6251#endif
6252 continue;
6253 }
6254 c = EscapeSequence::unescapeChar( c );
6255 if ( c == '\0' )
6256 return DeserializationError::InvalidInput;
6257 move();
6258 }
6259 stringStorage_.append( c );
6260 }
6261 if ( !stringStorage_.isValid() )
6262 return DeserializationError::NoMemory;
6263 return DeserializationError::Ok;
6264 }
6265 DeserializationError::Code parseNonQuotedString() {
6266 char c = current();
6267 ARDUINOJSON_ASSERT( c );
6268 if ( canBeInNonQuotedString( c ) ) { // no quotes
6269 do {
6270 move();
6271 stringStorage_.append( c );
6272 c = current();
6273 } while ( canBeInNonQuotedString( c ) );
6274 }
6275 else {
6276 return DeserializationError::InvalidInput;
6277 }
6278 if ( !stringStorage_.isValid() )
6279 return DeserializationError::NoMemory;
6280 return DeserializationError::Ok;
6281 }
6282 DeserializationError::Code skipKey() {
6283 if ( isQuote( current() ) ) {
6284 return skipQuotedString();
6285 }
6286 else {
6287 return skipNonQuotedString();
6288 }
6289 }
6290 DeserializationError::Code skipQuotedString() {
6291 const char stopChar = current();
6292 move();
6293 for ( ;;) {
6294 char c = current();
6295 move();
6296 if ( c == stopChar )
6297 break;
6298 if ( c == '\0' )
6299 return DeserializationError::IncompleteInput;
6300 if ( c == '\\' ) {
6301 if ( current() != '\0' )
6302 move();
6303 }
6304 }
6305 return DeserializationError::Ok;
6306 }
6307 DeserializationError::Code skipNonQuotedString() {
6308 char c = current();
6309 while ( canBeInNonQuotedString( c ) ) {
6310 move();
6311 c = current();
6312 }
6313 return DeserializationError::Ok;
6314 }
6315 DeserializationError::Code parseNumericValue( VariantData& result ) {
6316 uint8_t n = 0;
6317 char c = current();
6318 while ( canBeInNumber( c ) && n < 63 ) {
6319 move();
6320 buffer_[n++] = c;
6321 c = current();
6322 }
6323 buffer_[n] = 0;
6324 if ( !parseNumber( buffer_, result ) )
6325 return DeserializationError::InvalidInput;
6326 return DeserializationError::Ok;
6327 }
6328 DeserializationError::Code skipNumericValue() {
6329 char c = current();
6330 while ( canBeInNumber( c ) ) {
6331 move();
6332 c = current();
6333 }
6334 return DeserializationError::Ok;
6335 }
6336 DeserializationError::Code parseHex4( uint16_t& result ) {
6337 result = 0;
6338 for ( uint8_t i = 0; i < 4; ++i ) {
6339 char digit = current();
6340 if ( !digit )
6341 return DeserializationError::IncompleteInput;
6342 uint8_t value = decodeHex( digit );
6343 if ( value > 0x0F )
6344 return DeserializationError::InvalidInput;
6345 result = uint16_t( (result << 4) | value );
6346 move();
6347 }
6348 return DeserializationError::Ok;
6349 }
6350 static inline bool isBetween( char c, char min, char max ) {
6351 return min <= c && c <= max;
6352 }
6353 static inline bool canBeInNumber( char c ) {
6354 return isBetween( c, '0', '9' ) || c == '+' || c == '-' || c == '.' ||
6355#if ARDUINOJSON_ENABLE_NAN || ARDUINOJSON_ENABLE_INFINITY
6356 isBetween( c, 'A', 'Z' ) || isBetween( c, 'a', 'z' );
6357#else
6358 c == 'e' || c == 'E';
6359#endif
6360 }
6361 static inline bool canBeInNonQuotedString( char c ) {
6362 return isBetween( c, '0', '9' ) || isBetween( c, '_', 'z' ) ||
6363 isBetween( c, 'A', 'Z' );
6364 }
6365 static inline bool isQuote( char c ) {
6366 return c == '\'' || c == '\"';
6367 }
6368 static inline uint8_t decodeHex( char c ) {
6369 if ( c < 'A' )
6370 return uint8_t( c - '0' );
6371 c = char( c & ~0x20 ); // uppercase
6372 return uint8_t( c - 'A' + 10 );
6373 }
6374 DeserializationError::Code skipSpacesAndComments() {
6375 for ( ;;) {
6376 switch ( current() ) {
6377 case '\0':
6378 return foundSomething_ ? DeserializationError::IncompleteInput
6379 : DeserializationError::EmptyInput;
6380 case ' ':
6381 case '\t':
6382 case '\r':
6383 case '\n':
6384 move();
6385 continue;
6386#if ARDUINOJSON_ENABLE_COMMENTS
6387 case '/':
6388 move(); // skip '/'
6389 switch ( current() ) {
6390 case '*': {
6391 move(); // skip '*'
6392 bool wasStar = false;
6393 for ( ;;) {
6394 char c = current();
6395 if ( c == '\0' )
6396 return DeserializationError::IncompleteInput;
6397 if ( c == '/' && wasStar ) {
6398 move();
6399 break;
6400 }
6401 wasStar = c == '*';
6402 move();
6403 }
6404 break;
6405 }
6406 case '/':
6407 for ( ;;) {
6408 move();
6409 char c = current();
6410 if ( c == '\0' )
6411 return DeserializationError::IncompleteInput;
6412 if ( c == '\n' )
6413 break;
6414 }
6415 break;
6416 default:
6417 return DeserializationError::InvalidInput;
6418 }
6419 break;
6420#endif
6421 default:
6422 foundSomething_ = true;
6423 return DeserializationError::Ok;
6424 }
6425 }
6426 }
6427 DeserializationError::Code skipKeyword( const char* s ) {
6428 while ( *s ) {
6429 char c = current();
6430 if ( c == '\0' )
6431 return DeserializationError::IncompleteInput;
6432 if ( *s != c )
6433 return DeserializationError::InvalidInput;
6434 ++s;
6435 move();
6436 }
6437 return DeserializationError::Ok;
6438 }
6439 TStringStorage stringStorage_;
6440 bool foundSomething_;
6441 Latch<TReader> latch_;
6442 MemoryPool* pool_;
6443 char buffer_[64]; // using a member instead of a local variable because it
6444};
6445ARDUINOJSON_END_PRIVATE_NAMESPACE
6446ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
6447template <typename... Args>
6448DeserializationError deserializeJson( JsonDocument& doc, Args&&... args ) {
6449 using namespace detail;
6450 return deserialize<JsonDeserializer>( doc, detail::forward<Args>( args )... );
6451}
6452template <typename TChar, typename... Args>
6453DeserializationError deserializeJson( JsonDocument& doc, TChar* input,
6454 Args&&... args ) {
6455 using namespace detail;
6456 return deserialize<JsonDeserializer>( doc, input,
6457 detail::forward<Args>( args )... );
6458}
6459ARDUINOJSON_END_PUBLIC_NAMESPACE
6460ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
6461template <typename TWriter>
6462class PrettyJsonSerializer : public JsonSerializer<TWriter> {
6463 typedef JsonSerializer<TWriter> base;
6464public:
6465 PrettyJsonSerializer( TWriter writer ) : base( writer ), nesting_( 0 ) {}
6466 size_t visitArray( const CollectionData& array ) {
6467 const VariantSlot* slot = array.head();
6468 if ( slot ) {
6469 base::write( "[\r\n" );
6470 nesting_++;
6471 while ( slot != 0 ) {
6472 indent();
6473 slot->data()->accept( *this );
6474 slot = slot->next();
6475 base::write( slot ? ",\r\n" : "\r\n" );
6476 }
6477 nesting_--;
6478 indent();
6479 base::write( "]" );
6480 }
6481 else {
6482 base::write( "[]" );
6483 }
6484 return this->bytesWritten();
6485 }
6486 size_t visitObject( const CollectionData& object ) {
6487 const VariantSlot* slot = object.head();
6488 if ( slot ) {
6489 base::write( "{\r\n" );
6490 nesting_++;
6491 while ( slot != 0 ) {
6492 indent();
6493 base::visitString( slot->key() );
6494 base::write( ": " );
6495 slot->data()->accept( *this );
6496 slot = slot->next();
6497 base::write( slot ? ",\r\n" : "\r\n" );
6498 }
6499 nesting_--;
6500 indent();
6501 base::write( "}" );
6502 }
6503 else {
6504 base::write( "{}" );
6505 }
6506 return this->bytesWritten();
6507 }
6508private:
6509 void indent() {
6510 for ( uint8_t i = 0; i < nesting_; i++ )
6511 base::write( ARDUINOJSON_TAB );
6512 }
6513 uint8_t nesting_;
6514};
6515ARDUINOJSON_END_PRIVATE_NAMESPACE
6516ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
6517template <typename TDestination>
6518size_t serializeJsonPretty( JsonVariantConst source, TDestination& destination ) {
6519 using namespace ArduinoJson::detail;
6520 return serialize<PrettyJsonSerializer>( source, destination );
6521}
6522inline size_t serializeJsonPretty( JsonVariantConst source, void* buffer,
6523 size_t bufferSize ) {
6524 using namespace ArduinoJson::detail;
6525 return serialize<PrettyJsonSerializer>( source, buffer, bufferSize );
6526}
6527inline size_t measureJsonPretty( JsonVariantConst source ) {
6528 using namespace ArduinoJson::detail;
6529 return measure<PrettyJsonSerializer>( source );
6530}
6531ARDUINOJSON_END_PUBLIC_NAMESPACE
6532ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
6533#if ARDUINOJSON_LITTLE_ENDIAN
6534inline void swapBytes( uint8_t& a, uint8_t& b ) {
6535 uint8_t t( a );
6536 a = b;
6537 b = t;
6538}
6539inline void fixEndianess( uint8_t* p, integral_constant<size_t, 8> ) {
6540 swapBytes( p[0], p[7] );
6541 swapBytes( p[1], p[6] );
6542 swapBytes( p[2], p[5] );
6543 swapBytes( p[3], p[4] );
6544}
6545inline void fixEndianess( uint8_t* p, integral_constant<size_t, 4> ) {
6546 swapBytes( p[0], p[3] );
6547 swapBytes( p[1], p[2] );
6548}
6549inline void fixEndianess( uint8_t* p, integral_constant<size_t, 2> ) {
6550 swapBytes( p[0], p[1] );
6551}
6552inline void fixEndianess( uint8_t*, integral_constant<size_t, 1> ) {}
6553template <typename T>
6554inline void fixEndianess( T& value ) {
6555 fixEndianess( reinterpret_cast<uint8_t*>(&value),
6556 integral_constant<size_t, sizeof( T )>() );
6557}
6558#else
6559template <typename T>
6560inline void fixEndianess( T& ) {}
6561#endif
6562inline void doubleToFloat( const uint8_t d[8], uint8_t f[4] ) {
6563 f[0] = uint8_t( (d[0] & 0xC0) | (d[0] << 3 & 0x3f) | (d[1] >> 5) );
6564 f[1] = uint8_t( (d[1] << 3) | (d[2] >> 5) );
6565 f[2] = uint8_t( (d[2] << 3) | (d[3] >> 5) );
6566 f[3] = uint8_t( (d[3] << 3) | (d[4] >> 5) );
6567}
6568template <typename TReader, typename TStringStorage>
6569class MsgPackDeserializer {
6570public:
6571 MsgPackDeserializer( MemoryPool* pool, TReader reader,
6572 TStringStorage stringStorage )
6573 : pool_( pool ),
6574 reader_( reader ),
6575 stringStorage_( stringStorage ),
6576 foundSomething_( false ) {}
6577 template <typename TFilter>
6578 DeserializationError parse( VariantData& variant, TFilter filter,
6579 DeserializationOption::NestingLimit nestingLimit ) {
6580 DeserializationError::Code err;
6581 err = parseVariant( &variant, filter, nestingLimit );
6582 return foundSomething_ ? err : DeserializationError::EmptyInput;
6583 }
6584private:
6585 template <typename TFilter>
6586 DeserializationError::Code parseVariant(
6587 VariantData* variant, TFilter filter,
6588 DeserializationOption::NestingLimit nestingLimit ) {
6589 DeserializationError::Code err;
6590 uint8_t code = 0; // TODO: why do we need to initialize this variable?
6591 err = readByte( code );
6592 if ( err )
6593 return err;
6594 foundSomething_ = true;
6595 bool allowValue = filter.allowValue();
6596 if ( allowValue ) {
6597 ARDUINOJSON_ASSERT( variant != 0 );
6598 }
6599 switch ( code ) {
6600 case 0xc0:
6601 return DeserializationError::Ok;
6602 case 0xc1:
6603 return DeserializationError::InvalidInput;
6604 case 0xc2:
6605 if ( allowValue )
6606 variant->setBoolean( false );
6607 return DeserializationError::Ok;
6608 case 0xc3:
6609 if ( allowValue )
6610 variant->setBoolean( true );
6611 return DeserializationError::Ok;
6612 case 0xc4: // bin 8 (not supported)
6613 return skipString<uint8_t>();
6614 case 0xc5: // bin 16 (not supported)
6615 return skipString<uint16_t>();
6616 case 0xc6: // bin 32 (not supported)
6617 return skipString<uint32_t>();
6618 case 0xc7: // ext 8 (not supported)
6619 return skipExt<uint8_t>();
6620 case 0xc8: // ext 16 (not supported)
6621 return skipExt<uint16_t>();
6622 case 0xc9: // ext 32 (not supported)
6623 return skipExt<uint32_t>();
6624 case 0xca:
6625 if ( allowValue )
6626 return readFloat<float>( variant );
6627 else
6628 return skipBytes( 4 );
6629 case 0xcb:
6630 if ( allowValue )
6631 return readDouble<double>( variant );
6632 else
6633 return skipBytes( 8 );
6634 case 0xcc:
6635 if ( allowValue )
6636 return readInteger<uint8_t>( variant );
6637 else
6638 return skipBytes( 1 );
6639 case 0xcd:
6640 if ( allowValue )
6641 return readInteger<uint16_t>( variant );
6642 else
6643 return skipBytes( 2 );
6644 case 0xce:
6645 if ( allowValue )
6646 return readInteger<uint32_t>( variant );
6647 else
6648 return skipBytes( 4 );
6649 case 0xcf:
6650#if ARDUINOJSON_USE_LONG_LONG
6651 if ( allowValue )
6652 return readInteger<uint64_t>( variant );
6653 else
6654 return skipBytes( 8 );
6655#else
6656 return skipBytes( 8 ); // not supported
6657#endif
6658 case 0xd0:
6659 if ( allowValue )
6660 return readInteger<int8_t>( variant );
6661 else
6662 return skipBytes( 1 );
6663 case 0xd1:
6664 if ( allowValue )
6665 return readInteger<int16_t>( variant );
6666 else
6667 return skipBytes( 2 );
6668 case 0xd2:
6669 if ( allowValue )
6670 return readInteger<int32_t>( variant );
6671 else
6672 return skipBytes( 4 );
6673 case 0xd3:
6674#if ARDUINOJSON_USE_LONG_LONG
6675 if ( allowValue )
6676 return readInteger<int64_t>( variant );
6677 else
6678 return skipBytes( 8 ); // not supported
6679#else
6680 return skipBytes( 8 );
6681#endif
6682 case 0xd4: // fixext 1 (not supported)
6683 return skipBytes( 2 );
6684 case 0xd5: // fixext 2 (not supported)
6685 return skipBytes( 3 );
6686 case 0xd6: // fixext 4 (not supported)
6687 return skipBytes( 5 );
6688 case 0xd7: // fixext 8 (not supported)
6689 return skipBytes( 9 );
6690 case 0xd8: // fixext 16 (not supported)
6691 return skipBytes( 17 );
6692 case 0xd9:
6693 if ( allowValue )
6694 return readString<uint8_t>( variant );
6695 else
6696 return skipString<uint8_t>();
6697 case 0xda:
6698 if ( allowValue )
6699 return readString<uint16_t>( variant );
6700 else
6701 return skipString<uint16_t>();
6702 case 0xdb:
6703 if ( allowValue )
6704 return readString<uint32_t>( variant );
6705 else
6706 return skipString<uint32_t>();
6707 case 0xdc:
6708 return readArray<uint16_t>( variant, filter, nestingLimit );
6709 case 0xdd:
6710 return readArray<uint32_t>( variant, filter, nestingLimit );
6711 case 0xde:
6712 return readObject<uint16_t>( variant, filter, nestingLimit );
6713 case 0xdf:
6714 return readObject<uint32_t>( variant, filter, nestingLimit );
6715 }
6716 switch ( code & 0xf0 ) {
6717 case 0x80:
6718 return readObject( variant, code & 0x0F, filter, nestingLimit );
6719 case 0x90:
6720 return readArray( variant, code & 0x0F, filter, nestingLimit );
6721 }
6722 if ( (code & 0xe0) == 0xa0 ) {
6723 if ( allowValue )
6724 return readString( variant, code & 0x1f );
6725 else
6726 return skipBytes( code & 0x1f );
6727 }
6728 if ( allowValue )
6729 variant->setInteger( static_cast<int8_t>(code) );
6730 return DeserializationError::Ok;
6731 }
6732 DeserializationError::Code readByte( uint8_t& value ) {
6733 int c = reader_.read();
6734 if ( c < 0 )
6735 return DeserializationError::IncompleteInput;
6736 value = static_cast<uint8_t>(c);
6737 return DeserializationError::Ok;
6738 }
6739 DeserializationError::Code readBytes( uint8_t* p, size_t n ) {
6740 if ( reader_.readBytes( reinterpret_cast<char*>(p), n ) == n )
6741 return DeserializationError::Ok;
6742 return DeserializationError::IncompleteInput;
6743 }
6744 template <typename T>
6745 DeserializationError::Code readBytes( T& value ) {
6746 return readBytes( reinterpret_cast<uint8_t*>(&value), sizeof( value ) );
6747 }
6748 DeserializationError::Code skipBytes( size_t n ) {
6749 for ( ; n; --n ) {
6750 if ( reader_.read() < 0 )
6751 return DeserializationError::IncompleteInput;
6752 }
6753 return DeserializationError::Ok;
6754 }
6755 template <typename T>
6756 DeserializationError::Code readInteger( T& value ) {
6757 DeserializationError::Code err;
6758 err = readBytes( value );
6759 if ( err )
6760 return err;
6761 fixEndianess( value );
6762 return DeserializationError::Ok;
6763 }
6764 template <typename T>
6765 DeserializationError::Code readInteger( VariantData* variant ) {
6766 DeserializationError::Code err;
6767 T value;
6768 err = readInteger( value );
6769 if ( err )
6770 return err;
6771 variant->setInteger( value );
6772 return DeserializationError::Ok;
6773 }
6774 template <typename T>
6775 typename enable_if<sizeof( T ) == 4, DeserializationError::Code>::type
6776 readFloat( VariantData* variant ) {
6777 DeserializationError::Code err;
6778 T value;
6779 err = readBytes( value );
6780 if ( err )
6781 return err;
6782 fixEndianess( value );
6783 variant->setFloat( value );
6784 return DeserializationError::Ok;
6785 }
6786 template <typename T>
6787 typename enable_if<sizeof( T ) == 8, DeserializationError::Code>::type
6788 readDouble( VariantData* variant ) {
6789 DeserializationError::Code err;
6790 T value;
6791 err = readBytes( value );
6792 if ( err )
6793 return err;
6794 fixEndianess( value );
6795 variant->setFloat( value );
6796 return DeserializationError::Ok;
6797 }
6798 template <typename T>
6799 typename enable_if<sizeof( T ) == 4, DeserializationError::Code>::type
6800 readDouble( VariantData* variant ) {
6801 DeserializationError::Code err;
6802 uint8_t i[8]; // input is 8 bytes
6803 T value; // output is 4 bytes
6804 uint8_t* o = reinterpret_cast<uint8_t*>(&value);
6805 err = readBytes( i, 8 );
6806 if ( err )
6807 return err;
6808 doubleToFloat( i, o );
6809 fixEndianess( value );
6810 variant->setFloat( value );
6811 return DeserializationError::Ok;
6812 }
6813 template <typename T>
6814 DeserializationError::Code readString( VariantData* variant ) {
6815 DeserializationError::Code err;
6816 T size;
6817 err = readInteger( size );
6818 if ( err )
6819 return err;
6820 return readString( variant, size );
6821 }
6822 template <typename T>
6823 DeserializationError::Code readString() {
6824 DeserializationError::Code err;
6825 T size;
6826 err = readInteger( size );
6827 if ( err )
6828 return err;
6829 return readString( size );
6830 }
6831 template <typename T>
6832 DeserializationError::Code skipString() {
6833 DeserializationError::Code err;
6834 T size;
6835 err = readInteger( size );
6836 if ( err )
6837 return err;
6838 return skipBytes( size );
6839 }
6840 DeserializationError::Code readString( VariantData* variant, size_t n ) {
6841 DeserializationError::Code err;
6842 err = readString( n );
6843 if ( err )
6844 return err;
6845 variant->setString( stringStorage_.save() );
6846 return DeserializationError::Ok;
6847 }
6848 DeserializationError::Code readString( size_t n ) {
6849 DeserializationError::Code err;
6850 stringStorage_.startString();
6851 for ( ; n; --n ) {
6852 uint8_t c;
6853 err = readBytes( c );
6854 if ( err )
6855 return err;
6856 stringStorage_.append( static_cast<char>(c) );
6857 }
6858 if ( !stringStorage_.isValid() )
6859 return DeserializationError::NoMemory;
6860 return DeserializationError::Ok;
6861 }
6862 template <typename TSize, typename TFilter>
6863 DeserializationError::Code readArray(
6864 VariantData* variant, TFilter filter,
6865 DeserializationOption::NestingLimit nestingLimit ) {
6866 DeserializationError::Code err;
6867 TSize size;
6868 err = readInteger( size );
6869 if ( err )
6870 return err;
6871 return readArray( variant, size, filter, nestingLimit );
6872 }
6873 template <typename TFilter>
6874 DeserializationError::Code readArray(
6875 VariantData* variant, size_t n, TFilter filter,
6876 DeserializationOption::NestingLimit nestingLimit ) {
6877 DeserializationError::Code err;
6878 if ( nestingLimit.reached() )
6879 return DeserializationError::TooDeep;
6880 bool allowArray = filter.allowArray();
6881 CollectionData* array;
6882 if ( allowArray ) {
6883 ARDUINOJSON_ASSERT( variant != 0 );
6884 array = &variant->toArray();
6885 }
6886 else {
6887 array = 0;
6888 }
6889 TFilter memberFilter = filter[0U];
6890 for ( ; n; --n ) {
6891 VariantData* value;
6892 if ( memberFilter.allow() ) {
6893 ARDUINOJSON_ASSERT( array != 0 );
6894 value = array->addElement( pool_ );
6895 if ( !value )
6896 return DeserializationError::NoMemory;
6897 }
6898 else {
6899 value = 0;
6900 }
6901 err = parseVariant( value, memberFilter, nestingLimit.decrement() );
6902 if ( err )
6903 return err;
6904 }
6905 return DeserializationError::Ok;
6906 }
6907 template <typename TSize, typename TFilter>
6908 DeserializationError::Code readObject(
6909 VariantData* variant, TFilter filter,
6910 DeserializationOption::NestingLimit nestingLimit ) {
6911 DeserializationError::Code err;
6912 TSize size;
6913 err = readInteger( size );
6914 if ( err )
6915 return err;
6916 return readObject( variant, size, filter, nestingLimit );
6917 }
6918 template <typename TFilter>
6919 DeserializationError::Code readObject(
6920 VariantData* variant, size_t n, TFilter filter,
6921 DeserializationOption::NestingLimit nestingLimit ) {
6922 DeserializationError::Code err;
6923 if ( nestingLimit.reached() )
6924 return DeserializationError::TooDeep;
6925 CollectionData* object;
6926 if ( filter.allowObject() ) {
6927 ARDUINOJSON_ASSERT( variant != 0 );
6928 object = &variant->toObject();
6929 }
6930 else {
6931 object = 0;
6932 }
6933 for ( ; n; --n ) {
6934 err = readKey();
6935 if ( err )
6936 return err;
6937 JsonString key = stringStorage_.str();
6938 TFilter memberFilter = filter[key.c_str()];
6939 VariantData* member;
6940 if ( memberFilter.allow() ) {
6941 ARDUINOJSON_ASSERT( object != 0 );
6942 key = stringStorage_.save();
6943 VariantSlot* slot = object->addSlot( pool_ );
6944 if ( !slot )
6945 return DeserializationError::NoMemory;
6946 slot->setKey( key );
6947 member = slot->data();
6948 }
6949 else {
6950 member = 0;
6951 }
6952 err = parseVariant( member, memberFilter, nestingLimit.decrement() );
6953 if ( err )
6954 return err;
6955 }
6956 return DeserializationError::Ok;
6957 }
6958 DeserializationError::Code readKey() {
6959 DeserializationError::Code err;
6960 uint8_t code;
6961 err = readByte( code );
6962 if ( err )
6963 return err;
6964 if ( (code & 0xe0) == 0xa0 )
6965 return readString( code & 0x1f );
6966 switch ( code ) {
6967 case 0xd9:
6968 return readString<uint8_t>();
6969 case 0xda:
6970 return readString<uint16_t>();
6971 case 0xdb:
6972 return readString<uint32_t>();
6973 default:
6974 return DeserializationError::InvalidInput;
6975 }
6976 }
6977 template <typename T>
6978 DeserializationError::Code skipExt() {
6979 DeserializationError::Code err;
6980 T size;
6981 err = readInteger( size );
6982 if ( err )
6983 return err;
6984 return skipBytes( size + 1U );
6985 }
6986 MemoryPool* pool_;
6987 TReader reader_;
6988 TStringStorage stringStorage_;
6989 bool foundSomething_;
6990};
6991ARDUINOJSON_END_PRIVATE_NAMESPACE
6992ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
6993template <typename... Args>
6994DeserializationError deserializeMsgPack( JsonDocument& doc, Args&&... args ) {
6995 using namespace detail;
6996 return deserialize<MsgPackDeserializer>( doc, detail::forward<Args>( args )... );
6997}
6998template <typename TChar, typename... Args>
6999DeserializationError deserializeMsgPack( JsonDocument& doc, TChar* input,
7000 Args&&... args ) {
7001 using namespace detail;
7002 return deserialize<MsgPackDeserializer>( doc, input,
7003 detail::forward<Args>( args )... );
7004}
7005ARDUINOJSON_END_PUBLIC_NAMESPACE
7006ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
7007template <typename TWriter>
7008class MsgPackSerializer : public Visitor<size_t> {
7009public:
7010 static const bool producesText = false;
7011 MsgPackSerializer( TWriter writer ) : writer_( writer ) {}
7012 template <typename T>
7013 typename enable_if<sizeof( T ) == 4, size_t>::type visitFloat( T value32 ) {
7014 if ( canConvertNumber<JsonInteger>( value32 ) ) {
7015 JsonInteger truncatedValue = JsonInteger( value32 );
7016 if ( value32 == T( truncatedValue ) )
7017 return visitSignedInteger( truncatedValue );
7018 }
7019 writeByte( 0xCA );
7020 writeInteger( value32 );
7021 return bytesWritten();
7022 }
7023 template <typename T>
7024 ARDUINOJSON_NO_SANITIZE( "float-cast-overflow" )
7025 typename enable_if<sizeof( T ) == 8, size_t>::type visitFloat( T value64 ) {
7026 float value32 = float( value64 );
7027 if ( value32 == value64 )
7028 return visitFloat( value32 );
7029 writeByte( 0xCB );
7030 writeInteger( value64 );
7031 return bytesWritten();
7032 }
7033 size_t visitArray( const CollectionData& array ) {
7034 size_t n = array.size();
7035 if ( n < 0x10 ) {
7036 writeByte( uint8_t( 0x90 + n ) );
7037 }
7038 else if ( n < 0x10000 ) {
7039 writeByte( 0xDC );
7040 writeInteger( uint16_t( n ) );
7041 }
7042 else {
7043 writeByte( 0xDD );
7044 writeInteger( uint32_t( n ) );
7045 }
7046 for ( const VariantSlot* slot = array.head(); slot; slot = slot->next() ) {
7047 slot->data()->accept( *this );
7048 }
7049 return bytesWritten();
7050 }
7051 size_t visitObject( const CollectionData& object ) {
7052 size_t n = object.size();
7053 if ( n < 0x10 ) {
7054 writeByte( uint8_t( 0x80 + n ) );
7055 }
7056 else if ( n < 0x10000 ) {
7057 writeByte( 0xDE );
7058 writeInteger( uint16_t( n ) );
7059 }
7060 else {
7061 writeByte( 0xDF );
7062 writeInteger( uint32_t( n ) );
7063 }
7064 for ( const VariantSlot* slot = object.head(); slot; slot = slot->next() ) {
7065 visitString( slot->key() );
7066 slot->data()->accept( *this );
7067 }
7068 return bytesWritten();
7069 }
7070 size_t visitString( const char* value ) {
7071 return visitString( value, strlen( value ) );
7072 }
7073 size_t visitString( const char* value, size_t n ) {
7074 ARDUINOJSON_ASSERT( value != NULL );
7075 if ( n < 0x20 ) {
7076 writeByte( uint8_t( 0xA0 + n ) );
7077 }
7078 else if ( n < 0x100 ) {
7079 writeByte( 0xD9 );
7080 writeInteger( uint8_t( n ) );
7081 }
7082 else if ( n < 0x10000 ) {
7083 writeByte( 0xDA );
7084 writeInteger( uint16_t( n ) );
7085 }
7086 else {
7087 writeByte( 0xDB );
7088 writeInteger( uint32_t( n ) );
7089 }
7090 writeBytes( reinterpret_cast<const uint8_t*>(value), n );
7091 return bytesWritten();
7092 }
7093 size_t visitRawJson( const char* data, size_t size ) {
7094 writeBytes( reinterpret_cast<const uint8_t*>(data), size );
7095 return bytesWritten();
7096 }
7097 size_t visitSignedInteger( JsonInteger value ) {
7098 if ( value > 0 ) {
7099 visitUnsignedInteger( static_cast<JsonUInt>(value) );
7100 }
7101 else if ( value >= -0x20 ) {
7102 writeInteger( int8_t( value ) );
7103 }
7104 else if ( value >= -0x80 ) {
7105 writeByte( 0xD0 );
7106 writeInteger( int8_t( value ) );
7107 }
7108 else if ( value >= -0x8000 ) {
7109 writeByte( 0xD1 );
7110 writeInteger( int16_t( value ) );
7111 }
7112#if ARDUINOJSON_USE_LONG_LONG
7113 else if ( value >= -0x80000000LL )
7114#else
7115 else
7116#endif
7117 {
7118 writeByte( 0xD2 );
7119 writeInteger( int32_t( value ) );
7120 }
7121#if ARDUINOJSON_USE_LONG_LONG
7122 else {
7123 writeByte( 0xD3 );
7124 writeInteger( int64_t( value ) );
7125 }
7126#endif
7127 return bytesWritten();
7128 }
7129 size_t visitUnsignedInteger( JsonUInt value ) {
7130 if ( value <= 0x7F ) {
7131 writeInteger( uint8_t( value ) );
7132 }
7133 else if ( value <= 0xFF ) {
7134 writeByte( 0xCC );
7135 writeInteger( uint8_t( value ) );
7136 }
7137 else if ( value <= 0xFFFF ) {
7138 writeByte( 0xCD );
7139 writeInteger( uint16_t( value ) );
7140 }
7141#if ARDUINOJSON_USE_LONG_LONG
7142 else if ( value <= 0xFFFFFFFF )
7143#else
7144 else
7145#endif
7146 {
7147 writeByte( 0xCE );
7148 writeInteger( uint32_t( value ) );
7149 }
7150#if ARDUINOJSON_USE_LONG_LONG
7151 else {
7152 writeByte( 0xCF );
7153 writeInteger( uint64_t( value ) );
7154 }
7155#endif
7156 return bytesWritten();
7157 }
7158 size_t visitBoolean( bool value ) {
7159 writeByte( value ? 0xC3 : 0xC2 );
7160 return bytesWritten();
7161 }
7162 size_t visitNull() {
7163 writeByte( 0xC0 );
7164 return bytesWritten();
7165 }
7166private:
7167 size_t bytesWritten() const {
7168 return writer_.count();
7169 }
7170 void writeByte( uint8_t c ) {
7171 writer_.write( c );
7172 }
7173 void writeBytes( const uint8_t* p, size_t n ) {
7174 writer_.write( p, n );
7175 }
7176 template <typename T>
7177 void writeInteger( T value ) {
7178 fixEndianess( value );
7179 writeBytes( reinterpret_cast<uint8_t*>(&value), sizeof( value ) );
7180 }
7181 CountingDecorator<TWriter> writer_;
7182};
7183ARDUINOJSON_END_PRIVATE_NAMESPACE
7184ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
7185template <typename TDestination>
7186inline size_t serializeMsgPack( JsonVariantConst source, TDestination& output ) {
7187 using namespace ArduinoJson::detail;
7188 return serialize<MsgPackSerializer>( source, output );
7189}
7190inline size_t serializeMsgPack( JsonVariantConst source, void* output,
7191 size_t size ) {
7192 using namespace ArduinoJson::detail;
7193 return serialize<MsgPackSerializer>( source, output, size );
7194}
7195inline size_t measureMsgPack( JsonVariantConst source ) {
7196 using namespace ArduinoJson::detail;
7197 return measure<MsgPackSerializer>( source );
7198}
7199ARDUINOJSON_END_PUBLIC_NAMESPACE
7200#ifdef __GNUC__
7201#define ARDUINOJSON_PRAGMA(x) _Pragma(#x)
7202#define ARDUINOJSON_COMPILE_ERROR(msg) ARDUINOJSON_PRAGMA(GCC error msg)
7203#define ARDUINOJSON_STRINGIFY(S) #S
7204#define ARDUINOJSON_DEPRECATION_ERROR(X, Y) \
7205 ARDUINOJSON_COMPILE_ERROR(ARDUINOJSON_STRINGIFY(X is a Y from ArduinoJson 5. Please see https:/\/arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6))
7206#define StaticJsonBuffer ARDUINOJSON_DEPRECATION_ERROR(StaticJsonBuffer, class)
7207#define DynamicJsonBuffer ARDUINOJSON_DEPRECATION_ERROR(DynamicJsonBuffer, class)
7208#define JsonBuffer ARDUINOJSON_DEPRECATION_ERROR(JsonBuffer, class)
7209#define RawJson ARDUINOJSON_DEPRECATION_ERROR(RawJson, function)
7210#define ARDUINOJSON_NAMESPACE _Pragma ("GCC warning \"ARDUINOJSON_NAMESPACE is deprecated, use ArduinoJson instead\"") ArduinoJson
7211#endif
7212
7213using namespace ArduinoJson;
7214
7215#else
7216
7217#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp
7218
7219#endif
ostream & operator<<(ostream &out, const Cpl::Text::String &outstring)
Support stream output operator directly.