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.
13#ifndef ARDUINOJSON_ENABLE_STD_STREAM
15# if __has_include(<istream>) && \
16 __has_include(<ostream>) && \
19# define ARDUINOJSON_ENABLE_STD_STREAM 1
21# define ARDUINOJSON_ENABLE_STD_STREAM 0
25# define ARDUINOJSON_ENABLE_STD_STREAM 0
27# define ARDUINOJSON_ENABLE_STD_STREAM 1
31#ifndef ARDUINOJSON_ENABLE_STD_STRING
33# if __has_include(<string>) && !defined(min) && !defined(max)
34# define ARDUINOJSON_ENABLE_STD_STRING 1
36# define ARDUINOJSON_ENABLE_STD_STRING 0
40# define ARDUINOJSON_ENABLE_STD_STRING 0
42# define ARDUINOJSON_ENABLE_STD_STRING 1
46#ifndef ARDUINOJSON_ENABLE_STRING_VIEW
48# if __has_include(<string_view>) && __cplusplus >= 201703L
49# define ARDUINOJSON_ENABLE_STRING_VIEW 1
51# define ARDUINOJSON_ENABLE_STRING_VIEW 0
54# define ARDUINOJSON_ENABLE_STRING_VIEW 0
57#ifndef ARDUINOJSON_USE_DOUBLE
58# define ARDUINOJSON_USE_DOUBLE 1
60#ifndef ARDUINOJSON_USE_LONG_LONG
61# if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ >= 4 || \
63# define ARDUINOJSON_USE_LONG_LONG 1
66#ifndef ARDUINOJSON_USE_LONG_LONG
67# define ARDUINOJSON_USE_LONG_LONG 0
69#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
70# define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
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
79# define ARDUINOJSON_SLOT_OFFSET_SIZE 2
83# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
84# define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
86# ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
87# define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
89# ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
90# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1
92# ifndef ARDUINOJSON_ENABLE_PROGMEM
93# define ARDUINOJSON_ENABLE_PROGMEM 1
96# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
97# define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
99# ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
100# define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
102# ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
103# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
105# ifndef ARDUINOJSON_ENABLE_PROGMEM
107# define ARDUINOJSON_ENABLE_PROGMEM 1
109# define ARDUINOJSON_ENABLE_PROGMEM 0
113#ifndef ARDUINOJSON_DECODE_UNICODE
114# define ARDUINOJSON_DECODE_UNICODE 1
116#ifndef ARDUINOJSON_ENABLE_COMMENTS
117# define ARDUINOJSON_ENABLE_COMMENTS 0
119#ifndef ARDUINOJSON_ENABLE_NAN
120# define ARDUINOJSON_ENABLE_NAN 0
122#ifndef ARDUINOJSON_ENABLE_INFINITY
123# define ARDUINOJSON_ENABLE_INFINITY 0
125#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
126# define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
128#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
129# define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
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
138# define ARDUINOJSON_LITTLE_ENDIAN 0
141#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
143# define ARDUINOJSON_ENABLE_ALIGNMENT 0
145# define ARDUINOJSON_ENABLE_ALIGNMENT 1
148#ifndef ARDUINOJSON_TAB
149# define ARDUINOJSON_TAB " "
151#ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
152# define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1
154#ifndef ARDUINOJSON_STRING_BUFFER_SIZE
155# define ARDUINOJSON_STRING_BUFFER_SIZE 32
157#ifndef ARDUINOJSON_DEBUG
158# ifdef __PLATFORMIO_BUILD_DEBUG__
159# define ARDUINOJSON_DEBUG 1
161# define ARDUINOJSON_DEBUG 0
165# error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
167#if ARDUINOJSON_ENABLE_ARDUINO_STRING || ARDUINOJSON_ENABLE_ARDUINO_STREAM || \
168 ARDUINOJSON_ENABLE_ARDUINO_PRINT || \
169 (ARDUINOJSON_ENABLE_PROGMEM && defined(ARDUINO))
172#if !ARDUINOJSON_DEBUG
174# pragma clang system_header
175# elif defined __GNUC__
176# pragma GCC system_header
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)
218#define ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE \
219 namespace ArduinoJson { \
220 inline namespace ARDUINOJSON_VERSION_NAMESPACE {
221#define ARDUINOJSON_END_PUBLIC_NAMESPACE \
224#define ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE \
225 namespace ArduinoJson { \
226 inline namespace ARDUINOJSON_VERSION_NAMESPACE { \
228#define ARDUINOJSON_END_PRIVATE_NAMESPACE \
232ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
233template <
typename T,
typename Enable =
void>
235ARDUINOJSON_END_PUBLIC_NAMESPACE
236ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
237template <
typename T1,
typename T2>
238class InvalidConversion;
240struct ConverterNeedsWriteableRef;
241ARDUINOJSON_END_PRIVATE_NAMESPACE
244ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
245#if ARDUINOJSON_ENABLE_ALIGNMENT
246inline bool isAligned(
size_t value ) {
247 const size_t mask =
sizeof(
void* ) - 1;
249 return (addr & mask) == 0;
251inline size_t addPadding(
size_t bytes ) {
252 const size_t mask =
sizeof(
void* ) - 1;
253 return (bytes + mask) & ~mask;
255template <
size_t bytes>
257 static const size_t mask =
sizeof(
void* ) - 1;
258 static const size_t value = (bytes + mask) & ~mask;
261inline bool isAligned(
size_t ) {
264inline size_t addPadding(
size_t bytes ) {
267template <
size_t bytes>
269 static const size_t value = bytes;
273inline bool isAligned( T* ptr ) {
274 return isAligned(
reinterpret_cast<size_t>(ptr) );
277inline T* addPadding( T* p ) {
278 size_t address = addPadding(
reinterpret_cast<size_t>(p) );
279 return reinterpret_cast<T*
>(address);
281ARDUINOJSON_END_PRIVATE_NAMESPACE
284# define ARDUINOJSON_ASSERT(X) assert(X)
286# define ARDUINOJSON_ASSERT(X) ((void)0)
288ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
289template <
size_t X,
size_t Y,
bool MaxIsX = (X > Y)>
291template <
size_t X,
size_t Y>
292struct Max<X, Y, true> {
293 static const size_t value = X;
295template <
size_t X,
size_t Y>
296struct Max<X, Y, false> {
297 static const size_t value = Y;
299template <
bool Condition,
class TrueType,
class FalseType>
301 typedef TrueType type;
303template <
class TrueType,
class FalseType>
304struct conditional<false, TrueType, FalseType> {
305 typedef FalseType type;
307template <
bool Condition,
typename T =
void>
310struct enable_if<true, T> {
313template <
typename T, T v>
314struct integral_constant {
315 static const T value = v;
317typedef integral_constant<bool, true> true_type;
318typedef integral_constant<bool, false> false_type;
320struct is_array : false_type {};
322struct is_array<T[]> : true_type {};
323template <
typename T,
size_t N>
324struct is_array<T[N]> : true_type {};
326struct remove_reference {
330struct remove_reference<T&> {
333template <
typename TBase,
typename TDerived>
336 static int probe(
const TBase* );
337 static char probe( ... );
339 static const bool value =
340 sizeof( probe(
reinterpret_cast<typename remove_reference<TDerived>::type*
>(
341 0) ) ) ==
sizeof(
int );
348 template <
typename U>
349 static int probe(
void (U::*)(void) );
351 static char probe( ... );
353 static const bool value =
sizeof( probe<T>( 0 ) ) ==
sizeof(
int );
356struct is_const : false_type {};
358struct is_const<const T> : true_type {};
359ARDUINOJSON_END_PRIVATE_NAMESPACE
361# pragma warning(push)
362# pragma warning(disable : 4244)
365#pragma diag_suppress=Pa093
367ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
368template <
typename From,
typename To>
369struct is_convertible {
371 static int probe( To );
372 static char probe( ... );
375 static const bool value =
sizeof( probe( from_ ) ) ==
sizeof(
int );
377ARDUINOJSON_END_PRIVATE_NAMESPACE
382#pragma diag_default=Pa093
384ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
385template <
typename T,
typename U>
386struct is_same : false_type {};
388struct is_same<T, T> : true_type {};
394struct remove_cv<const T> {
398struct remove_cv<volatile T> {
402struct remove_cv<const volatile T> {
406struct is_floating_point
409 is_same<float, typename remove_cv<T>::type>::value ||
410 is_same<double, typename remove_cv<T>::type>::value> {};
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> {};
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;
432struct is_pointer : false_type {};
434struct is_pointer<T*> : true_type {};
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> {};
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> {};
454struct type_identity {
460struct make_unsigned<char> : type_identity<unsigned char> {};
462struct make_unsigned<signed char> : type_identity<unsigned char> {};
464struct make_unsigned<unsigned char> : type_identity<unsigned char> {};
466struct make_unsigned<signed short> : type_identity<unsigned short> {};
468struct make_unsigned<unsigned short> : type_identity<unsigned short> {};
470struct make_unsigned<signed int> : type_identity<unsigned int> {};
472struct make_unsigned<unsigned int> : type_identity<unsigned int> {};
474struct make_unsigned<signed long> : type_identity<unsigned long> {};
476struct make_unsigned<unsigned long> : type_identity<unsigned long> {};
478struct make_unsigned<signed long long> : type_identity<unsigned long long> {};
480struct make_unsigned<unsigned long long> : type_identity<unsigned long long> {};
481template <
class =
void>
490struct remove_const<const T> {
493ARDUINOJSON_END_PRIVATE_NAMESPACE
497# define NO_INLINE __declspec(noinline)
498#elif defined(__GNUC__)
499# define FORCE_INLINE __attribute__((always_inline))
500# define NO_INLINE __attribute__((noinline))
505#if defined(__has_attribute)
506# if __has_attribute(no_sanitize)
507# define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check)))
509# define ARDUINOJSON_NO_SANITIZE(check)
512# define ARDUINOJSON_NO_SANITIZE(check)
514ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
515namespace StringStoragePolicy {
522template <
typename TString,
typename Enable =
void>
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 );
530template <
typename TChar>
531typename StringAdapter<TChar*>::AdaptedString adaptString( TChar* p ) {
532 return StringAdapter<TChar*>::adapt( p );
534template <
typename TChar>
535typename SizedStringAdapter<TChar*>::AdaptedString adaptString( TChar* p,
537 return SizedStringAdapter<TChar*>::adapt( p, n );
541 : integral_constant<bool, is_integral<T>::value && sizeof( T ) == 1> {};
542class ZeroTerminatedRamString {
544 static const size_t typeSortKey = 3;
545 ZeroTerminatedRamString(
const char* str ) : str_( str ) {}
546 bool isNull()
const {
549 FORCE_INLINE
size_t size()
const {
550 return str_ ? ::strlen( str_ ) : 0;
552 char operator[](
size_t i )
const {
553 ARDUINOJSON_ASSERT( str_ != 0 );
554 ARDUINOJSON_ASSERT( i <= size() );
557 const char* data()
const {
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_ );
566 friend bool stringEquals( ZeroTerminatedRamString a,
567 ZeroTerminatedRamString b ) {
568 return stringCompare( a, b ) == 0;
570 StringStoragePolicy::Copy storagePolicy()
const {
571 return StringStoragePolicy::Copy();
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) );
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) );
590class StaticStringAdapter :
public ZeroTerminatedRamString {
592 StaticStringAdapter(
const char* str ) : ZeroTerminatedRamString( str ) {}
593 StringStoragePolicy::Link storagePolicy()
const {
594 return StringStoragePolicy::Link();
598struct StringAdapter<const char*,
void> {
599 typedef StaticStringAdapter AdaptedString;
600 static AdaptedString adapt(
const char* p ) {
601 return AdaptedString( p );
604class SizedRamString {
606 static const size_t typeSortKey = 2;
607 SizedRamString(
const char* str,
size_t sz ) : str_( str ), size_( sz ) {}
608 bool isNull()
const {
611 size_t size()
const {
614 char operator[](
size_t i )
const {
615 ARDUINOJSON_ASSERT( str_ != 0 );
616 ARDUINOJSON_ASSERT( i <= size() );
619 const char* data()
const {
622 StringStoragePolicy::Copy storagePolicy()
const {
623 return StringStoragePolicy::Copy();
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 );
637ARDUINOJSON_END_PRIVATE_NAMESPACE
638#if ARDUINOJSON_ENABLE_STD_STREAM
641ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
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 {
653 bool isNull()
const {
656 bool isLinked()
const {
657 return ownership_ == Linked;
659 size_t size()
const {
662 explicit operator bool()
const {
665 friend bool operator==( JsonString lhs, JsonString rhs ) {
666 if ( lhs.size_ != rhs.size_ )
668 if ( lhs.data_ == rhs.data_ )
674 return memcmp( lhs.data_, rhs.data_, lhs.size_ ) == 0;
676 friend bool operator!=( JsonString lhs, JsonString rhs ) {
677 return !(lhs == rhs);
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()) );
688 Ownership ownership_;
690ARDUINOJSON_END_PUBLIC_NAMESPACE
691ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
692class JsonStringAdapter :
public SizedRamString {
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_ };
704struct StringAdapter<JsonString> {
705 typedef JsonStringAdapter AdaptedString;
706 static AdaptedString adapt(
const JsonString& s ) {
707 return AdaptedString( s );
710namespace string_traits_impl {
711template <
class T,
class =
void>
712struct has_cstr : false_type {};
715 typename enable_if<is_same<decltype(declval<const T>().c_str()),
716 const char*>::value>::type>
718template <
class T,
class =
void>
719struct has_data : false_type {};
722 typename enable_if<is_same<decltype(declval<const T>().data()),
723 const char*>::value>::type>
725template <
class T,
class =
void>
726struct has_length : false_type {};
729 T, typename enable_if<
730 is_same<decltype(declval<const T>().length()), size_t>::value>::type>
732template <
class T,
class =
void>
733struct has_size : false_type {};
736 T, typename enable_if<
737 is_same<decltype(declval<const T>().size()), size_t>::value>::type>
741struct string_traits {
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
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 ) );
760 template <
typename U>
761 static typename enable_if<string_traits<U>::has_size,
size_t>::type get_size(
765 template <
typename U>
766 static typename enable_if<!string_traits<U>::has_size,
size_t>::type get_size(
770 template <
typename U>
771 static typename enable_if<string_traits<U>::has_data,
const char*>::type
772 get_data(
const U& s ) {
775 template <
typename U>
776 static typename enable_if<!string_traits<U>::has_data,
const char*>::type
777 get_data(
const U& s ) {
781ARDUINOJSON_END_PRIVATE_NAMESPACE
782#if ARDUINOJSON_ENABLE_PROGMEM
785class __FlashStringHelper;
786#include <avr/pgmspace.h>
788ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
790 pgm_p(
const void* p ) : address( reinterpret_cast<const char*>(p) ) {}
793ARDUINOJSON_END_PRIVATE_NAMESPACE
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 ) )
800 return size_t( p - s.address );
804inline int strncmp_P(
const char* a, ArduinoJson::detail::pgm_p b,
size_t n ) {
806 const char* s2 = b.address;
807 ARDUINOJSON_ASSERT( s1 != NULL );
808 ARDUINOJSON_ASSERT( s2 != NULL );
811 char c2 =
static_cast<char>(pgm_read_byte( s2++ ));
823inline int strcmp_P(
const char* a, ArduinoJson::detail::pgm_p b ) {
825 const char* s2 = b.address;
826 ARDUINOJSON_ASSERT( s1 != NULL );
827 ARDUINOJSON_ASSERT( s2 != NULL );
830 char c2 =
static_cast<char>(pgm_read_byte( s2++ ));
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 );
848 uint8_t v2 = pgm_read_byte( p2++ );
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 );
862 *d++ = pgm_read_byte( s++ );
867#ifndef pgm_read_dword
868inline uint32_t pgm_read_dword( ArduinoJson::detail::pgm_p p ) {
870 memcpy_P( &result, p.address, 4 );
874#ifndef pgm_read_float
875inline float pgm_read_float( ArduinoJson::detail::pgm_p p ) {
877 memcpy_P( &result, p.address,
sizeof(
float ) );
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 );
888inline double pgm_read_double( ArduinoJson::detail::pgm_p p ) {
890 memcpy_P( &result, p.address,
sizeof(
double ) );
896inline void* pgm_read_ptr( ArduinoJson::detail::pgm_p p ) {
898 memcpy_P( &result, p.address,
sizeof( result ) );
902ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
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 {
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 ));
916 size_t size()
const {
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() )
925 return ::memcmp_P( b.data(), a.str_, a.size_ ) == 0;
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 );
935 if ( a.size() < b.size() )
937 if ( a.size() > b.size() )
941 friend void stringGetChars( FlashString s,
char* p,
size_t n ) {
942 ARDUINOJSON_ASSERT( s.size() <= n );
943 ::memcpy_P( p, s.str_, n );
945 StringStoragePolicy::Copy storagePolicy()
const {
946 return StringStoragePolicy::Copy();
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 );
960struct SizedStringAdapter<const __FlashStringHelper*,
void> {
961 typedef FlashString AdaptedString;
962 static AdaptedString adapt(
const __FlashStringHelper* s,
size_t n ) {
963 return AdaptedString( s, n );
966ARDUINOJSON_END_PRIVATE_NAMESPACE
968ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
969template <
typename TAdaptedString1,
typename TAdaptedString2>
970typename enable_if<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey,
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];
988template <
typename TAdaptedString1,
typename TAdaptedString2>
990 (TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey),
int>::type
991 stringCompare( TAdaptedString1 s1, TAdaptedString2 s2 ) {
992 return -stringCompare( s2, s1 );
994template <
typename TAdaptedString1,
typename TAdaptedString2>
995typename enable_if<TAdaptedString1::typeSortKey <= TAdaptedString2::typeSortKey,
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 )
1004 for (
size_t i = 0; i < size1; i++ ) {
1005 if ( s1[i] != s2[i] )
1010template <
typename TAdaptedString1,
typename TAdaptedString2>
1012 (TAdaptedString1::typeSortKey > TAdaptedString2::typeSortKey),
bool>::type
1013 stringEquals( TAdaptedString1 s1, TAdaptedString2 s2 ) {
1014 return stringEquals( s2, s1 );
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++ ) {
1027 typedef int8_t type;
1031 typedef int16_t type;
1035 typedef int32_t type;
1037ARDUINOJSON_END_PRIVATE_NAMESPACE
1039# pragma warning(push)
1040# pragma warning(disable : 4310)
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> {
1050 static T highest() {
1054template <
typename T>
1055struct numeric_limits<
1056 T, typename enable_if<is_integral<T>::value && is_signed<T>::value>::type> {
1058 return T( T( 1 ) << (
sizeof( T ) * 8 - 1) );
1060 static T highest() {
1061 return T( ~lowest() );
1064ARDUINOJSON_END_PRIVATE_NAMESPACE
1066# pragma warning(pop)
1068ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1072class CollectionData {
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 ) );
1090 template <
typename TAdaptedString>
1091 bool containsKey(
const TAdaptedString& key )
const;
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 {
1101 void movePointers( ptrdiff_t stringDistance, ptrdiff_t variantDistance );
1103 VariantSlot* getSlot(
size_t index )
const;
1104 template <
typename TAdaptedString>
1105 VariantSlot* getSlot( TAdaptedString key )
const;
1106 VariantSlot* getPreviousSlot( VariantSlot* )
const;
1108inline const VariantData* collectionToVariant(
1109 const CollectionData* collection ) {
1110 const void* data = collection;
1111 return reinterpret_cast<const VariantData*
>(data);
1113inline VariantData* collectionToVariant( CollectionData* collection ) {
1114 void* data = collection;
1115 return reinterpret_cast<VariantData*
>(data);
1117ARDUINOJSON_END_PRIVATE_NAMESPACE
1118ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
1119#if ARDUINOJSON_USE_DOUBLE
1120typedef double JsonFloat;
1122typedef float JsonFloat;
1124#if ARDUINOJSON_USE_LONG_LONG
1125typedef int64_t JsonInteger;
1126typedef uint64_t JsonUInt;
1128typedef long JsonInteger;
1129typedef unsigned long JsonUInt;
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
1140 OWNED_VALUE_BIT = 0x01,
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,
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
1160union VariantContent {
1163 JsonUInt asUnsignedInteger;
1164 JsonInteger asSignedInteger;
1165 CollectionData asCollection;
1171typedef int_t<ARDUINOJSON_SLOT_OFFSET_SIZE * 8>::type VariantSlotDiff;
1173 VariantContent content_;
1175 VariantSlotDiff next_;
1178 VariantData* data() {
1179 return reinterpret_cast<VariantData*
>(&content_);
1181 const VariantData* data()
const {
1182 return reinterpret_cast<const VariantData*
>(&content_);
1184 VariantSlot* next() {
1185 return next_ ?
this + next_ : 0;
1187 const VariantSlot* next()
const {
1188 return const_cast<VariantSlot*
>(
this)->next();
1190 VariantSlot* next(
size_t distance ) {
1191 VariantSlot* slot =
this;
1192 while ( distance-- ) {
1195 slot += slot->next_;
1199 const VariantSlot* next(
size_t distance )
const {
1200 return const_cast<VariantSlot*
>(
this)->next( distance );
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 );
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 );
1217 void setKey( JsonString k ) {
1218 ARDUINOJSON_ASSERT( k );
1220 flags_ &= VALUE_MASK;
1222 flags_ |= OWNED_KEY_BIT;
1225 const char* key()
const {
1228 bool ownsKey()
const {
1229 return (flags_ & OWNED_KEY_BIT) != 0;
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 );
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
1254 MemoryPool(
char* buf,
size_t capa )
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_ ) );
1267 size_t capacity()
const {
1268 return size_t( end_ - begin_ );
1270 size_t size()
const {
1271 return size_t( left_ - begin_ + end_ - right_ );
1273 bool overflowed()
const {
1276 VariantSlot* allocVariant() {
1277 return allocRight<VariantSlot>();
1279 template <
typename TAdaptedString>
1280 const char* saveString( TAdaptedString str ) {
1283#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
1284 const char* existingCopy = findString( str );
1286 return existingCopy;
1288 size_t n = str.size();
1289 char* newCopy = allocString( n + 1 );
1291 stringGetChars( str, newCopy, n );
1296 void getFreeZone(
char** zoneStart,
size_t* zoneSize )
const {
1298 *zoneSize = size_t( right_ - left_ );
1300 const char* saveStringFromFreeZone(
size_t len ) {
1301#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
1302 const char* dup = findString( adaptString( left_, len ) );
1306 const char* str = left_;
1312 void markAsOverflowed() {
1318 overflowed_ =
false;
1320 bool canAlloc(
size_t bytes )
const {
1321 return left_ + bytes <= right_;
1323 bool owns(
void* p )
const {
1324 return begin_ <= p && p < end_;
1326 void*
operator new(size_t,
void* p) {
1329 ptrdiff_t squash() {
1330 char* new_right = addPadding( left_ );
1331 if ( new_right >= right_ )
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;
1337 end_ = new_right + right_size;
1338 return bytes_reclaimed;
1340 void movePointers( ptrdiff_t offset ) {
1347 void checkInvariants() {
1348 ARDUINOJSON_ASSERT( begin_ <= left_ );
1349 ARDUINOJSON_ASSERT( left_ <= right_ );
1350 ARDUINOJSON_ASSERT( right_ <= end_ );
1351 ARDUINOJSON_ASSERT( isAligned( right_ ) );
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 ) ) )
1366 char* allocString(
size_t n ) {
1367 if ( !canAlloc( n ) ) {
1376 template <
typename T>
1378 return reinterpret_cast<T*
>(allocRight(
sizeof( T ) ));
1380 void* allocRight(
size_t bytes ) {
1381 if ( !canAlloc( bytes ) ) {
1388 char *begin_, *left_, *right_, *end_;
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 );
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();
1406template <
typename TAdaptedString,
typename TCallback>
1407bool storeString( MemoryPool* pool, TAdaptedString str,
1408 StringStoragePolicy::LinkOrCopy policy, TCallback callback ) {
1410 return storeString( pool, str, StringStoragePolicy::Link(), callback );
1412 return storeString( pool, str, StringStoragePolicy::Copy(), callback );
1414template <
typename TAdaptedString,
typename TCallback>
1415bool storeString( MemoryPool* pool, TAdaptedString str, TCallback callback ) {
1416 return storeString( pool, str, str.storagePolicy(), callback );
1418template <
typename T,
typename Enable =
void>
1419struct IsString : false_type {};
1420template <
typename T>
1422 T, typename make_void<typename StringAdapter<T>::AdaptedString>::type>
1424ARDUINOJSON_END_PRIVATE_NAMESPACE
1425ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
1429ARDUINOJSON_END_PUBLIC_NAMESPACE
1430ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1431template <
typename T>
1434struct VariantTo<JsonArray> {
1435 typedef JsonArray type;
1438struct VariantTo<JsonObject> {
1439 typedef JsonObject type;
1442struct VariantTo<JsonVariant> {
1443 typedef JsonVariant type;
1445class VariantAttorney {
1446 template <
typename TClient>
1447 struct ResultOfGetData {
1449 static int probe(
const VariantData* );
1450 static char probe( VariantData* );
1451 static TClient& client;
1453 typedef typename conditional<
sizeof( probe( client.getData() ) ) ==
sizeof(
int ),
1454 const VariantData*, VariantData*>::type type;
1457 template <
typename TClient>
1458 FORCE_INLINE
static MemoryPool* getPool( TClient& client ) {
1459 return client.getPool();
1461 template <
typename TClient>
1462 FORCE_INLINE
static typename ResultOfGetData<TClient>::type getData(
1464 return client.getData();
1466 template <
typename TClient>
1467 FORCE_INLINE
static VariantData* getOrCreateData( TClient& client ) {
1468 return client.getOrCreateData();
1471ARDUINOJSON_END_PRIVATE_NAMESPACE
1472ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
1473template <
typename T>
1474class SerializedValue {
1476 explicit SerializedValue( T str ) : str_( str ) {}
1477 operator T()
const {
1480 const char* data()
const {
1481 return str_.c_str();
1483 size_t size()
const {
1484 return str_.length();
1489template <
typename TChar>
1490class SerializedValue<TChar*> {
1492 explicit SerializedValue( TChar* p,
size_t n ) : data_( p ), size_( n ) {}
1493 operator TChar*()
const {
1496 TChar* data()
const {
1499 size_t size()
const {
1506template <
typename T>
1507inline SerializedValue<T> serialized( T str ) {
1508 return SerializedValue<T>( str );
1510template <
typename TChar>
1511inline SerializedValue<TChar*> serialized( TChar* p ) {
1512 return SerializedValue<TChar*>( p, detail::adaptString( p ).size() );
1514template <
typename TChar>
1515inline SerializedValue<TChar*> serialized( TChar* p,
size_t n ) {
1516 return SerializedValue<TChar*>( p, n );
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"
1527ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1529template <
typename T>
1535template <
typename T>
1537 return x != 0.0 && x * 2 == x;
1540template <
typename T,
typename F>
1541struct alias_cast_t {
1547template <
typename T,
typename F>
1548T alias_cast( F raw_data ) {
1549 alias_cast_t<T, F> ac;
1553ARDUINOJSON_END_PRIVATE_NAMESPACE
1554#if ARDUINOJSON_ENABLE_PROGMEM
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__;
1562template <
typename T>
1563inline const T* pgm_read(
const T*
const* p ) {
1564 return reinterpret_cast<const T*
>(pgm_read_ptr( p ));
1566inline uint32_t pgm_read(
const uint32_t* p ) {
1567 return pgm_read_dword( p );
1569inline double pgm_read(
const double* p ) {
1570 return pgm_read_double( p );
1572inline float pgm_read(
const float* p ) {
1573 return pgm_read_float( p );
1576# ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY
1577# define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, ...) \
1578 static type const name[] = __VA_ARGS__;
1580template <
typename T>
1581inline T pgm_read(
const T* p ) {
1585template <
typename T>
1588 explicit pgm_ptr(
const T* ptr ) : ptr_( ptr ) {}
1589 T operator[]( intptr_t index )
const {
1590 return pgm_read( ptr_ + index );
1595template <
typename T,
size_t = sizeof( T )>
1596struct FloatTraits {};
1597template <
typename T>
1598struct FloatTraits<T, 8 > {
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(
1619 return pgm_ptr<T>(
reinterpret_cast<const T*
>(factors) );
1621 static pgm_ptr<T> negativeBinaryPowersOfTen() {
1622 ARDUINOJSON_DEFINE_PROGMEM_ARRAY(
1635 return pgm_ptr<T>(
reinterpret_cast<const T*
>(factors) );
1638 return forge( 0x7ff8000000000000 );
1641 return forge( 0x7ff0000000000000 );
1643 static T highest() {
1644 return forge( 0x7FEFFFFFFFFFFFFF );
1646 template <
typename TOut>
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 );
1653 template <
typename TOut>
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 );
1661 return forge( 0xFFEFFFFFFFFFFFFF );
1663 static T forge( uint64_t bits ) {
1664 return alias_cast<T>(bits);
1667template <
typename T>
1668struct FloatTraits<T, 4 > {
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,
1685 return pgm_ptr<T>(
reinterpret_cast<const T*
>(factors) );
1687 static pgm_ptr<T> negativeBinaryPowersOfTen() {
1688 ARDUINOJSON_DEFINE_PROGMEM_ARRAY( uint32_t, factors,
1697 return pgm_ptr<T>(
reinterpret_cast<const T*
>(factors) );
1699 static T forge( uint32_t bits ) {
1700 return alias_cast<T>(bits);
1703 return forge( 0x7fc00000 );
1706 return forge( 0x7f800000 );
1708 static T highest() {
1709 return forge( 0x7f7fffff );
1711 template <
typename TOut>
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 );
1718 template <
typename TOut>
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 );
1725 template <
typename TOut>
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 );
1732 template <
typename TOut>
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 );
1740 return forge( 0xFf7fffff );
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();
1749 e = TExponent( -e );
1750 for ( uint8_t index = 0; e != 0; index++ ) {
1752 m *= powersOfTen[index];
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 ),
1761 canConvertNumber( TIn value ) {
1762 return value <= TIn( numeric_limits<TOut>::highest() );
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 ),
1768 canConvertNumber( TIn ) {
1771template <
typename TOut,
typename TIn>
1772typename enable_if<is_integral<TIn>::value && is_floating_point<TOut>::value,
1774 canConvertNumber( TIn ) {
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 ),
1782 canConvertNumber( TIn value ) {
1783 return value >= TIn( numeric_limits<TOut>::lowest() ) &&
1784 value <= TIn( numeric_limits<TOut>::highest() );
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 ),
1791 canConvertNumber( TIn ) {
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 ),
1799 canConvertNumber( TIn value ) {
1802 return TOut( value ) <= numeric_limits<TOut>::highest();
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 ),
1809 canConvertNumber( TIn value ) {
1812 return value <= TIn( numeric_limits<TOut>::highest() );
1814template <
typename TOut,
typename TIn>
1815typename enable_if < is_floating_point<TIn>::value && is_integral<TOut>::value &&
1816 sizeof( TOut ) <
sizeof( TIn ),
1818 canConvertNumber( TIn value ) {
1819 return value >= numeric_limits<TOut>::lowest() &&
1820 value <= numeric_limits<TOut>::highest();
1822template <
typename TOut,
typename TIn>
1823typename enable_if<is_floating_point<TIn>::value && is_integral<TOut>::value &&
1824 sizeof( TOut ) >=
sizeof( TIn ),
1826 canConvertNumber( TIn value ) {
1827 return value >= numeric_limits<TOut>::lowest() &&
1828 value <= FloatTraits<TIn>::template highest_for<TOut>();
1830template <
typename TOut,
typename TIn>
1831TOut convertNumber( TIn value ) {
1832 return canConvertNumber<TOut>( value ) ? TOut( value ) : 0;
1834ARDUINOJSON_END_PRIVATE_NAMESPACE
1835#if defined(__clang__)
1836# pragma clang diagnostic pop
1837#elif defined(__GNUC__)
1838# pragma GCC diagnostic pop
1840ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
1842 VariantContent content_;
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) );
1850 template <
typename TVisitor>
1851 typename TVisitor::result_type accept( TVisitor& visitor )
const {
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 );
1874 return visitor.visitNull();
1877 template <
typename T>
1878 T asIntegral()
const;
1879 template <
typename T>
1881 JsonString asString()
const;
1882 bool asBoolean()
const;
1883 CollectionData* asArray() {
1884 return isArray() ? &content_.asCollection : 0;
1886 const CollectionData* asArray()
const {
1887 return const_cast<VariantData*
>(
this)->asArray();
1889 const CollectionData* asCollection()
const {
1890 return isCollection() ? &content_.asCollection : 0;
1892 CollectionData* asObject() {
1893 return isObject() ? &content_.asCollection : 0;
1895 const CollectionData* asObject()
const {
1896 return const_cast<VariantData*
>(
this)->asObject();
1898 bool copyFrom(
const VariantData& src, MemoryPool* pool );
1899 bool isArray()
const {
1900 return (flags_ & VALUE_IS_ARRAY) != 0;
1902 bool isBoolean()
const {
1903 return type() == VALUE_IS_BOOLEAN;
1905 bool isCollection()
const {
1906 return (flags_ & COLLECTION_MASK) != 0;
1908 template <
typename T>
1909 bool isInteger()
const {
1911 case VALUE_IS_UNSIGNED_INTEGER:
1912 return canConvertNumber<T>( content_.asUnsignedInteger );
1913 case VALUE_IS_SIGNED_INTEGER:
1914 return canConvertNumber<T>( content_.asSignedInteger );
1919 bool isFloat()
const {
1920 return (flags_ & NUMBER_BIT) != 0;
1922 bool isString()
const {
1923 return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
1925 bool isObject()
const {
1926 return (flags_ & VALUE_IS_OBJECT) != 0;
1928 bool isNull()
const {
1929 return type() == VALUE_IS_NULL;
1931 bool isEnclosed()
const {
1934 void remove(
size_t index ) {
1936 content_.asCollection.removeElement( index );
1938 template <
typename TAdaptedString>
1939 void remove( TAdaptedString key ) {
1941 content_.asCollection.removeMember( key );
1943 void setBoolean(
bool value ) {
1944 setType( VALUE_IS_BOOLEAN );
1945 content_.asBoolean = value;
1947 void setFloat( JsonFloat value ) {
1948 setType( VALUE_IS_FLOAT );
1949 content_.asFloat = value;
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();
1958 setType( VALUE_IS_NULL );
1961 template <
typename T>
1962 bool storeOwnedRaw( SerializedValue<T> value, MemoryPool* pool ) {
1963 const char* dup = pool->saveString( adaptString( value.data(), value.size() ) );
1965 setType( VALUE_IS_OWNED_RAW );
1966 content_.asString.data = dup;
1967 content_.asString.size = value.size();
1971 setType( VALUE_IS_NULL );
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);
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;
1986 setType( VALUE_IS_NULL );
1988 void setString( JsonString s ) {
1989 ARDUINOJSON_ASSERT( s );
1991 setType( VALUE_IS_LINKED_STRING );
1993 setType( VALUE_IS_OWNED_STRING );
1994 content_.asString.data = s.c_str();
1995 content_.asString.size = s.size();
1997 CollectionData& toArray() {
1998 setType( VALUE_IS_ARRAY );
1999 content_.asCollection.clear();
2000 return content_.asCollection;
2002 CollectionData& toObject() {
2003 setType( VALUE_IS_OBJECT );
2004 content_.asCollection.clear();
2005 return content_.asCollection;
2007 size_t memoryUsage()
const {
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();
2019 size_t size()
const {
2020 return isCollection() ? content_.asCollection.size() : 0;
2022 VariantData* addElement( MemoryPool* pool ) {
2027 return content_.asCollection.addElement( pool );
2029 VariantData* getElement(
size_t index )
const {
2030 const CollectionData* col = asArray();
2031 return col ? col->getElement( index ) : 0;
2033 VariantData* getOrAddElement(
size_t index, MemoryPool* pool ) {
2038 return content_.asCollection.getOrAddElement( index, pool );
2040 template <
typename TAdaptedString>
2041 VariantData* getMember( TAdaptedString key )
const {
2042 const CollectionData* col = asObject();
2043 return col ? col->getMember( key ) : 0;
2045 template <
typename TAdaptedString>
2046 VariantData* getOrAddMember( TAdaptedString key, MemoryPool* pool ) {
2051 return content_.asCollection.getOrAddMember( key, pool );
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 );
2059 uint8_t type()
const {
2060 return flags_ & VALUE_MASK;
2062 template <
typename TAdaptedString>
2063 inline bool setString( TAdaptedString value, MemoryPool* pool ) {
2064 if ( value.isNull() ) {
2068 return storeString( pool, value, VariantStringSetter(
this ) );
2071 void setType( uint8_t t ) {
2072 flags_ &= OWNED_KEY_BIT;
2075 struct VariantStringSetter {
2076 VariantStringSetter( VariantData* instance ) : instance_( instance ) {}
2077 template <
typename TStoredString>
2078 void operator()( TStoredString s ) {
2080 instance_->setString( s );
2082 instance_->setNull();
2084 VariantData* instance_;
2087template <
typename TResult>
2089 typedef TResult result_type;
2090 TResult visitArray(
const CollectionData& ) {
2093 TResult visitBoolean(
bool ) {
2096 TResult visitFloat( JsonFloat ) {
2099 TResult visitSignedInteger( JsonInteger ) {
2102 TResult visitNull() {
2105 TResult visitObject(
const CollectionData& ) {
2108 TResult visitUnsignedInteger( JsonUInt ) {
2111 TResult visitRawJson(
const char*,
size_t ) {
2114 TResult visitString(
const char*,
size_t ) {
2118template <
typename TVisitor>
2119inline typename TVisitor::result_type variantAccept(
const VariantData* var,
2120 TVisitor& visitor ) {
2122 return var->accept( visitor );
2124 return visitor.visitNull();
2126inline bool variantCopyFrom( VariantData* dst,
const VariantData* src,
2127 MemoryPool* pool ) {
2134 return dst->copyFrom( *src, pool );
2136inline void variantSetNull( VariantData* var ) {
2141template <
typename TAdaptedString>
2142inline bool variantSetString( VariantData* var, TAdaptedString value,
2143 MemoryPool* pool ) {
2144 return var != 0 ? var->setString( value, pool ) : 0;
2146inline size_t variantSize(
const VariantData* var ) {
2147 return var != 0 ? var->size() : 0;
2149inline CollectionData* variantToArray( VariantData* var ) {
2152 return &var->toArray();
2154inline CollectionData* variantToObject( VariantData* var ) {
2157 return &var->toObject();
2159inline VariantData* variantGetElement(
const VariantData* var,
size_t index ) {
2160 return var != 0 ? var->getElement( index ) : 0;
2162inline NO_INLINE VariantData* variantAddElement( VariantData* var,
2163 MemoryPool* pool ) {
2164 return var != 0 ? var->addElement( pool ) : 0;
2166inline NO_INLINE VariantData* variantGetOrAddElement( VariantData* var,
2168 MemoryPool* pool ) {
2169 return var != 0 ? var->getOrAddElement( index, pool ) : 0;
2171template <
typename TAdaptedString>
2172VariantData* variantGetMember(
const VariantData* var, TAdaptedString key ) {
2175 return var->getMember( key );
2177template <
typename TAdaptedString>
2178VariantData* variantGetOrAddMember( VariantData* var, TAdaptedString key,
2179 MemoryPool* pool ) {
2182 return var->getOrAddMember( key, pool );
2184inline bool variantIsNull(
const VariantData* var ) {
2185 return var == 0 || var->isNull();
2187inline size_t variantNesting(
const VariantData* var ) {
2190 const CollectionData* collection = var->asCollection();
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;
2199 return maxChildNesting + 1;
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
2209template <
typename T>
2210CompareResult arithmeticCompare(
const T& lhs,
const T& rhs ) {
2212 return COMPARE_RESULT_LESS;
2213 else if ( lhs > rhs )
2214 return COMPARE_RESULT_GREATER;
2216 return COMPARE_RESULT_EQUAL;
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 );
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) );
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) );
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 ) {
2247 return COMPARE_RESULT_GREATER;
2248 return arithmeticCompare<T1>( lhs,
static_cast<T1
>(rhs) );
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 ) {
2257 return COMPARE_RESULT_LESS;
2258 return arithmeticCompare<T2>(
static_cast<T2
>(lhs), rhs );
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) );
2268template <
typename T2>
2269CompareResult arithmeticCompareNegateLeft(
2270 JsonUInt,
const T2&,
2271 typename enable_if<is_unsigned<T2>::value>::type* = 0 ) {
2272 return COMPARE_RESULT_LESS;
2274template <
typename T2>
2275CompareResult arithmeticCompareNegateLeft(
2276 JsonUInt lhs,
const T2& rhs,
2277 typename enable_if<is_signed<T2>::value>::type* = 0 ) {
2279 return COMPARE_RESULT_LESS;
2280 return arithmeticCompare( -rhs,
static_cast<T2
>(lhs) );
2282template <
typename T1>
2283CompareResult arithmeticCompareNegateRight(
2284 const T1&, JsonUInt,
2285 typename enable_if<is_unsigned<T1>::value>::type* = 0 ) {
2286 return COMPARE_RESULT_GREATER;
2288template <
typename T1>
2289CompareResult arithmeticCompareNegateRight(
2290 const T1& lhs, JsonUInt rhs,
2291 typename enable_if<is_signed<T1>::value>::type* = 0 ) {
2293 return COMPARE_RESULT_GREATER;
2294 return arithmeticCompare(
static_cast<T1
>(rhs), -lhs );
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,
2307struct VariantOperatorTag {};
2308template <
typename TVariant>
2309struct VariantOperators : VariantOperatorTag {
2310 template <
typename T>
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>();
2317 return defaultValue;
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*>();
2324 return defaultValue;
2326 template <
typename T>
2327 friend typename enable_if<IsVariant<T>::value, JsonVariantConst>::type
2328 operator|(
const TVariant& variant, T defaultValue ) {
2332 return defaultValue;
2334 template <
typename T>
2335 friend bool operator==( T* lhs, TVariant rhs ) {
2336 return compare( rhs, lhs ) == COMPARE_RESULT_EQUAL;
2338 template <
typename T>
2339 friend bool operator==(
const T& lhs, TVariant rhs ) {
2340 return compare( rhs, lhs ) == COMPARE_RESULT_EQUAL;
2342 template <
typename T>
2343 friend bool operator==( TVariant lhs, T* rhs ) {
2344 return compare( lhs, rhs ) == COMPARE_RESULT_EQUAL;
2346 template <
typename T>
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;
2352 template <
typename T>
2353 friend bool operator!=( T* lhs, TVariant rhs ) {
2354 return compare( rhs, lhs ) != COMPARE_RESULT_EQUAL;
2356 template <
typename T>
2357 friend bool operator!=(
const T& lhs, TVariant rhs ) {
2358 return compare( rhs, lhs ) != COMPARE_RESULT_EQUAL;
2360 template <
typename T>
2361 friend bool operator!=( TVariant lhs, T* rhs ) {
2362 return compare( lhs, rhs ) != COMPARE_RESULT_EQUAL;
2364 template <
typename T>
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;
2370 template <
typename T>
2371 friend bool operator<( T* lhs, TVariant rhs ) {
2372 return compare( rhs, lhs ) == COMPARE_RESULT_GREATER;
2374 template <
typename T>
2375 friend bool operator<(
const T& lhs, TVariant rhs ) {
2376 return compare( rhs, lhs ) == COMPARE_RESULT_GREATER;
2378 template <
typename T>
2379 friend bool operator<( TVariant lhs, T* rhs ) {
2380 return compare( lhs, rhs ) == COMPARE_RESULT_LESS;
2382 template <
typename T>
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;
2388 template <
typename T>
2389 friend bool operator<=( T* lhs, TVariant rhs ) {
2390 return (compare( rhs, lhs ) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2392 template <
typename T>
2393 friend bool operator<=(
const T& lhs, TVariant rhs ) {
2394 return (compare( rhs, lhs ) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2396 template <
typename T>
2397 friend bool operator<=( TVariant lhs, T* rhs ) {
2398 return (compare( lhs, rhs ) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2400 template <
typename T>
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;
2406 template <
typename T>
2407 friend bool operator>( T* lhs, TVariant rhs ) {
2408 return compare( rhs, lhs ) == COMPARE_RESULT_LESS;
2410 template <
typename T>
2411 friend bool operator>(
const T& lhs, TVariant rhs ) {
2412 return compare( rhs, lhs ) == COMPARE_RESULT_LESS;
2414 template <
typename T>
2415 friend bool operator>( TVariant lhs, T* rhs ) {
2416 return compare( lhs, rhs ) == COMPARE_RESULT_GREATER;
2418 template <
typename T>
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;
2424 template <
typename T>
2425 friend bool operator>=( T* lhs, TVariant rhs ) {
2426 return (compare( rhs, lhs ) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2428 template <
typename T>
2429 friend bool operator>=(
const T& lhs, TVariant rhs ) {
2430 return (compare( rhs, lhs ) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
2432 template <
typename T>
2433 friend bool operator>=( TVariant lhs, T* rhs ) {
2434 return (compare( lhs, rhs ) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
2436 template <
typename T>
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;
2443ARDUINOJSON_END_PRIVATE_NAMESPACE
2444ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2447class JsonVariantConst :
public detail::VariantTag,
2448 public detail::VariantOperators<JsonVariantConst> {
2449 friend class detail::VariantAttorney;
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_ );
2457 FORCE_INLINE
bool isUnbound()
const {
2460 FORCE_INLINE
size_t memoryUsage()
const {
2461 return data_ ? data_->memoryUsage() : 0;
2463 FORCE_INLINE
size_t nesting()
const {
2464 return variantNesting( data_ );
2466 size_t size()
const {
2467 return variantSize( data_ );
2469 template <
typename T>
2470 FORCE_INLINE
typename detail::enable_if<!detail::is_same<T, char*>::value &&
2471 !detail::is_same<T, char>::value,
2474 return Converter<T>::fromJson( *
this );
2476 template <
typename T>
2477 FORCE_INLINE
typename detail::enable_if<!detail::is_same<T, char*>::value &&
2478 !detail::is_same<T, char>::value,
2481 return Converter<T>::checkJson( *
this );
2483 template <
typename T>
2484 FORCE_INLINE
operator T()
const {
2487 FORCE_INLINE JsonVariantConst operator[](
size_t index )
const {
2488 return JsonVariantConst( variantGetElement( data_, index ) );
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 ) ) );
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 ) ) );
2502 template <
typename TString>
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;
2508 template <
typename TChar>
2510 typename detail::enable_if<detail::IsString<TChar*>::value,
bool>::type
2511 containsKey( TChar* key )
const {
2512 return variantGetMember( getData(), detail::adaptString( key ) ) != 0;
2515 const detail::VariantData* getData()
const {
2519 const detail::VariantData* data_;
2522ARDUINOJSON_END_PUBLIC_NAMESPACE
2523ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
2526template <
typename,
typename>
2528template <
typename TDerived>
2529class VariantRefBase :
public VariantTag {
2530 friend class VariantAttorney;
2532 FORCE_INLINE
void clear()
const {
2533 variantSetNull( getData() );
2535 FORCE_INLINE
bool isNull()
const {
2536 return variantIsNull( getData() );
2538 FORCE_INLINE
bool isUnbound()
const {
2541 template <
typename T>
2543 typename enable_if<!ConverterNeedsWriteableRef<T>::value, T>::type
2545 return Converter<T>::fromJson( getVariantConst() );
2547 template <
typename T>
2548 FORCE_INLINE
typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
2550 template <
typename T,
2551 typename =
typename enable_if<!is_same<T, TDerived>::value>::type>
2552 FORCE_INLINE
operator T()
const {
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()
2560 template <
typename T>
2561 typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type to()
2563 template <
typename T>
2565 typename enable_if<ConverterNeedsWriteableRef<T>::value,
bool>::type
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,
2573 return Converter<T>::checkJson( getVariantConst() );
2575 FORCE_INLINE
void shallowCopy( ArduinoJson::JsonVariantConst target ) {
2576 VariantData* data = getOrCreateData();
2579 const VariantData* targetData = VariantAttorney::getData( target );
2581 *data = *targetData;
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() );
2592 FORCE_INLINE
size_t memoryUsage()
const {
2593 VariantData* data = getData();
2594 return data ? data->memoryUsage() : 0;
2596 FORCE_INLINE
size_t nesting()
const {
2597 return variantNesting( getData() );
2599 FORCE_INLINE JsonVariant add()
const;
2600 template <
typename T>
2601 FORCE_INLINE
bool add(
const T& value )
const {
2602 return add().set( value );
2604 template <
typename T>
2605 FORCE_INLINE
bool add( T* value )
const {
2606 return add().set( value );
2608 FORCE_INLINE
void remove(
size_t index )
const {
2609 VariantData* data = getData();
2611 data->remove( index );
2613 template <
typename TChar>
2614 FORCE_INLINE
typename enable_if<IsString<TChar*>::value>::type remove(
2615 TChar* key )
const {
2616 VariantData* data = getData();
2618 data->remove( adaptString( key ) );
2620 template <
typename TString>
2621 FORCE_INLINE
typename enable_if<IsString<TString>::value>::type remove(
2622 const TString& key )
const {
2623 VariantData* data = getData();
2625 data->remove( adaptString( key ) );
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;
2653 TDerived& derived() {
2654 return static_cast<TDerived&
>(*this);
2656 const TDerived& derived()
const {
2657 return static_cast<const TDerived&
>(*this);
2659 FORCE_INLINE MemoryPool* getPool()
const {
2660 return VariantAttorney::getPool( derived() );
2662 FORCE_INLINE VariantData* getData()
const {
2663 return VariantAttorney::getData( derived() );
2665 FORCE_INLINE VariantData* getOrCreateData()
const {
2666 return VariantAttorney::getOrCreateData( derived() );
2669 FORCE_INLINE ArduinoJson::JsonVariant getVariant()
const;
2670 FORCE_INLINE ArduinoJson::JsonVariantConst getVariantConst()
const {
2671 return ArduinoJson::JsonVariantConst( getData() );
2673 FORCE_INLINE ArduinoJson::JsonVariant getOrCreateVariant()
const;
2675template <
typename TUpstream>
2676class ElementProxy :
public VariantRefBase<ElementProxy<TUpstream>>,
2677 public VariantOperators<ElementProxy<TUpstream>> {
2678 friend class VariantAttorney;
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 ) {
2688 template <
typename T>
2689 FORCE_INLINE ElementProxy& operator=(
const T& src ) {
2693 template <
typename T>
2694 FORCE_INLINE ElementProxy& operator=( T* src ) {
2699 FORCE_INLINE MemoryPool* getPool()
const {
2700 return VariantAttorney::getPool( upstream_ );
2702 FORCE_INLINE VariantData* getData()
const {
2703 return variantGetElement( VariantAttorney::getData( upstream_ ), index_ );
2705 FORCE_INLINE VariantData* getOrCreateData()
const {
2706 return variantGetOrAddElement( VariantAttorney::getOrCreateData( upstream_ ),
2707 index_, VariantAttorney::getPool( upstream_ ) );
2709 TUpstream upstream_;
2712ARDUINOJSON_END_PRIVATE_NAMESPACE
2713ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2714class JsonVariant :
public detail::VariantRefBase<JsonVariant>,
2715 public detail::VariantOperators<JsonVariant> {
2716 friend class detail::VariantAttorney;
2718 JsonVariant() : data_( 0 ), pool_( 0 ) {}
2719 JsonVariant( detail::MemoryPool* pool, detail::VariantData* data )
2720 : data_( data ), pool_( pool ) {}
2722 FORCE_INLINE detail::MemoryPool* getPool()
const {
2725 FORCE_INLINE detail::VariantData* getData()
const {
2728 FORCE_INLINE detail::VariantData* getOrCreateData()
const {
2731 detail::VariantData* data_;
2732 detail::MemoryPool* pool_;
2735struct Converter<JsonVariant> :
private detail::VariantAttorney {
2736 static void toJson( JsonVariant src, JsonVariant dst ) {
2737 detail::variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
2739 static JsonVariant fromJson( JsonVariant src ) {
2742 static detail::InvalidConversion<JsonVariantConst, JsonVariant> fromJson(
2744 static bool checkJson( JsonVariant src ) {
2745 auto data = getData( src );
2748 static bool checkJson( JsonVariantConst ) {
2753struct Converter<JsonVariantConst> :
private detail::VariantAttorney {
2754 static void toJson( JsonVariantConst src, JsonVariant dst ) {
2755 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
2757 static JsonVariantConst fromJson( JsonVariantConst src ) {
2758 return JsonVariantConst( getData( src ) );
2760 static bool checkJson( JsonVariantConst src ) {
2761 auto data = getData( src );
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 ) {
2773 ARDUINOJSON_ASSERT( instance_ != 0 );
2774 instance_->setKey( s );
2776 VariantSlot* instance_;
2778template <
typename TAdaptedString>
2779inline bool slotSetKey( VariantSlot* var, TAdaptedString key, MemoryPool* pool ) {
2782 return storeString( pool, key, SlotKeySetter( var ) );
2784inline size_t slotSize(
const VariantSlot* var ) {
2792inline VariantData* slotData( VariantSlot* slot ) {
2793 return reinterpret_cast<VariantData*
>(slot);
2795ARDUINOJSON_END_PRIVATE_NAMESPACE
2796ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
2799 VariantPtr( detail::MemoryPool* pool, detail::VariantData* data )
2800 : variant_( pool, data ) {}
2801 JsonVariant* operator->() {
2804 JsonVariant& operator*() {
2808 JsonVariant variant_;
2810class JsonArrayIterator {
2811 friend class JsonArray;
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() );
2820 VariantPtr operator->() {
2821 return VariantPtr( pool_, slot_->data() );
2823 bool operator==(
const JsonArrayIterator& other )
const {
2824 return slot_ == other.slot_;
2826 bool operator!=(
const JsonArrayIterator& other )
const {
2827 return slot_ != other.slot_;
2829 JsonArrayIterator& operator++() {
2830 slot_ = slot_->next();
2833 JsonArrayIterator& operator+=(
size_t distance ) {
2834 slot_ = slot_->next( distance );
2838 detail::MemoryPool* pool_;
2839 detail::VariantSlot* slot_;
2841class VariantConstPtr {
2843 VariantConstPtr(
const detail::VariantData* data ) : variant_( data ) {}
2844 JsonVariantConst* operator->() {
2847 JsonVariantConst& operator*() {
2851 JsonVariantConst variant_;
2853class JsonArrayConstIterator {
2854 friend class JsonArray;
2856 JsonArrayConstIterator() : slot_( 0 ) {}
2857 explicit JsonArrayConstIterator(
const detail::VariantSlot* slot )
2859 JsonVariantConst operator*()
const {
2860 return JsonVariantConst( slot_->data() );
2862 VariantConstPtr operator->() {
2863 return VariantConstPtr( slot_->data() );
2865 bool operator==(
const JsonArrayConstIterator& other )
const {
2866 return slot_ == other.slot_;
2868 bool operator!=(
const JsonArrayConstIterator& other )
const {
2869 return slot_ != other.slot_;
2871 JsonArrayConstIterator& operator++() {
2872 slot_ = slot_->next();
2875 JsonArrayConstIterator& operator+=(
size_t distance ) {
2876 slot_ = slot_->next( distance );
2880 const detail::VariantSlot* slot_;
2883class JsonArrayConst :
public detail::VariantOperators<JsonArrayConst> {
2884 friend class JsonArray;
2885 friend class detail::VariantAttorney;
2887 typedef JsonArrayConstIterator iterator;
2888 FORCE_INLINE iterator begin()
const {
2891 return iterator( data_->head() );
2893 FORCE_INLINE iterator end()
const {
2896 FORCE_INLINE JsonArrayConst() : data_( 0 ) {}
2897 FORCE_INLINE JsonArrayConst(
const detail::CollectionData* data )
2899 FORCE_INLINE
bool operator==( JsonArrayConst rhs )
const {
2900 if ( data_ == rhs.data_ )
2902 if ( !data_ || !rhs.data_ )
2904 iterator it1 = begin();
2905 iterator it2 = rhs.begin();
2907 bool end1 = it1 == end();
2908 bool end2 = it2 == rhs.end();
2919 FORCE_INLINE JsonVariantConst operator[](
size_t index )
const {
2920 return JsonVariantConst( data_ ? data_->getElement( index ) : 0 );
2922 operator JsonVariantConst()
const {
2923 return JsonVariantConst( collectionToVariant( data_ ) );
2925 FORCE_INLINE
bool isNull()
const {
2928 FORCE_INLINE
operator bool()
const {
2931 FORCE_INLINE
size_t memoryUsage()
const {
2932 return data_ ? data_->memoryUsage() : 0;
2934 FORCE_INLINE
size_t nesting()
const {
2935 return variantNesting( collectionToVariant( data_ ) );
2937 FORCE_INLINE
size_t size()
const {
2938 return data_ ? data_->size() : 0;
2941 const detail::VariantData* getData()
const {
2942 return collectionToVariant( data_ );
2944 const detail::CollectionData* data_;
2947struct Converter<JsonArrayConst> :
private detail::VariantAttorney {
2948 static void toJson( JsonVariantConst src, JsonVariant dst ) {
2949 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
2951 static JsonArrayConst fromJson( JsonVariantConst src ) {
2952 auto data = getData( src );
2953 return data ? data->asArray() : 0;
2955 static bool checkJson( JsonVariantConst src ) {
2956 auto data = getData( src );
2957 return data && data->isArray();
2961class JsonArray :
public detail::VariantOperators<JsonArray> {
2962 friend class detail::VariantAttorney;
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() {
2970 return JsonVariant( pool_,
reinterpret_cast<detail::VariantData*
>(data) );
2972 operator JsonArrayConst()
const {
2973 return JsonArrayConst( data_ );
2975 JsonVariant add()
const {
2977 return JsonVariant();
2978 return JsonVariant( pool_, data_->addElement( pool_ ) );
2980 template <
typename T>
2981 FORCE_INLINE
bool add(
const T& value )
const {
2982 return add().set( value );
2984 template <
typename T>
2985 FORCE_INLINE
bool add( T* value )
const {
2986 return add().set( value );
2988 FORCE_INLINE iterator begin()
const {
2991 return iterator( pool_, data_->head() );
2993 FORCE_INLINE iterator end()
const {
2996 FORCE_INLINE
bool set( JsonArrayConst src )
const {
2997 if ( !data_ || !src.data_ )
2999 return data_->copyFrom( *src.data_, pool_ );
3001 FORCE_INLINE
bool operator==( JsonArray rhs )
const {
3002 return JsonArrayConst( data_ ) == JsonArrayConst( rhs.data_ );
3004 FORCE_INLINE
void remove( iterator it )
const {
3007 data_->removeSlot( it.slot_ );
3009 FORCE_INLINE
void remove(
size_t index )
const {
3012 data_->removeElement( index );
3014 void clear()
const {
3019 FORCE_INLINE detail::ElementProxy<JsonArray> operator[](
size_t index )
const {
3020 return { *
this, index };
3022 FORCE_INLINE JsonObject createNestedObject()
const;
3023 FORCE_INLINE JsonArray createNestedArray()
const {
3024 return add().to<JsonArray>();
3026 operator JsonVariantConst()
const {
3027 return JsonVariantConst( collectionToVariant( data_ ) );
3029 FORCE_INLINE
bool isNull()
const {
3032 FORCE_INLINE
operator bool()
const {
3035 FORCE_INLINE
size_t memoryUsage()
const {
3036 return data_ ? data_->memoryUsage() : 0;
3038 FORCE_INLINE
size_t nesting()
const {
3039 return variantNesting( collectionToVariant( data_ ) );
3041 FORCE_INLINE
size_t size()
const {
3042 return data_ ? data_->size() : 0;
3045 detail::MemoryPool* getPool()
const {
3048 detail::VariantData* getData()
const {
3049 return collectionToVariant( data_ );
3051 detail::VariantData* getOrCreateData()
const {
3052 return collectionToVariant( data_ );
3054 detail::CollectionData* data_;
3055 detail::MemoryPool* pool_;
3058struct Converter<JsonArray> :
private detail::VariantAttorney {
3059 static void toJson( JsonVariantConst src, JsonVariant dst ) {
3060 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
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 );
3067 static detail::InvalidConversion<JsonVariantConst, JsonArray> fromJson(
3069 static bool checkJson( JsonVariantConst ) {
3072 static bool checkJson( JsonVariant src ) {
3073 auto data = getData( src );
3074 return data && data->isArray();
3079 JsonPair( detail::MemoryPool* pool, detail::VariantSlot* slot ) {
3081 key_ = JsonString( slot->key(), slot->ownsKey() ? JsonString::Copied
3082 : JsonString::Linked );
3083 value_ = JsonVariant( pool, slot->data() );
3086 JsonString key()
const {
3089 JsonVariant value()
const {
3096class JsonPairConst {
3098 JsonPairConst(
const detail::VariantSlot* slot ) {
3100 key_ = JsonString( slot->key(), slot->ownsKey() ? JsonString::Copied
3101 : JsonString::Linked );
3102 value_ = JsonVariantConst( slot->data() );
3105 JsonString key()
const {
3108 JsonVariantConst value()
const {
3113 JsonVariantConst value_;
3117 JsonPairPtr( detail::MemoryPool* pool, detail::VariantSlot* slot )
3118 : pair_( pool, slot ) {}
3119 const JsonPair* operator->()
const {
3122 const JsonPair& operator*()
const {
3128class JsonObjectIterator {
3129 friend class JsonObject;
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_ );
3138 JsonPairPtr operator->() {
3139 return JsonPairPtr( pool_, slot_ );
3141 bool operator==(
const JsonObjectIterator& other )
const {
3142 return slot_ == other.slot_;
3144 bool operator!=(
const JsonObjectIterator& other )
const {
3145 return slot_ != other.slot_;
3147 JsonObjectIterator& operator++() {
3148 slot_ = slot_->next();
3151 JsonObjectIterator& operator+=(
size_t distance ) {
3152 slot_ = slot_->next( distance );
3156 detail::MemoryPool* pool_;
3157 detail::VariantSlot* slot_;
3159class JsonPairConstPtr {
3161 JsonPairConstPtr(
const detail::VariantSlot* slot ) : pair_( slot ) {}
3162 const JsonPairConst* operator->()
const {
3165 const JsonPairConst& operator*()
const {
3169 JsonPairConst pair_;
3171class JsonObjectConstIterator {
3172 friend class JsonObject;
3174 JsonObjectConstIterator() : slot_( 0 ) {}
3175 explicit JsonObjectConstIterator(
const detail::VariantSlot* slot )
3177 JsonPairConst operator*()
const {
3178 return JsonPairConst( slot_ );
3180 JsonPairConstPtr operator->() {
3181 return JsonPairConstPtr( slot_ );
3183 bool operator==(
const JsonObjectConstIterator& other )
const {
3184 return slot_ == other.slot_;
3186 bool operator!=(
const JsonObjectConstIterator& other )
const {
3187 return slot_ != other.slot_;
3189 JsonObjectConstIterator& operator++() {
3190 slot_ = slot_->next();
3193 JsonObjectConstIterator& operator+=(
size_t distance ) {
3194 slot_ = slot_->next( distance );
3198 const detail::VariantSlot* slot_;
3200class JsonObjectConst :
public detail::VariantOperators<JsonObjectConst> {
3201 friend class JsonObject;
3202 friend class detail::VariantAttorney;
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_ ) );
3210 FORCE_INLINE
bool isNull()
const {
3213 FORCE_INLINE
operator bool()
const {
3216 FORCE_INLINE
size_t memoryUsage()
const {
3217 return data_ ? data_->memoryUsage() : 0;
3219 FORCE_INLINE
size_t nesting()
const {
3220 return variantNesting( collectionToVariant( data_ ) );
3222 FORCE_INLINE
size_t size()
const {
3223 return data_ ? data_->size() : 0;
3225 FORCE_INLINE iterator begin()
const {
3228 return iterator( data_->head() );
3230 FORCE_INLINE iterator end()
const {
3233 template <
typename TString>
3234 FORCE_INLINE
bool containsKey(
const TString& key )
const {
3235 return getMember( detail::adaptString( key ) ) != 0;
3237 template <
typename TChar>
3238 FORCE_INLINE
bool containsKey( TChar* key )
const {
3239 return getMember( detail::adaptString( key ) ) != 0;
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 ) ) );
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 ) ) );
3253 FORCE_INLINE
bool operator==( JsonObjectConst rhs )
const {
3254 if ( data_ == rhs.data_ )
3256 if ( !data_ || !rhs.data_ )
3259 for ( iterator it = begin(); it != end(); ++it ) {
3260 if ( it->value() != rhs[it->key()] )
3264 return count == rhs.size();
3267 const detail::VariantData* getData()
const {
3268 return collectionToVariant( data_ );
3270 template <
typename TAdaptedString>
3271 const detail::VariantData* getMember( TAdaptedString key )
const {
3274 return data_->getMember( key );
3276 const detail::CollectionData* data_;
3279struct Converter<JsonObjectConst> :
private detail::VariantAttorney {
3280 static void toJson( JsonVariantConst src, JsonVariant dst ) {
3281 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
3283 static JsonObjectConst fromJson( JsonVariantConst src ) {
3284 auto data = getData( src );
3285 return data != 0 ? data->asObject() : 0;
3287 static bool checkJson( JsonVariantConst src ) {
3288 auto data = getData( src );
3289 return data && data->isObject();
3292ARDUINOJSON_END_PUBLIC_NAMESPACE
3293ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
3294template <
typename TUpstream,
typename TStringRef>
3296 :
public VariantRefBase<MemberProxy<TUpstream, TStringRef>>,
3297 public VariantOperators<MemberProxy<TUpstream, TStringRef>> {
3298 friend class VariantAttorney;
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 ) {
3308 template <
typename T>
3309 FORCE_INLINE MemberProxy& operator=(
const T& src ) {
3313 template <
typename T>
3314 FORCE_INLINE MemberProxy& operator=( T* src ) {
3319 FORCE_INLINE MemoryPool* getPool()
const {
3320 return VariantAttorney::getPool( upstream_ );
3322 FORCE_INLINE VariantData* getData()
const {
3323 return variantGetMember( VariantAttorney::getData( upstream_ ),
3324 adaptString( key_ ) );
3326 FORCE_INLINE VariantData* getOrCreateData()
const {
3327 return variantGetOrAddMember( VariantAttorney::getOrCreateData( upstream_ ),
3328 adaptString( key_ ),
3329 VariantAttorney::getPool( upstream_ ) );
3332 TUpstream upstream_;
3335ARDUINOJSON_END_PRIVATE_NAMESPACE
3336ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
3338class JsonObject :
public detail::VariantOperators<JsonObject> {
3339 friend class detail::VariantAttorney;
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 {
3347 return JsonVariant( pool_,
reinterpret_cast<detail::VariantData*
>(data) );
3349 operator JsonObjectConst()
const {
3350 return JsonObjectConst( data_ );
3352 operator JsonVariantConst()
const {
3353 return JsonVariantConst( collectionToVariant( data_ ) );
3355 FORCE_INLINE
bool isNull()
const {
3358 FORCE_INLINE
operator bool()
const {
3361 FORCE_INLINE
size_t memoryUsage()
const {
3362 return data_ ? data_->memoryUsage() : 0;
3364 FORCE_INLINE
size_t nesting()
const {
3365 return variantNesting( collectionToVariant( data_ ) );
3367 FORCE_INLINE
size_t size()
const {
3368 return data_ ? data_->size() : 0;
3370 FORCE_INLINE iterator begin()
const {
3373 return iterator( pool_, data_->head() );
3375 FORCE_INLINE iterator end()
const {
3378 void clear()
const {
3383 FORCE_INLINE
bool set( JsonObjectConst src ) {
3384 if ( !data_ || !src.data_ )
3386 return data_->copyFrom( *src.data_, pool_ );
3388 FORCE_INLINE
bool operator==( JsonObject rhs )
const {
3389 return JsonObjectConst( data_ ) == JsonObjectConst( rhs.data_ );
3391 template <
typename TString>
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 };
3398 template <
typename TChar>
3400 typename detail::enable_if<detail::IsString<TChar*>::value,
3401 detail::MemberProxy<JsonObject, TChar*>>::type
3402 operator[]( TChar* key )
const {
3403 return { *
this, key };
3405 FORCE_INLINE
void remove( iterator it )
const {
3408 data_->removeSlot( it.slot_ );
3410 template <
typename TString>
3411 FORCE_INLINE
void remove(
const TString& key )
const {
3412 removeMember( detail::adaptString( key ) );
3414 template <
typename TChar>
3415 FORCE_INLINE
void remove( TChar* key )
const {
3416 removeMember( detail::adaptString( key ) );
3418 template <
typename TString>
3420 typename detail::enable_if<detail::IsString<TString>::value,
bool>::type
3421 containsKey(
const TString& key )
const {
3422 return getMember( detail::adaptString( key ) ) != 0;
3424 template <
typename TChar>
3426 typename detail::enable_if<detail::IsString<TChar*>::value,
bool>::type
3427 containsKey( TChar* key )
const {
3428 return getMember( detail::adaptString( key ) ) != 0;
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>();
3438 template <
typename TChar>
3439 JsonObject createNestedObject( TChar* key )
const {
3440 return operator[]( key ).template to<JsonObject>();
3443 detail::MemoryPool* getPool()
const {
3446 detail::VariantData* getData()
const {
3447 return detail::collectionToVariant( data_ );
3449 detail::VariantData* getOrCreateData()
const {
3450 return detail::collectionToVariant( data_ );
3452 template <
typename TAdaptedString>
3453 inline detail::VariantData* getMember( TAdaptedString key )
const {
3456 return data_->getMember( key );
3458 template <
typename TAdaptedString>
3459 void removeMember( TAdaptedString key )
const {
3462 data_->removeMember( key );
3464 detail::CollectionData* data_;
3465 detail::MemoryPool* pool_;
3468struct Converter<JsonObject> :
private detail::VariantAttorney {
3469 static void toJson( JsonVariantConst src, JsonVariant dst ) {
3470 variantCopyFrom( getData( dst ), getData( src ), getPool( dst ) );
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 );
3477 static detail::InvalidConversion<JsonVariantConst, JsonObject> fromJson(
3479 static bool checkJson( JsonVariantConst ) {
3482 static bool checkJson( JsonVariant src ) {
3483 auto data = getData( src );
3484 return data && data->isObject();
3487class JsonDocument :
public detail::VariantOperators<const JsonDocument&> {
3488 friend class detail::VariantAttorney;
3490 JsonDocument(
const JsonDocument& ) =
delete;
3491 JsonDocument& operator=(
const JsonDocument& ) =
delete;
3492 template <
typename T>
3494 return getVariant().template as<T>();
3496 template <
typename T>
3498 return getVariant().template as<T>();
3504 template <
typename T>
3506 return getVariant().template is<T>();
3508 template <
typename T>
3510 return getVariant().template is<T>();
3512 bool isNull()
const {
3513 return getVariant().isNull();
3515 size_t memoryUsage()
const {
3516 return pool_.size();
3518 bool overflowed()
const {
3519 return pool_.overflowed();
3521 size_t nesting()
const {
3522 return variantNesting( &data_ );
3524 size_t capacity()
const {
3525 return pool_.capacity();
3527 size_t size()
const {
3528 return data_.size();
3530 bool set(
const JsonDocument& src ) {
3531 return to<JsonVariant>().set( src.as<JsonVariantConst>() );
3533 template <
typename T>
3534 typename detail::enable_if<!detail::is_base_of<JsonDocument, T>::value,
3536 set(
const T& src ) {
3537 return to<JsonVariant>().set( src );
3539 template <
typename T>
3540 typename detail::VariantTo<T>::type to() {
3542 return getVariant().template to<T>();
3544 JsonArray createNestedArray() {
3545 return add().to<JsonArray>();
3547 template <
typename TChar>
3548 JsonArray createNestedArray( TChar* key ) {
3549 return operator[]( key ).template to<JsonArray>();
3551 template <
typename TString>
3552 JsonArray createNestedArray(
const TString& key ) {
3553 return operator[]( key ).template to<JsonArray>();
3555 JsonObject createNestedObject() {
3556 return add().to<JsonObject>();
3558 template <
typename TChar>
3559 JsonObject createNestedObject( TChar* key ) {
3560 return operator[]( key ).template to<JsonObject>();
3562 template <
typename TString>
3563 JsonObject createNestedObject(
const TString& key ) {
3564 return operator[]( key ).template to<JsonObject>();
3566 template <
typename TChar>
3567 bool containsKey( TChar* key )
const {
3568 return data_.getMember( detail::adaptString( key ) ) != 0;
3570 template <
typename TString>
3571 bool containsKey(
const TString& key )
const {
3572 return data_.getMember( detail::adaptString( key ) ) != 0;
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 };
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 };
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 ) ) );
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 ) ) );
3600 FORCE_INLINE detail::ElementProxy<JsonDocument&> operator[](
size_t index ) {
3601 return { *
this, index };
3603 FORCE_INLINE JsonVariantConst operator[](
size_t index )
const {
3604 return JsonVariantConst( data_.getElement( index ) );
3606 FORCE_INLINE JsonVariant add() {
3607 return JsonVariant( &pool_, data_.addElement( &pool_ ) );
3609 template <
typename TValue>
3610 FORCE_INLINE
bool add(
const TValue& value ) {
3611 return add().set( value );
3613 template <
typename TChar>
3614 FORCE_INLINE
bool add( TChar* value ) {
3615 return add().set( value );
3617 FORCE_INLINE
void remove(
size_t index ) {
3618 data_.remove( index );
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 ) );
3625 template <
typename TString>
3627 typename detail::enable_if<detail::IsString<TString>::value>::type
3628 remove(
const TString& key ) {
3629 data_.remove( detail::adaptString( key ) );
3631 FORCE_INLINE
operator JsonVariant() {
3632 return getVariant();
3634 FORCE_INLINE
operator JsonVariantConst()
const {
3635 return getVariant();
3638 JsonDocument() : pool_( 0, 0 ) {}
3639 JsonDocument( detail::MemoryPool pool ) : pool_( pool ) {}
3640 JsonDocument(
char* buf,
size_t capa ) : pool_( buf, capa ) {}
3642 void replacePool( detail::MemoryPool pool ) {
3645 JsonVariant getVariant() {
3646 return JsonVariant( &pool_, &data_ );
3648 JsonVariantConst getVariant()
const {
3649 return JsonVariantConst( &data_ );
3651 detail::MemoryPool pool_;
3652 detail::VariantData data_;
3654 detail::MemoryPool* getPool() {
3657 detail::VariantData* getData() {
3660 const detail::VariantData* getData()
const {
3663 detail::VariantData* getOrCreateData() {
3667inline void convertToJson(
const JsonDocument& src, JsonVariant dst ) {
3668 dst.set( src.as<JsonVariantConst>() );
3670template <
typename TAllocator>
3671class AllocatorOwner {
3674 AllocatorOwner( TAllocator a ) : allocator_( a ) {}
3675 void* allocate(
size_t size ) {
3676 return allocator_.allocate( size );
3678 void deallocate(
void* ptr ) {
3680 allocator_.deallocate( ptr );
3682 void* reallocate(
void* ptr,
size_t new_size ) {
3683 return allocator_.reallocate( ptr, new_size );
3685 TAllocator& allocator() {
3689 TAllocator allocator_;
3691template <
typename TAllocator>
3692class BasicJsonDocument : AllocatorOwner<TAllocator>,
public JsonDocument {
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 );
3700 BasicJsonDocument( BasicJsonDocument&& src ) : AllocatorOwner<TAllocator>( src ) {
3701 moveAssignFrom( src );
3703 BasicJsonDocument(
const JsonDocument& src ) {
3704 copyAssignFrom( src );
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() ) ) {
3718 BasicJsonDocument( JsonVariant src )
3719 : JsonDocument( allocPool( src.memoryUsage() ) ) {
3722 ~BasicJsonDocument() {
3725 BasicJsonDocument& operator=(
const BasicJsonDocument& src ) {
3726 copyAssignFrom( src );
3729 BasicJsonDocument& operator=( BasicJsonDocument&& src ) {
3730 moveAssignFrom( src );
3733 template <
typename T>
3734 BasicJsonDocument& operator=(
const T& src ) {
3735 size_t requiredSize = src.memoryUsage();
3736 if ( requiredSize > capacity() )
3737 reallocPool( requiredSize );
3741 void shrinkToFit() {
3742 ptrdiff_t bytes_reclaimed = pool_.squash();
3743 if ( bytes_reclaimed == 0 )
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 );
3752 bool garbageCollect() {
3753 BasicJsonDocument tmp( *
this );
3754 if ( !tmp.capacity() )
3756 moveAssignFrom( tmp );
3759 using AllocatorOwner<TAllocator>::allocator;
3761 detail::MemoryPool allocPool(
size_t requiredSize ) {
3762 size_t capa = detail::addPadding( requiredSize );
3763 return {
reinterpret_cast<char*
>(this->allocate( capa )), capa };
3765 void reallocPool(
size_t requiredSize ) {
3766 size_t capa = detail::addPadding( requiredSize );
3767 if ( capa == pool_.capacity() )
3770 replacePool( allocPool( detail::addPadding( requiredSize ) ) );
3773 this->deallocate( getPool()->buffer() );
3775 void copyAssignFrom(
const JsonDocument& src ) {
3776 reallocPool( src.capacity() );
3779 void moveAssignFrom( BasicJsonDocument& src ) {
3783 src.data_.setNull();
3784 src.pool_ ={ 0, 0 };
3787struct DefaultAllocator {
3788 void* allocate(
size_t size ) {
3789 return malloc( size );
3791 void deallocate(
void* ptr ) {
3794 void* reallocate(
void* ptr,
size_t new_size ) {
3795 return realloc( ptr, new_size );
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;
3804 StaticJsonDocument() : JsonDocument( buffer_, capacity_ ) {}
3805 StaticJsonDocument(
const StaticJsonDocument& src )
3806 : JsonDocument( buffer_, capacity_ ) {
3809 template <
typename T>
3812 typename detail::enable_if<
3813 detail::is_convertible<T, JsonVariantConst>::value>::type* = 0 )
3814 : JsonDocument( buffer_, capacity_ ) {
3817 StaticJsonDocument( JsonVariant src ) : JsonDocument( buffer_, capacity_ ) {
3820 StaticJsonDocument& operator=(
const StaticJsonDocument& src ) {
3824 template <
typename T>
3825 StaticJsonDocument& operator=(
const T& src ) {
3829 void garbageCollect() {
3830 StaticJsonDocument tmp( *
this );
3834 char buffer_[capacity_];
3836inline JsonObject JsonArray::createNestedObject()
const {
3837 return add().to<JsonObject>();
3839ARDUINOJSON_END_PUBLIC_NAMESPACE
3840ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
3841template <
typename TDerived>
3842inline JsonArray VariantRefBase<TDerived>::createNestedArray()
const {
3843 return add().template to<JsonArray>();
3845template <
typename TDerived>
3846inline JsonObject VariantRefBase<TDerived>::createNestedObject()
const {
3847 return add().template to<JsonObject>();
3849template <
typename TDerived>
3850inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
3851 size_t index )
const {
3852 return ElementProxy<TDerived>( derived(), index );
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 );
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 );
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 ) {
3872 for (
size_t i = 0; i < len; i++ ) {
3873 ok &= copyArray( src[i], dst.add() );
3877template <
typename TDestination>
3878inline bool copyArray(
const char* src,
size_t,
const TDestination& dst ) {
3879 return dst.set( src );
3881template <
typename T>
3882inline bool copyArray(
const T& src, JsonDocument& dst ) {
3883 return copyArray( src, dst.to<JsonArray>() );
3885template <
typename T>
3886inline bool copyArray(
const T* src,
size_t len, JsonDocument& dst ) {
3887 return copyArray( src, len, dst.to<JsonArray>() );
3889template <
typename T>
3890inline typename detail::enable_if<!detail::is_array<T>::value,
size_t>::type
3891copyArray( JsonVariantConst src, T& dst ) {
3895template <
typename T,
size_t N>
3896inline size_t copyArray( JsonArrayConst src, T( &dst )[N] ) {
3897 return copyArray( src, dst, N );
3899template <
typename T>
3900inline size_t copyArray( JsonArrayConst src, T* dst,
size_t len ) {
3902 for ( JsonArrayConst::iterator it = src.begin(); it != src.end() && i < len;
3904 copyArray( *it, dst[i++] );
3908inline size_t copyArray( JsonVariantConst src,
char( &dst )[N] ) {
3911 if ( len > s.size() )
3913 memcpy( dst, s.c_str(), len );
3917template <
typename TSource,
typename T>
3918inline typename detail::enable_if<
3919 detail::is_array<T>::value &&
3920 detail::is_base_of<JsonDocument, TSource>::value,
3922 copyArray(
const TSource& src, T& dst ) {
3923 return copyArray( src.template as<JsonArrayConst>(), dst );
3925ARDUINOJSON_END_PUBLIC_NAMESPACE
3926ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
3927inline VariantSlot* CollectionData::addSlot( MemoryPool* pool ) {
3928 VariantSlot* slot = pool->allocVariant();
3932 ARDUINOJSON_ASSERT( pool->owns( tail_ ) );
3933 tail_->setNextNotNull( slot );
3943inline VariantData* CollectionData::addElement( MemoryPool* pool ) {
3944 return slotData( addSlot( pool ) );
3946template <
typename TAdaptedString>
3947inline VariantData* CollectionData::addMember( TAdaptedString key,
3948 MemoryPool* pool ) {
3949 VariantSlot* slot = addSlot( pool );
3950 if ( !slotSetKey( slot, key, pool ) ) {
3954 return slot->data();
3956inline void CollectionData::clear() {
3960template <
typename TAdaptedString>
3961inline bool CollectionData::containsKey(
const TAdaptedString& key )
const {
3962 return getSlot( key ) != 0;
3964inline bool CollectionData::copyFrom(
const CollectionData& src,
3965 MemoryPool* pool ) {
3967 for ( VariantSlot* s = src.head_; s; s = s->next() ) {
3969 if ( s->key() != 0 ) {
3970 JsonString key( s->key(),
3971 s->ownsKey() ? JsonString::Copied : JsonString::Linked );
3972 var = addMember( adaptString( key ), pool );
3975 var = addElement( pool );
3979 if ( !var->copyFrom( *s->data(), pool ) )
3984template <
typename TAdaptedString>
3985inline VariantSlot* CollectionData::getSlot( TAdaptedString key )
const {
3988 VariantSlot* slot = head_;
3990 if ( stringEquals( key, adaptString( slot->key() ) ) )
3992 slot = slot->next();
3996inline VariantSlot* CollectionData::getSlot(
size_t index )
const {
3999 return head_->next( index );
4001inline VariantSlot* CollectionData::getPreviousSlot( VariantSlot* target )
const {
4002 VariantSlot* current = head_;
4004 VariantSlot* next = current->next();
4005 if ( next == target )
4011template <
typename TAdaptedString>
4012inline VariantData* CollectionData::getMember( TAdaptedString key )
const {
4013 VariantSlot* slot = getSlot( key );
4014 return slot ? slot->data() : 0;
4016template <
typename TAdaptedString>
4017inline VariantData* CollectionData::getOrAddMember( TAdaptedString key,
4018 MemoryPool* pool ) {
4021 VariantSlot* slot = getSlot( key );
4023 return slot->data();
4024 return addMember( key, pool );
4026inline VariantData* CollectionData::getElement(
size_t index )
const {
4027 VariantSlot* slot = getSlot( index );
4028 return slot ? slot->data() : 0;
4030inline VariantData* CollectionData::getOrAddElement(
size_t index,
4031 MemoryPool* pool ) {
4032 VariantSlot* slot = head_;
4033 while ( slot && index > 0 ) {
4034 slot = slot->next();
4039 while ( index > 0 ) {
4040 slot = addSlot( pool );
4043 return slotData( slot );
4045inline void CollectionData::removeSlot( VariantSlot* slot ) {
4048 VariantSlot* prev = getPreviousSlot( slot );
4049 VariantSlot* next = slot->next();
4051 prev->setNext( next );
4057inline void CollectionData::removeElement(
size_t index ) {
4058 removeSlot( getSlot( index ) );
4060inline size_t CollectionData::memoryUsage()
const {
4062 for ( VariantSlot* s = head_; s; s = s->next() ) {
4063 total +=
sizeof( VariantSlot ) + s->data()->memoryUsage();
4065 total += strlen( s->key() ) + 1;
4069inline size_t CollectionData::size()
const {
4070 return slotSize( head_ );
4072template <
typename T>
4073inline void movePointer( T*& p, ptrdiff_t offset ) {
4076 p =
reinterpret_cast<T*
>(
4077 reinterpret_cast<void*
>(
reinterpret_cast<char*
>(p) + offset));
4078 ARDUINOJSON_ASSERT( isAligned( p ) );
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 );
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>();
4093template <
typename TChar>
4094inline JsonArray JsonObject::createNestedArray( TChar* key )
const {
4095 return operator[]( key ).template to<JsonArray>();
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>();
4105template <
typename TDerived>
4106template <
typename TChar>
4107inline JsonArray VariantRefBase<TDerived>::createNestedArray( TChar* key )
const {
4108 return operator[]( key ).template to<JsonArray>();
4110template <
typename TDerived>
4111template <
typename TString>
4112inline JsonObject VariantRefBase<TDerived>::createNestedObject(
4113 const TString& key )
const {
4114 return operator[]( key ).template to<JsonObject>();
4116template <
typename TDerived>
4117template <
typename TChar>
4118inline JsonObject VariantRefBase<TDerived>::createNestedObject(
4119 TChar* key )
const {
4120 return operator[]( key ).template to<JsonObject>();
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;
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;
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 );
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 );
4150class EscapeSequence {
4152 static char escapeChar(
char c ) {
4153 const char* p = escapeTable(
true );
4154 while ( p[0] && p[1] != c ) {
4159 static char unescapeChar(
char c ) {
4160 const char* p = escapeTable(
false );
4170 static const char* escapeTable(
bool excludeSolidus ) {
4171 return &
"//\"\"\\\\b\bf\fn\nr\rt\t"[excludeSolidus ? 2 : 0];
4174template <
typename TFloat>
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;
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 ) {
4196 if ( exponent && integral >= 10 ) {
4201 while ( decimal % 10 == 0 && decimalPlaces > 0 ) {
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 );
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 );
4232template <
typename TWriter>
4233class CountingDecorator {
4235 explicit CountingDecorator( TWriter& writer ) : writer_( writer ), count_( 0 ) {}
4236 void write( uint8_t c ) {
4237 count_ += writer_.write( c );
4239 void write(
const uint8_t* s,
size_t n ) {
4240 count_ += writer_.write( s, n );
4242 size_t count()
const {
4249template <
typename TWriter>
4250class TextFormatter {
4252 explicit TextFormatter( TWriter writer ) : writer_( writer ) {}
4253 TextFormatter& operator=(
const TextFormatter& ) =
delete;
4254 size_t bytesWritten()
const {
4255 return writer_.count();
4257 void writeBoolean(
bool value ) {
4261 writeRaw(
"false" );
4263 void writeString(
const char* value ) {
4264 ARDUINOJSON_ASSERT( value != NULL );
4267 writeChar( *value++ );
4270 void writeString(
const char* value,
size_t n ) {
4271 ARDUINOJSON_ASSERT( value != NULL );
4274 writeChar( *value++ );
4277 void writeChar(
char c ) {
4278 char specialChar = EscapeSequence::escapeChar( c );
4279 if ( specialChar ) {
4281 writeRaw( specialChar );
4287 writeRaw(
"\\u0000" );
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 ) {
4299 if ( isinf( value ) )
4300 return writeRaw(
"Infinity" );
4302 if ( isinf( value ) )
4303 return writeRaw(
"null" );
4304 if ( value < 0.0 ) {
4309 FloatParts<T> parts( value );
4310 writeInteger( parts.integral );
4311 if ( parts.decimalPlaces )
4312 writeDecimals( parts.decimal, parts.decimalPlaces );
4313 if ( parts.exponent ) {
4315 writeInteger( parts.exponent );
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;
4324 unsigned_value = unsigned_type( unsigned_type( ~value ) + 1 );
4327 unsigned_value = unsigned_type( value );
4329 writeInteger( unsigned_value );
4331 template <
typename T>
4332 typename enable_if<is_unsigned<T>::value>::type writeInteger( T value ) {
4334 char* end = buffer +
sizeof( buffer );
4337 *--begin = char( value % 10 +
'0' );
4338 value = T( value / 10 );
4340 writeRaw( begin, end );
4342 void writeDecimals( uint32_t value, int8_t width ) {
4344 char* end = buffer +
sizeof( buffer );
4347 *--begin = char( value % 10 +
'0' );
4351 writeRaw( begin, end );
4353 void writeRaw(
const char* s ) {
4354 writer_.write(
reinterpret_cast<const uint8_t*
>(s), strlen( s ) );
4356 void writeRaw(
const char* s,
size_t n ) {
4357 writer_.write(
reinterpret_cast<const uint8_t*
>(s), n );
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) );
4364 void writeRaw(
const char( &s )[N] ) {
4365 writer_.write(
reinterpret_cast<const uint8_t*
>(s), N - 1 );
4367 void writeRaw(
char c ) {
4368 writer_.write(
static_cast<uint8_t
>(c) );
4371 CountingDecorator<TWriter> writer_;
4375 size_t write( uint8_t ) {
4378 size_t write(
const uint8_t*,
size_t n ) {
4382template <
template <
typename>
class TSerializer>
4383size_t measure( ArduinoJson::JsonVariantConst source ) {
4385 TSerializer<DummyWriter> serializer( dp );
4386 return variantAccept( VariantAttorney::getData( source ), serializer );
4388template <
typename TDestination,
typename Enable =
void>
4391 explicit Writer( TDestination& dest ) : dest_( &dest ) {}
4392 size_t write( uint8_t c ) {
4393 return dest_->write( c );
4395 size_t write(
const uint8_t* s,
size_t n ) {
4396 return dest_->write( s, n );
4399 TDestination* dest_;
4401class StaticStringWriter {
4403 StaticStringWriter(
char* buf,
size_t size ) : end( buf + size ), p( buf ) {}
4404 size_t write( uint8_t c ) {
4407 *p++ =
static_cast<char>(c);
4410 size_t write(
const uint8_t* s,
size_t n ) {
4412 while ( p < end && n > 0 ) {
4413 *p++ =
static_cast<char>(*s++);
4416 return size_t( p - begin );
4422ARDUINOJSON_END_PRIVATE_NAMESPACE
4423#if ARDUINOJSON_ENABLE_STD_STRING
4424ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4427template <
class T,
typename =
void>
4428struct is_std_string : false_type {};
4430struct is_std_string<
4431 T, void_t<
decltype(T().push_back(
'a' )),
decltype(T().append(
"" ))>>
4433template <
typename TDestination>
4434class Writer<TDestination,
4435 typename enable_if<is_std_string<TDestination>::value>::type> {
4437 Writer( TDestination& str ) : str_( &str ) {}
4438 size_t write( uint8_t c ) {
4439 str_->push_back(
static_cast<char>(c) );
4442 size_t write(
const uint8_t* s,
size_t n ) {
4443 str_->append(
reinterpret_cast<const char*
>(s), n );
4449ARDUINOJSON_END_PRIVATE_NAMESPACE
4451#if ARDUINOJSON_ENABLE_ARDUINO_STRING
4452ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4454class Writer<::String, void> {
4455 static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
4457 explicit Writer( ::String& str ) : destination_( &str ) {
4463 size_t write( uint8_t c ) {
4464 if ( size_ + 1 >= bufferCapacity )
4467 buffer_[size_++] =
static_cast<char>(c);
4470 size_t write(
const uint8_t* s,
size_t n ) {
4471 for (
size_t i = 0; i < n; i++ ) {
4477 ARDUINOJSON_ASSERT( size_ < bufferCapacity );
4479 if ( destination_->concat( buffer_ ) )
4484 ::String* destination_;
4485 char buffer_[bufferCapacity];
4488ARDUINOJSON_END_PRIVATE_NAMESPACE
4490#if ARDUINOJSON_ENABLE_STD_STREAM
4491ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4492template <
typename TDestination>
4495 typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
4497 explicit Writer( std::ostream& os ) : os_( &os ) {}
4498 size_t write( uint8_t c ) {
4499 os_->put(
static_cast<char>(c) );
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) );
4510ARDUINOJSON_END_PRIVATE_NAMESPACE
4512#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
4513ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4514template <
typename TDestination>
4517 typename enable_if<is_base_of<::Print, TDestination>::value>::type> {
4519 explicit Writer( ::Print& print ) : print_( &print ) {}
4520 size_t write( uint8_t c ) {
4521 return print_->write( c );
4523 size_t write(
const uint8_t* s,
size_t n ) {
4524 return print_->write( s, n );
4529ARDUINOJSON_END_PRIVATE_NAMESPACE
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 );
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 );
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 );
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;
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 );
4565template <
typename TWriter>
4566class JsonSerializer :
public Visitor<size_t> {
4568 static const bool producesText =
true;
4569 JsonSerializer( TWriter writer ) : formatter_( writer ) {}
4570 FORCE_INLINE
size_t visitArray(
const CollectionData& array ) {
4572 const VariantSlot* slot = array.head();
4573 while ( slot != 0 ) {
4574 slot->data()->accept( *
this );
4575 slot = slot->next();
4581 return bytesWritten();
4583 size_t visitObject(
const CollectionData&
object ) {
4585 const VariantSlot* slot =
object.head();
4586 while ( slot != 0 ) {
4587 formatter_.writeString( slot->key() );
4589 slot->data()->accept( *
this );
4590 slot = slot->next();
4596 return bytesWritten();
4598 size_t visitFloat( JsonFloat value ) {
4599 formatter_.writeFloat( value );
4600 return bytesWritten();
4602 size_t visitString(
const char* value ) {
4603 formatter_.writeString( value );
4604 return bytesWritten();
4606 size_t visitString(
const char* value,
size_t n ) {
4607 formatter_.writeString( value, n );
4608 return bytesWritten();
4610 size_t visitRawJson(
const char* data,
size_t n ) {
4611 formatter_.writeRaw( data, n );
4612 return bytesWritten();
4614 size_t visitSignedInteger( JsonInteger value ) {
4615 formatter_.writeInteger( value );
4616 return bytesWritten();
4618 size_t visitUnsignedInteger( JsonUInt value ) {
4619 formatter_.writeInteger( value );
4620 return bytesWritten();
4622 size_t visitBoolean(
bool value ) {
4623 formatter_.writeBoolean( value );
4624 return bytesWritten();
4626 size_t visitNull() {
4627 formatter_.writeRaw(
"null" );
4628 return bytesWritten();
4631 size_t bytesWritten()
const {
4632 return formatter_.bytesWritten();
4634 void write(
char c ) {
4635 formatter_.writeRaw( c );
4637 void write(
const char* s ) {
4638 formatter_.writeRaw( s );
4641 TextFormatter<TWriter> formatter_;
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 );
4650inline size_t serializeJson( JsonVariantConst source,
void* buffer,
4651 size_t bufferSize ) {
4652 using namespace detail;
4653 return serialize<JsonSerializer>( source, buffer, bufferSize );
4655inline size_t measureJson( JsonVariantConst source ) {
4656 using namespace detail;
4657 return measure<JsonSerializer>( source );
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 );
4668ARDUINOJSON_END_PUBLIC_NAMESPACE
4669#if ARDUINOJSON_ENABLE_STD_STRING
4672#if ARDUINOJSON_ENABLE_STRING_VIEW
4673#include <string_view>
4675ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
4676template <
typename T,
typename Enable>
4678 static void toJson(
const T& src, JsonVariant dst ) {
4679 convertToJson( src, dst );
4681 static T fromJson( JsonVariantConst src ) {
4683 convertFromJson( src, result );
4686 static bool checkJson( JsonVariantConst src ) {
4688 return canConvertFromJson( src, dummy );
4691template <
typename T>
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 );
4701 data->setInteger( src );
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();
4708 static bool checkJson( JsonVariantConst src ) {
4709 auto data = getData( src );
4710 return data && data->template isInteger<T>();
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) );
4719 static T fromJson( JsonVariantConst src ) {
4720 auto data = getData( src );
4721 return data ?
static_cast<T
>(data->template asIntegral<int>()) : T();
4723 static bool checkJson( JsonVariantConst src ) {
4724 auto data = getData( src );
4725 return data && data->template isInteger<int>();
4729struct Converter<bool> :
private detail::VariantAttorney {
4730 static void toJson(
bool src, JsonVariant dst ) {
4731 auto data = getData( dst );
4733 data->setBoolean( src );
4735 static bool fromJson( JsonVariantConst src ) {
4736 auto data = getData( src );
4737 return data ? data->asBoolean() :
false;
4739 static bool checkJson( JsonVariantConst src ) {
4740 auto data = getData( src );
4741 return data && data->isBoolean();
4744template <
typename T>
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 );
4751 data->setFloat(
static_cast<JsonFloat
>(src) );
4753 static T fromJson( JsonVariantConst src ) {
4754 auto data = getData( src );
4755 return data ? data->template asFloat<T>() : 0;
4757 static bool checkJson( JsonVariantConst src ) {
4758 auto data = getData( src );
4759 return data && data->isFloat();
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 ) );
4767 static const char* fromJson( JsonVariantConst src ) {
4768 auto data = getData( src );
4769 return data ? data->asString().c_str() : 0;
4771 static bool checkJson( JsonVariantConst src ) {
4772 auto data = getData( src );
4773 return data && data->isString();
4777struct Converter<JsonString> :
private detail::VariantAttorney {
4778 static void toJson( JsonString src, JsonVariant dst ) {
4779 variantSetString( getData( dst ), detail::adaptString( src ), getPool( dst ) );
4781 static JsonString fromJson( JsonVariantConst src ) {
4782 auto data = getData( src );
4783 return data ? data->asString() : 0;
4785 static bool checkJson( JsonVariantConst src ) {
4786 auto data = getData( src );
4787 return data && data->isString();
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 );
4799struct Converter<SerializedValue<const char*>>
4800 :
private detail::VariantAttorney {
4801 static void toJson( SerializedValue<const char*> src, JsonVariant dst ) {
4802 auto data = getData( dst );
4804 data->setLinkedRaw( src );
4807template <
typename 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 );
4816 data->storeOwnedRaw( src, pool );
4820struct Converter<decltype(nullptr)> :
private detail::VariantAttorney {
4821 static void toJson(
decltype(
nullptr), JsonVariant dst ) {
4822 variantSetNull( getData( dst ) );
4824 static decltype(
nullptr) fromJson( JsonVariantConst ) {
4827 static bool checkJson( JsonVariantConst src ) {
4828 auto data = getData( src );
4829 return data == 0 || data->isNull();
4832#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
4834class MemoryPoolPrint :
public Print {
4836 MemoryPoolPrint( MemoryPool* pool ) : pool_( pool ), size_( 0 ) {
4837 pool->getFreeZone( &string_, &capacity_ );
4840 ARDUINOJSON_ASSERT( size_ < capacity_ );
4841 return JsonString( pool_->saveStringFromFreeZone( size_ ), size_,
4842 JsonString::Copied );
4844 size_t write( uint8_t c ) {
4845 if ( size_ >= capacity_ )
4847 string_[size_++] = char( c );
4850 size_t write(
const uint8_t* buffer,
size_t size ) {
4851 if ( size_ + size >= capacity_ ) {
4855 memcpy( &string_[size_], buffer, size );
4859 bool overflowed()
const {
4860 return size_ >= capacity_;
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 )
4874 detail::MemoryPoolPrint print( pool );
4875 src.printTo( print );
4876 if ( print.overflowed() ) {
4877 pool->markAsOverflowed();
4881 data->setString( print.str() );
4884#if ARDUINOJSON_ENABLE_ARDUINO_STRING
4885inline void convertFromJson( JsonVariantConst src, ::String& dst ) {
4886 JsonString str = src.as<JsonString>();
4890 serializeJson( src, dst );
4892inline bool canConvertFromJson( JsonVariantConst src, const ::String& ) {
4893 return src.is<JsonString>();
4896#if ARDUINOJSON_ENABLE_STD_STRING
4897inline void convertFromJson( JsonVariantConst src, std::string& dst ) {
4898 JsonString str = src.as<JsonString>();
4900 dst.assign( str.c_str(), str.size() );
4902 serializeJson( src, dst );
4904inline bool canConvertFromJson( JsonVariantConst src,
const std::string& ) {
4905 return src.is<JsonString>();
4908#if ARDUINOJSON_ENABLE_STRING_VIEW
4909inline void convertFromJson( JsonVariantConst src, std::string_view& dst ) {
4910 JsonString str = src.as<JsonString>();
4912 dst = std::string_view( str.c_str(), str.size() );
4914inline bool canConvertFromJson( JsonVariantConst src,
const std::string_view& ) {
4915 return src.is<JsonString>();
4919template <
typename T>
4920struct ConverterNeedsWriteableRef {
4922 static int probe( T( *f )(ArduinoJson::JsonVariant) );
4923 static char probe( T( *f )(ArduinoJson::JsonVariantConst) );
4925 static const bool value =
4926 sizeof( probe( Converter<T>::fromJson ) ) ==
sizeof(
int );
4929ARDUINOJSON_END_PUBLIC_NAMESPACE
4930ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
4931class CollectionData;
4932struct ComparerBase : Visitor<CompareResult> {};
4933template <
typename T,
typename Enable =
void>
4935template <
typename T>
4936struct Comparer<T, typename enable_if<IsString<T>::value>::type>
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 ) );
4943 return COMPARE_RESULT_GREATER;
4945 return COMPARE_RESULT_LESS;
4947 return COMPARE_RESULT_EQUAL;
4949 CompareResult visitNull() {
4950 if ( adaptString( rhs ).isNull() )
4951 return COMPARE_RESULT_EQUAL;
4953 return COMPARE_RESULT_DIFFER;
4956template <
typename T>
4957struct Comparer<T, typename enable_if<is_integral<T>::value ||
4958 is_floating_point<T>::value>::type>
4961 explicit Comparer( T value ) : rhs( value ) {}
4962 CompareResult visitFloat( JsonFloat lhs ) {
4963 return arithmeticCompare( lhs, rhs );
4965 CompareResult visitSignedInteger( JsonInteger lhs ) {
4966 return arithmeticCompare( lhs, rhs );
4968 CompareResult visitUnsignedInteger( JsonUInt lhs ) {
4969 return arithmeticCompare( lhs, rhs );
4971 CompareResult visitBoolean(
bool lhs ) {
4972 return visitUnsignedInteger(
static_cast<JsonUInt
>(lhs) );
4975struct NullComparer : ComparerBase {
4976 CompareResult visitNull() {
4977 return COMPARE_RESULT_EQUAL;
4981struct Comparer<decltype(nullptr), void> : NullComparer {
4982 explicit Comparer(
decltype(
nullptr) ) : NullComparer() {}
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;
4991 return COMPARE_RESULT_DIFFER;
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;
5001 return COMPARE_RESULT_DIFFER;
5004struct RawComparer : ComparerBase {
5005 const char* rhsData_;
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 );
5013 return COMPARE_RESULT_LESS;
5015 return COMPARE_RESULT_GREATER;
5017 return COMPARE_RESULT_EQUAL;
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 );
5027 CompareResult visitObject(
const CollectionData& lhs ) {
5028 ObjectComparer comparer( lhs );
5029 return accept( comparer );
5031 CompareResult visitFloat( JsonFloat lhs ) {
5032 Comparer<JsonFloat> comparer( lhs );
5033 return accept( comparer );
5035 CompareResult visitString(
const char* lhs,
size_t ) {
5036 Comparer<const char*> comparer( lhs );
5037 return accept( comparer );
5039 CompareResult visitRawJson(
const char* lhsData,
size_t lhsSize ) {
5040 RawComparer comparer( lhsData, lhsSize );
5041 return accept( comparer );
5043 CompareResult visitSignedInteger( JsonInteger lhs ) {
5044 Comparer<JsonInteger> comparer( lhs );
5045 return accept( comparer );
5047 CompareResult visitUnsignedInteger( JsonUInt lhs ) {
5048 Comparer<JsonUInt> comparer( lhs );
5049 return accept( comparer );
5051 CompareResult visitBoolean(
bool lhs ) {
5052 Comparer<bool> comparer( lhs );
5053 return accept( comparer );
5055 CompareResult visitNull() {
5056 NullComparer comparer;
5057 return accept( comparer );
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;
5069 return reversedResult;
5073template <
typename T>
5074struct Comparer<T, typename enable_if<is_convertible<
5075 T, ArduinoJson::JsonVariantConst>::value>::type>
5077 explicit Comparer(
const T& value )
5078 : VariantComparer( VariantAttorney::getData( value ) ) {}
5080template <
typename T>
5081CompareResult compare( ArduinoJson::JsonVariantConst lhs,
const T& rhs ) {
5082 Comparer<T> comparer( rhs );
5083 return variantAccept( VariantAttorney::getData( lhs ), comparer );
5086inline bool isdigit(
char c ) {
5087 return '0' <= c && c <=
'9';
5090inline bool issign(
char c ) {
5091 return '-' == c || c ==
'+';
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;
5110#if ARDUINOJSON_ENABLE_NAN
5111 if ( *s ==
'n' || *s ==
'N' ) {
5112 result.setFloat( traits::nan() );
5116#if ARDUINOJSON_ENABLE_INFINITY
5117 if ( *s ==
'i' || *s ==
'I' ) {
5118 result.setFloat( is_negative ? -traits::inf() : traits::inf() );
5122 if ( !isdigit( *s ) && *s !=
'.' )
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 )
5132 if ( mantissa > maxUint - digit )
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 ) );
5147 result.setInteger( JsonUInt( mantissa ) );
5151 while ( mantissa > traits::mantissa_max ) {
5155 while ( isdigit( *s ) ) {
5161 while ( isdigit( *s ) ) {
5162 if ( mantissa < traits::mantissa_max / 10 ) {
5163 mantissa = mantissa * 10 + uint8_t( *s -
'0' );
5170 if ( *s ==
'e' || *s ==
'E' ) {
5172 bool negative_exponent =
false;
5174 negative_exponent =
true;
5177 else if ( *s ==
'+' ) {
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 );
5186 result.setFloat( is_negative ? -traits::inf() : traits::inf() );
5191 if ( negative_exponent )
5192 exponent = -exponent;
5194 exponent += exponent_offset;
5197 JsonFloat final_result =
5198 make_float(
static_cast<JsonFloat
>(mantissa), exponent );
5199 result.setFloat( is_negative ? -final_result : final_result );
5202template <
typename T>
5203inline T parseNumber(
const char* s ) {
5205 parseNumber( s, value );
5206 return Converter<T>::fromJson( JsonVariantConst( &value ) );
5208template <
typename T>
5209inline T VariantData::asIntegral()
const {
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 );
5226inline bool VariantData::asBoolean()
const {
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;
5241template <
typename T>
5242inline T VariantData::asFloat()
const {
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);
5259inline JsonString VariantData::asString()
const {
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 );
5268 return JsonString();
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 );
5281 case VALUE_IS_OWNED_RAW:
5282 return storeOwnedRaw(
5283 serialized( src.content_.asString.data, src.content_.asString.size ),
5286 setType( src.type() );
5287 content_ = src.content_;
5291template <
typename TDerived>
5292inline JsonVariant VariantRefBase<TDerived>::add()
const {
5293 return JsonVariant( getPool(),
5294 variantAddElement( getOrCreateData(), getPool() ) );
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() );
5302template <
typename TDerived>
5303inline JsonVariant VariantRefBase<TDerived>::getVariant()
const {
5304 return JsonVariant( getPool(), getData() );
5306template <
typename TDerived>
5307inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant()
const {
5308 return JsonVariant( getPool(), getOrCreateData() );
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() );
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();
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();
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() ) );
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() ) );
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 );
5351template <
typename TDerived>
5352inline void convertToJson(
const VariantRefBase<TDerived>& src,
5354 dst.set( src.template as<JsonVariantConst>() );
5356ARDUINOJSON_END_PRIVATE_NAMESPACE
5357#if ARDUINOJSON_ENABLE_STD_STREAM
5359ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
5360class DeserializationError {
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_;
5376 friend bool operator!=(
const DeserializationError& lhs,
5377 const DeserializationError& rhs ) {
5378 return lhs.code_ != rhs.code_;
5380 friend bool operator==(
const DeserializationError& lhs, Code rhs ) {
5381 return lhs.code_ == rhs;
5383 friend bool operator==( Code lhs,
const DeserializationError& rhs ) {
5384 return lhs == rhs.code_;
5386 friend bool operator!=(
const DeserializationError& lhs, Code rhs ) {
5387 return lhs.code_ != rhs;
5389 friend bool operator!=( Code lhs,
const DeserializationError& rhs ) {
5390 return lhs != rhs.code_;
5392 explicit operator bool()
const {
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_];
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_ ));
5423#if ARDUINOJSON_ENABLE_STD_STREAM
5424inline std::ostream&
operator<<( std::ostream& s,
5425 const DeserializationError& e ) {
5429inline std::ostream&
operator<<( std::ostream& s, DeserializationError::Code c ) {
5430 s << DeserializationError( c ).c_str();
5434namespace DeserializationOption {
5437 explicit Filter( JsonVariantConst v ) : variant_( v ) {}
5438 bool allow()
const {
5441 bool allowArray()
const {
5442 return variant_ ==
true || variant_.is<JsonArrayConst>();
5444 bool allowObject()
const {
5445 return variant_ ==
true || variant_.is<JsonObjectConst>();
5447 bool allowValue()
const {
5448 return variant_ ==
true;
5450 template <
typename TKey>
5451 Filter operator[](
const TKey& key )
const {
5452 if ( variant_ ==
true )
5454 JsonVariantConst member = variant_[key];
5455 return Filter( member.isNull() ? variant_[
"*"] : member );
5458 JsonVariantConst variant_;
5462struct AllowAllFilter {
5463 bool allow()
const {
5466 bool allowArray()
const {
5469 bool allowObject()
const {
5472 bool allowValue()
const {
5475 template <
typename TKey>
5476 AllowAllFilter operator[](
const TKey& )
const {
5477 return AllowAllFilter();
5481namespace DeserializationOption {
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) );
5490 bool reached()
const {
5497ARDUINOJSON_END_PUBLIC_NAMESPACE
5498ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5499template <
typename TFilter>
5500struct DeserializationOptions {
5502 DeserializationOption::NestingLimit nestingLimit;
5504template <
typename TFilter>
5505inline DeserializationOptions<TFilter> makeDeserializationOptions(
5506 TFilter filter, DeserializationOption::NestingLimit nestingLimit ={} ) {
5507 return { filter, nestingLimit };
5509template <
typename TFilter>
5510inline DeserializationOptions<TFilter> makeDeserializationOptions(
5511 DeserializationOption::NestingLimit nestingLimit, TFilter filter ) {
5512 return { filter, nestingLimit };
5514inline DeserializationOptions<AllowAllFilter> makeDeserializationOptions(
5515 DeserializationOption::NestingLimit nestingLimit ={} ) {
5516 return { {}, nestingLimit };
5519T&& forward(
typename remove_reference<T>::type& t )
noexcept {
5520 return static_cast<T&&
>(t);
5522template <
typename TSource,
typename Enable =
void>
5525 Reader( TSource& source ) : source_( &source ) {}
5527 return source_->read();
5529 size_t readBytes(
char* buffer,
size_t length ) {
5530 return source_->readBytes( buffer, length );
5535template <
typename TSource,
typename Enable =
void>
5536struct BoundedReader {
5538template <
typename TIterator>
5539class IteratorReader {
5540 TIterator ptr_, end_;
5542 explicit IteratorReader( TIterator begin, TIterator end )
5543 : ptr_( begin ), end_( end ) {}
5546 return static_cast<unsigned char>(*ptr_++);
5550 size_t readBytes(
char* buffer,
size_t length ) {
5552 while ( i < length && ptr_ < end_ )
5553 buffer[i++] = *ptr_++;
5557template <
typename T>
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(),
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;
5574template <
typename T>
5575struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
5576template <
typename TSource>
5577struct Reader<TSource*,
5578 typename enable_if<IsCharOrVoid<TSource>::value>::type> {
5581 explicit Reader(
const void* ptr )
5582 : ptr_( ptr ? reinterpret_cast<const char*>(ptr) :
"" ) {}
5584 return static_cast<unsigned char>(*ptr_++);
5586 size_t readBytes(
char* buffer,
size_t length ) {
5587 for (
size_t i = 0; i < length; i++ )
5588 buffer[i] = *ptr_++;
5592template <
typename TSource>
5593struct BoundedReader<TSource*,
5594 typename enable_if<IsCharOrVoid<TSource>::value>::type>
5595 :
public IteratorReader<const char*> {
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 ) {}
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*>() ) {}
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> {
5614 explicit Reader( Stream& stream ) : stream_( &stream ) {}
5617 return stream_->readBytes( &c, 1 ) ?
static_cast<unsigned char>(c) : -1;
5619 size_t readBytes(
char* buffer,
size_t length ) {
5620 return stream_->readBytes( buffer, length );
5625ARDUINOJSON_END_PRIVATE_NAMESPACE
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() ) {}
5636ARDUINOJSON_END_PRIVATE_NAMESPACE
5638#if ARDUINOJSON_ENABLE_PROGMEM
5639ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5641struct Reader<const __FlashStringHelper*,
void> {
5644 explicit Reader(
const __FlashStringHelper* ptr )
5645 : ptr_( reinterpret_cast<const char*>(ptr) ) {}
5647 return pgm_read_byte( ptr_++ );
5649 size_t readBytes(
char* buffer,
size_t length ) {
5650 memcpy_P( buffer, ptr_, length );
5656struct BoundedReader<const __FlashStringHelper*,
void> {
5660 explicit BoundedReader(
const __FlashStringHelper* ptr,
size_t size )
5661 : ptr_( reinterpret_cast<const char*>(ptr) ), end_( ptr_ + size ) {}
5664 return pgm_read_byte( ptr_++ );
5668 size_t readBytes(
char* buffer,
size_t length ) {
5669 size_t available =
static_cast<size_t>(end_ - ptr_);
5670 if ( available < length )
5672 memcpy_P( buffer, ptr_, length );
5677ARDUINOJSON_END_PRIVATE_NAMESPACE
5679#if ARDUINOJSON_ENABLE_STD_STREAM
5681ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5682template <
typename TSource>
5683struct Reader<TSource, typename enable_if<
5684 is_base_of<std::istream, TSource>::value>::type> {
5686 explicit Reader( std::istream& stream ) : stream_( &stream ) {}
5688 return stream_->get();
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());
5695 std::istream* stream_;
5697ARDUINOJSON_END_PRIVATE_NAMESPACE
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 )};
5705template <
typename TChar>
5706BoundedReader<TChar*> makeReader( TChar* input,
size_t inputSize ) {
5707 return BoundedReader<TChar*>{input, inputSize};
5711 StringCopier( MemoryPool* pool ) : pool_( pool ) {}
5712 void startString() {
5713 pool_->getFreeZone( &ptr_, &capacity_ );
5715 if ( capacity_ == 0 )
5716 pool_->markAsOverflowed();
5719 ARDUINOJSON_ASSERT( ptr_ );
5720 ARDUINOJSON_ASSERT( size_ < capacity_ );
5721 return JsonString( pool_->saveStringFromFreeZone( size_ ), size_,
5722 JsonString::Copied );
5724 void append(
const char* s ) {
5728 void append(
const char* s,
size_t n ) {
5732 void append(
char c ) {
5733 if ( size_ + 1 < capacity_ )
5736 pool_->markAsOverflowed();
5738 bool isValid()
const {
5739 return !pool_->overflowed();
5741 size_t size()
const {
5744 JsonString str()
const {
5745 ARDUINOJSON_ASSERT( ptr_ );
5746 ARDUINOJSON_ASSERT( size_ < capacity_ );
5748 return JsonString( ptr_, size_, JsonString::Copied );
5753 size_t size_, capacity_;
5757 StringMover(
char* ptr ) : writePtr_( ptr ) {}
5758 void startString() {
5759 startPtr_ = writePtr_;
5761 FORCE_INLINE JsonString save() {
5762 JsonString s = str();
5766 void append(
char c ) {
5769 bool isValid()
const {
5772 JsonString str()
const {
5774 return JsonString( startPtr_, size(), JsonString::Linked );
5776 size_t size()
const {
5777 return size_t( writePtr_ - startPtr_ );
5783template <
typename TInput>
5784StringCopier makeStringStorage( TInput&, MemoryPool* pool ) {
5785 ARDUINOJSON_ASSERT( pool != 0 );
5786 return StringCopier( pool );
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) );
5794template <
typename...>
5795struct first_or_void {
5798template <
typename T,
typename... Rest>
5799struct first_or_void<T, Rest...> {
5802template <
template <
typename,
typename>
class TDeserializer,
typename TReader,
5804TDeserializer<TReader, TWriter> makeDeserializer( MemoryPool* pool,
5807 ARDUINOJSON_ASSERT( pool != 0 );
5808 return TDeserializer<TReader, TWriter>( pool, reader, writer );
5810template <
template <
typename,
typename>
class TDeserializer,
typename TStream,
5812 typename =
typename enable_if<
5813 !is_integral<
typename first_or_void<Args...>::type>::value>::type>
5814DeserializationError deserialize( JsonDocument& doc, TStream&& input,
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... );
5821 return makeDeserializer<TDeserializer>( pool, reader,
5822 makeStringStorage( input, pool ) )
5823 .parse( *data, options.filter, options.nestingLimit );
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... );
5835 return makeDeserializer<TDeserializer>( pool, reader,
5836 makeStringStorage( input, pool ) )
5837 .parse( *data, options.filter, options.nestingLimit );
5839template <
typename TReader>
5842 Latch( TReader reader ) : reader_( reader ), loaded_( false ) {
5843#if ARDUINOJSON_DEBUG
5853 FORCE_INLINE
char current() {
5861 ARDUINOJSON_ASSERT( !ended_ );
5862 int c = reader_.read();
5863#if ARDUINOJSON_DEBUG
5867 current_ =
static_cast<char>(c > 0 ? c : 0);
5873#if ARDUINOJSON_DEBUG
5877ARDUINOJSON_END_PRIVATE_NAMESPACE
5878#if defined(__GNUC__)
5880# pragma GCC diagnostic push
5881# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
5884ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5886inline bool isHighSurrogate( uint16_t codeunit ) {
5887 return codeunit >= 0xD800 && codeunit < 0xDC00;
5889inline bool isLowSurrogate( uint16_t codeunit ) {
5890 return codeunit >= 0xDC00 && codeunit < 0xE000;
5894 Codepoint() : highSurrogate_( 0 ), codepoint_( 0 ) {}
5895 bool append( uint16_t codeunit ) {
5896 if ( isHighSurrogate( codeunit ) ) {
5897 highSurrogate_ = codeunit & 0x3FF;
5900 if ( isLowSurrogate( codeunit ) ) {
5902 uint32_t( 0x10000 + ((highSurrogate_ << 10) | (codeunit & 0x3FF)) );
5905 codepoint_ = codeunit;
5908 uint32_t value()
const {
5912 uint16_t highSurrogate_;
5913 uint32_t codepoint_;
5916ARDUINOJSON_END_PRIVATE_NAMESPACE
5917#if defined(__GNUC__)
5919# pragma GCC diagnostic pop
5922ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
5924template <
typename TStringBuilder>
5925inline void encodeCodepoint( uint32_t codepoint32, TStringBuilder& str ) {
5926 if ( codepoint32 < 0x80 ) {
5927 str.append(
char( codepoint32 ) );
5933 *(p++) =
char( (codepoint32 | 0x80) & 0xBF );
5934 uint16_t codepoint16 = uint16_t( codepoint32 >> 6 );
5935 if ( codepoint16 < 0x20 ) {
5936 *(p++) =
char( codepoint16 | 0xC0 );
5939 *(p++) =
char( (codepoint16 | 0x80) & 0xBF );
5940 codepoint16 = uint16_t( codepoint16 >> 6 );
5941 if ( codepoint16 < 0x10 ) {
5942 *(p++) =
char( codepoint16 | 0xE0 );
5945 *(p++) =
char( (codepoint16 | 0x80) & 0xBF );
5946 codepoint16 = uint16_t( codepoint16 >> 6 );
5947 *(p++) =
char( codepoint16 | 0xF0 );
5956template <
typename TReader,
typename TStringStorage>
5957class JsonDeserializer {
5959 JsonDeserializer( MemoryPool* pool, TReader reader,
5960 TStringStorage stringStorage )
5961 : stringStorage_( stringStorage ),
5962 foundSomething_( false ),
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;
5977 return latch_.current();
5982 bool eat(
char charToSkip ) {
5983 if ( current() != charToSkip )
5988 template <
typename TFilter>
5989 DeserializationError::Code parseVariant(
5990 VariantData& variant, TFilter filter,
5991 DeserializationOption::NestingLimit nestingLimit ) {
5992 DeserializationError::Code err;
5993 err = skipSpacesAndComments();
5996 switch ( current() ) {
5998 if ( filter.allowArray() )
5999 return parseArray( variant.toArray(), filter, nestingLimit );
6001 return skipArray( nestingLimit );
6003 if ( filter.allowObject() )
6004 return parseObject( variant.toObject(), filter, nestingLimit );
6006 return skipObject( nestingLimit );
6009 if ( filter.allowValue() )
6010 return parseStringValue( variant );
6012 return skipQuotedString();
6014 if ( filter.allowValue() )
6015 variant.setBoolean(
true );
6016 return skipKeyword(
"true" );
6018 if ( filter.allowValue() )
6019 variant.setBoolean(
false );
6020 return skipKeyword(
"false" );
6022 return skipKeyword(
"null" );
6024 if ( filter.allowValue() )
6025 return parseNumericValue( variant );
6027 return skipNumericValue();
6030 DeserializationError::Code skipVariant(
6031 DeserializationOption::NestingLimit nestingLimit ) {
6032 DeserializationError::Code err;
6033 err = skipSpacesAndComments();
6036 switch ( current() ) {
6038 return skipArray( nestingLimit );
6040 return skipObject( nestingLimit );
6043 return skipQuotedString();
6045 return skipKeyword(
"true" );
6047 return skipKeyword(
"false" );
6049 return skipKeyword(
"null" );
6051 return skipNumericValue();
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() ==
'[' );
6063 err = skipSpacesAndComments();
6067 return DeserializationError::Ok;
6068 TFilter memberFilter = filter[0UL];
6070 if ( memberFilter.allow() ) {
6071 VariantData* value = array.addElement( pool_ );
6073 return DeserializationError::NoMemory;
6074 err = parseVariant( *value, memberFilter, nestingLimit.decrement() );
6079 err = skipVariant( nestingLimit.decrement() );
6083 err = skipSpacesAndComments();
6087 return DeserializationError::Ok;
6089 return DeserializationError::InvalidInput;
6092 DeserializationError::Code skipArray(
6093 DeserializationOption::NestingLimit nestingLimit ) {
6094 DeserializationError::Code err;
6095 if ( nestingLimit.reached() )
6096 return DeserializationError::TooDeep;
6097 ARDUINOJSON_ASSERT( current() ==
'[' );
6100 err = skipVariant( nestingLimit.decrement() );
6103 err = skipSpacesAndComments();
6107 return DeserializationError::Ok;
6109 return DeserializationError::InvalidInput;
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() ==
'{' );
6121 err = skipSpacesAndComments();
6125 return DeserializationError::Ok;
6130 err = skipSpacesAndComments();
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() ) );
6140 key = stringStorage_.save();
6141 VariantSlot* slot =
object.addSlot( pool_ );
6143 return DeserializationError::NoMemory;
6144 slot->setKey( key );
6145 variant = slot->data();
6147 err = parseVariant( *variant, memberFilter, nestingLimit.decrement() );
6152 err = skipVariant( nestingLimit.decrement() );
6156 err = skipSpacesAndComments();
6160 return DeserializationError::Ok;
6162 return DeserializationError::InvalidInput;
6163 err = skipSpacesAndComments();
6168 DeserializationError::Code skipObject(
6169 DeserializationOption::NestingLimit nestingLimit ) {
6170 DeserializationError::Code err;
6171 if ( nestingLimit.reached() )
6172 return DeserializationError::TooDeep;
6173 ARDUINOJSON_ASSERT( current() ==
'{' );
6175 err = skipSpacesAndComments();
6179 return DeserializationError::Ok;
6184 err = skipSpacesAndComments();
6188 return DeserializationError::InvalidInput;
6189 err = skipVariant( nestingLimit.decrement() );
6192 err = skipSpacesAndComments();
6196 return DeserializationError::Ok;
6198 return DeserializationError::InvalidInput;
6199 err = skipSpacesAndComments();
6204 DeserializationError::Code parseKey() {
6205 stringStorage_.startString();
6206 if ( isQuote( current() ) ) {
6207 return parseQuotedString();
6210 return parseNonQuotedString();
6213 DeserializationError::Code parseStringValue( VariantData& variant ) {
6214 DeserializationError::Code err;
6215 stringStorage_.startString();
6216 err = parseQuotedString();
6219 variant.setString( stringStorage_.save() );
6220 return DeserializationError::Ok;
6222 DeserializationError::Code parseQuotedString() {
6223#if ARDUINOJSON_DECODE_UNICODE
6224 Utf16::Codepoint codepoint;
6225 DeserializationError::Code err;
6227 const char stopChar = current();
6232 if ( c == stopChar )
6235 return DeserializationError::IncompleteInput;
6239 return DeserializationError::IncompleteInput;
6241#if ARDUINOJSON_DECODE_UNICODE
6244 err = parseHex4( codeunit );
6247 if ( codepoint.append( codeunit ) )
6248 Utf8::encodeCodepoint( codepoint.value(), stringStorage_ );
6250 stringStorage_.append(
'\\' );
6254 c = EscapeSequence::unescapeChar( c );
6256 return DeserializationError::InvalidInput;
6259 stringStorage_.append( c );
6261 if ( !stringStorage_.isValid() )
6262 return DeserializationError::NoMemory;
6263 return DeserializationError::Ok;
6265 DeserializationError::Code parseNonQuotedString() {
6267 ARDUINOJSON_ASSERT( c );
6268 if ( canBeInNonQuotedString( c ) ) {
6271 stringStorage_.append( c );
6273 }
while ( canBeInNonQuotedString( c ) );
6276 return DeserializationError::InvalidInput;
6278 if ( !stringStorage_.isValid() )
6279 return DeserializationError::NoMemory;
6280 return DeserializationError::Ok;
6282 DeserializationError::Code skipKey() {
6283 if ( isQuote( current() ) ) {
6284 return skipQuotedString();
6287 return skipNonQuotedString();
6290 DeserializationError::Code skipQuotedString() {
6291 const char stopChar = current();
6296 if ( c == stopChar )
6299 return DeserializationError::IncompleteInput;
6301 if ( current() !=
'\0' )
6305 return DeserializationError::Ok;
6307 DeserializationError::Code skipNonQuotedString() {
6309 while ( canBeInNonQuotedString( c ) ) {
6313 return DeserializationError::Ok;
6315 DeserializationError::Code parseNumericValue( VariantData& result ) {
6318 while ( canBeInNumber( c ) && n < 63 ) {
6324 if ( !parseNumber( buffer_, result ) )
6325 return DeserializationError::InvalidInput;
6326 return DeserializationError::Ok;
6328 DeserializationError::Code skipNumericValue() {
6330 while ( canBeInNumber( c ) ) {
6334 return DeserializationError::Ok;
6336 DeserializationError::Code parseHex4( uint16_t& result ) {
6338 for ( uint8_t i = 0; i < 4; ++i ) {
6339 char digit = current();
6341 return DeserializationError::IncompleteInput;
6342 uint8_t value = decodeHex( digit );
6344 return DeserializationError::InvalidInput;
6345 result = uint16_t( (result << 4) | value );
6348 return DeserializationError::Ok;
6350 static inline bool isBetween(
char c,
char min,
char max ) {
6351 return min <= c && c <= max;
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' );
6358 c ==
'e' || c ==
'E';
6361 static inline bool canBeInNonQuotedString(
char c ) {
6362 return isBetween( c,
'0',
'9' ) || isBetween( c,
'_',
'z' ) ||
6363 isBetween( c,
'A',
'Z' );
6365 static inline bool isQuote(
char c ) {
6366 return c ==
'\'' || c ==
'\"';
6368 static inline uint8_t decodeHex(
char c ) {
6370 return uint8_t( c -
'0' );
6371 c = char( c & ~0x20 );
6372 return uint8_t( c -
'A' + 10 );
6374 DeserializationError::Code skipSpacesAndComments() {
6376 switch ( current() ) {
6378 return foundSomething_ ? DeserializationError::IncompleteInput
6379 : DeserializationError::EmptyInput;
6386#if ARDUINOJSON_ENABLE_COMMENTS
6389 switch ( current() ) {
6392 bool wasStar =
false;
6396 return DeserializationError::IncompleteInput;
6397 if ( c ==
'/' && wasStar ) {
6411 return DeserializationError::IncompleteInput;
6417 return DeserializationError::InvalidInput;
6422 foundSomething_ =
true;
6423 return DeserializationError::Ok;
6427 DeserializationError::Code skipKeyword(
const char* s ) {
6431 return DeserializationError::IncompleteInput;
6433 return DeserializationError::InvalidInput;
6437 return DeserializationError::Ok;
6439 TStringStorage stringStorage_;
6440 bool foundSomething_;
6441 Latch<TReader> latch_;
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 )... );
6452template <
typename TChar,
typename... Args>
6453DeserializationError deserializeJson( JsonDocument& doc, TChar* input,
6455 using namespace detail;
6456 return deserialize<JsonDeserializer>( doc, input,
6457 detail::forward<Args>( args )... );
6459ARDUINOJSON_END_PUBLIC_NAMESPACE
6460ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
6461template <
typename TWriter>
6462class PrettyJsonSerializer :
public JsonSerializer<TWriter> {
6463 typedef JsonSerializer<TWriter> base;
6465 PrettyJsonSerializer( TWriter writer ) : base( writer ), nesting_( 0 ) {}
6466 size_t visitArray(
const CollectionData& array ) {
6467 const VariantSlot* slot = array.head();
6469 base::write(
"[\r\n" );
6471 while ( slot != 0 ) {
6473 slot->data()->accept( *
this );
6474 slot = slot->next();
6475 base::write( slot ?
",\r\n" :
"\r\n" );
6482 base::write(
"[]" );
6484 return this->bytesWritten();
6486 size_t visitObject(
const CollectionData&
object ) {
6487 const VariantSlot* slot =
object.head();
6489 base::write(
"{\r\n" );
6491 while ( slot != 0 ) {
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" );
6504 base::write(
"{}" );
6506 return this->bytesWritten();
6510 for ( uint8_t i = 0; i < nesting_; i++ )
6511 base::write( ARDUINOJSON_TAB );
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 );
6522inline size_t serializeJsonPretty( JsonVariantConst source,
void* buffer,
6523 size_t bufferSize ) {
6524 using namespace ArduinoJson::detail;
6525 return serialize<PrettyJsonSerializer>( source, buffer, bufferSize );
6527inline size_t measureJsonPretty( JsonVariantConst source ) {
6528 using namespace ArduinoJson::detail;
6529 return measure<PrettyJsonSerializer>( source );
6531ARDUINOJSON_END_PUBLIC_NAMESPACE
6532ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
6533#if ARDUINOJSON_LITTLE_ENDIAN
6534inline void swapBytes( uint8_t& a, uint8_t& b ) {
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] );
6545inline void fixEndianess( uint8_t* p, integral_constant<size_t, 4> ) {
6546 swapBytes( p[0], p[3] );
6547 swapBytes( p[1], p[2] );
6549inline void fixEndianess( uint8_t* p, integral_constant<size_t, 2> ) {
6550 swapBytes( p[0], p[1] );
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 )>() );
6559template <
typename T>
6560inline void fixEndianess( T& ) {}
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) );
6568template <
typename TReader,
typename TStringStorage>
6569class MsgPackDeserializer {
6571 MsgPackDeserializer( MemoryPool* pool, TReader reader,
6572 TStringStorage stringStorage )
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;
6585 template <
typename TFilter>
6586 DeserializationError::Code parseVariant(
6587 VariantData* variant, TFilter filter,
6588 DeserializationOption::NestingLimit nestingLimit ) {
6589 DeserializationError::Code err;
6591 err = readByte( code );
6594 foundSomething_ =
true;
6595 bool allowValue = filter.allowValue();
6597 ARDUINOJSON_ASSERT( variant != 0 );
6601 return DeserializationError::Ok;
6603 return DeserializationError::InvalidInput;
6606 variant->setBoolean(
false );
6607 return DeserializationError::Ok;
6610 variant->setBoolean(
true );
6611 return DeserializationError::Ok;
6613 return skipString<uint8_t>();
6615 return skipString<uint16_t>();
6617 return skipString<uint32_t>();
6619 return skipExt<uint8_t>();
6621 return skipExt<uint16_t>();
6623 return skipExt<uint32_t>();
6626 return readFloat<float>( variant );
6628 return skipBytes( 4 );
6631 return readDouble<double>( variant );
6633 return skipBytes( 8 );
6636 return readInteger<uint8_t>( variant );
6638 return skipBytes( 1 );
6641 return readInteger<uint16_t>( variant );
6643 return skipBytes( 2 );
6646 return readInteger<uint32_t>( variant );
6648 return skipBytes( 4 );
6650#if ARDUINOJSON_USE_LONG_LONG
6652 return readInteger<uint64_t>( variant );
6654 return skipBytes( 8 );
6656 return skipBytes( 8 );
6660 return readInteger<int8_t>( variant );
6662 return skipBytes( 1 );
6665 return readInteger<int16_t>( variant );
6667 return skipBytes( 2 );
6670 return readInteger<int32_t>( variant );
6672 return skipBytes( 4 );
6674#if ARDUINOJSON_USE_LONG_LONG
6676 return readInteger<int64_t>( variant );
6678 return skipBytes( 8 );
6680 return skipBytes( 8 );
6683 return skipBytes( 2 );
6685 return skipBytes( 3 );
6687 return skipBytes( 5 );
6689 return skipBytes( 9 );
6691 return skipBytes( 17 );
6694 return readString<uint8_t>( variant );
6696 return skipString<uint8_t>();
6699 return readString<uint16_t>( variant );
6701 return skipString<uint16_t>();
6704 return readString<uint32_t>( variant );
6706 return skipString<uint32_t>();
6708 return readArray<uint16_t>( variant, filter, nestingLimit );
6710 return readArray<uint32_t>( variant, filter, nestingLimit );
6712 return readObject<uint16_t>( variant, filter, nestingLimit );
6714 return readObject<uint32_t>( variant, filter, nestingLimit );
6716 switch ( code & 0xf0 ) {
6718 return readObject( variant, code & 0x0F, filter, nestingLimit );
6720 return readArray( variant, code & 0x0F, filter, nestingLimit );
6722 if ( (code & 0xe0) == 0xa0 ) {
6724 return readString( variant, code & 0x1f );
6726 return skipBytes( code & 0x1f );
6729 variant->setInteger(
static_cast<int8_t
>(code) );
6730 return DeserializationError::Ok;
6732 DeserializationError::Code readByte( uint8_t& value ) {
6733 int c = reader_.read();
6735 return DeserializationError::IncompleteInput;
6736 value =
static_cast<uint8_t
>(c);
6737 return DeserializationError::Ok;
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;
6744 template <
typename T>
6745 DeserializationError::Code readBytes( T& value ) {
6746 return readBytes(
reinterpret_cast<uint8_t*
>(&value),
sizeof( value ) );
6748 DeserializationError::Code skipBytes(
size_t n ) {
6750 if ( reader_.read() < 0 )
6751 return DeserializationError::IncompleteInput;
6753 return DeserializationError::Ok;
6755 template <
typename T>
6756 DeserializationError::Code readInteger( T& value ) {
6757 DeserializationError::Code err;
6758 err = readBytes( value );
6761 fixEndianess( value );
6762 return DeserializationError::Ok;
6764 template <
typename T>
6765 DeserializationError::Code readInteger( VariantData* variant ) {
6766 DeserializationError::Code err;
6768 err = readInteger( value );
6771 variant->setInteger( value );
6772 return DeserializationError::Ok;
6774 template <
typename T>
6775 typename enable_if<
sizeof( T ) == 4, DeserializationError::Code>::type
6776 readFloat( VariantData* variant ) {
6777 DeserializationError::Code err;
6779 err = readBytes( value );
6782 fixEndianess( value );
6783 variant->setFloat( value );
6784 return DeserializationError::Ok;
6786 template <
typename T>
6787 typename enable_if<
sizeof( T ) == 8, DeserializationError::Code>::type
6788 readDouble( VariantData* variant ) {
6789 DeserializationError::Code err;
6791 err = readBytes( value );
6794 fixEndianess( value );
6795 variant->setFloat( value );
6796 return DeserializationError::Ok;
6798 template <
typename T>
6799 typename enable_if<
sizeof( T ) == 4, DeserializationError::Code>::type
6800 readDouble( VariantData* variant ) {
6801 DeserializationError::Code err;
6804 uint8_t* o =
reinterpret_cast<uint8_t*
>(&value);
6805 err = readBytes( i, 8 );
6808 doubleToFloat( i, o );
6809 fixEndianess( value );
6810 variant->setFloat( value );
6811 return DeserializationError::Ok;
6813 template <
typename T>
6814 DeserializationError::Code readString( VariantData* variant ) {
6815 DeserializationError::Code err;
6817 err = readInteger( size );
6820 return readString( variant, size );
6822 template <
typename T>
6823 DeserializationError::Code readString() {
6824 DeserializationError::Code err;
6826 err = readInteger( size );
6829 return readString( size );
6831 template <
typename T>
6832 DeserializationError::Code skipString() {
6833 DeserializationError::Code err;
6835 err = readInteger( size );
6838 return skipBytes( size );
6840 DeserializationError::Code readString( VariantData* variant,
size_t n ) {
6841 DeserializationError::Code err;
6842 err = readString( n );
6845 variant->setString( stringStorage_.save() );
6846 return DeserializationError::Ok;
6848 DeserializationError::Code readString(
size_t n ) {
6849 DeserializationError::Code err;
6850 stringStorage_.startString();
6853 err = readBytes( c );
6856 stringStorage_.append(
static_cast<char>(c) );
6858 if ( !stringStorage_.isValid() )
6859 return DeserializationError::NoMemory;
6860 return DeserializationError::Ok;
6862 template <
typename TSize,
typename TFilter>
6863 DeserializationError::Code readArray(
6864 VariantData* variant, TFilter filter,
6865 DeserializationOption::NestingLimit nestingLimit ) {
6866 DeserializationError::Code err;
6868 err = readInteger( size );
6871 return readArray( variant, size, filter, nestingLimit );
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;
6883 ARDUINOJSON_ASSERT( variant != 0 );
6884 array = &variant->toArray();
6889 TFilter memberFilter = filter[0U];
6892 if ( memberFilter.allow() ) {
6893 ARDUINOJSON_ASSERT( array != 0 );
6894 value = array->addElement( pool_ );
6896 return DeserializationError::NoMemory;
6901 err = parseVariant( value, memberFilter, nestingLimit.decrement() );
6905 return DeserializationError::Ok;
6907 template <
typename TSize,
typename TFilter>
6908 DeserializationError::Code readObject(
6909 VariantData* variant, TFilter filter,
6910 DeserializationOption::NestingLimit nestingLimit ) {
6911 DeserializationError::Code err;
6913 err = readInteger( size );
6916 return readObject( variant, size, filter, nestingLimit );
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();
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_ );
6945 return DeserializationError::NoMemory;
6946 slot->setKey( key );
6947 member = slot->data();
6952 err = parseVariant( member, memberFilter, nestingLimit.decrement() );
6956 return DeserializationError::Ok;
6958 DeserializationError::Code readKey() {
6959 DeserializationError::Code err;
6961 err = readByte( code );
6964 if ( (code & 0xe0) == 0xa0 )
6965 return readString( code & 0x1f );
6968 return readString<uint8_t>();
6970 return readString<uint16_t>();
6972 return readString<uint32_t>();
6974 return DeserializationError::InvalidInput;
6977 template <
typename T>
6978 DeserializationError::Code skipExt() {
6979 DeserializationError::Code err;
6981 err = readInteger( size );
6984 return skipBytes( size + 1U );
6988 TStringStorage stringStorage_;
6989 bool foundSomething_;
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 )... );
6998template <
typename TChar,
typename... Args>
6999DeserializationError deserializeMsgPack( JsonDocument& doc, TChar* input,
7001 using namespace detail;
7002 return deserialize<MsgPackDeserializer>( doc, input,
7003 detail::forward<Args>( args )... );
7005ARDUINOJSON_END_PUBLIC_NAMESPACE
7006ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
7007template <
typename TWriter>
7008class MsgPackSerializer :
public Visitor<size_t> {
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 );
7020 writeInteger( value32 );
7021 return bytesWritten();
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 );
7030 writeInteger( value64 );
7031 return bytesWritten();
7033 size_t visitArray(
const CollectionData& array ) {
7034 size_t n = array.size();
7036 writeByte( uint8_t( 0x90 + n ) );
7038 else if ( n < 0x10000 ) {
7040 writeInteger( uint16_t( n ) );
7044 writeInteger( uint32_t( n ) );
7046 for (
const VariantSlot* slot = array.head(); slot; slot = slot->next() ) {
7047 slot->data()->accept( *
this );
7049 return bytesWritten();
7051 size_t visitObject(
const CollectionData&
object ) {
7052 size_t n =
object.size();
7054 writeByte( uint8_t( 0x80 + n ) );
7056 else if ( n < 0x10000 ) {
7058 writeInteger( uint16_t( n ) );
7062 writeInteger( uint32_t( n ) );
7064 for (
const VariantSlot* slot =
object.head(); slot; slot = slot->next() ) {
7065 visitString( slot->key() );
7066 slot->data()->accept( *
this );
7068 return bytesWritten();
7070 size_t visitString(
const char* value ) {
7071 return visitString( value, strlen( value ) );
7073 size_t visitString(
const char* value,
size_t n ) {
7074 ARDUINOJSON_ASSERT( value != NULL );
7076 writeByte( uint8_t( 0xA0 + n ) );
7078 else if ( n < 0x100 ) {
7080 writeInteger( uint8_t( n ) );
7082 else if ( n < 0x10000 ) {
7084 writeInteger( uint16_t( n ) );
7088 writeInteger( uint32_t( n ) );
7090 writeBytes(
reinterpret_cast<const uint8_t*
>(value), n );
7091 return bytesWritten();
7093 size_t visitRawJson(
const char* data,
size_t size ) {
7094 writeBytes(
reinterpret_cast<const uint8_t*
>(data), size );
7095 return bytesWritten();
7097 size_t visitSignedInteger( JsonInteger value ) {
7099 visitUnsignedInteger(
static_cast<JsonUInt
>(value) );
7101 else if ( value >= -0x20 ) {
7102 writeInteger( int8_t( value ) );
7104 else if ( value >= -0x80 ) {
7106 writeInteger( int8_t( value ) );
7108 else if ( value >= -0x8000 ) {
7110 writeInteger( int16_t( value ) );
7112#if ARDUINOJSON_USE_LONG_LONG
7113 else if ( value >= -0x80000000LL )
7119 writeInteger( int32_t( value ) );
7121#if ARDUINOJSON_USE_LONG_LONG
7124 writeInteger( int64_t( value ) );
7127 return bytesWritten();
7129 size_t visitUnsignedInteger( JsonUInt value ) {
7130 if ( value <= 0x7F ) {
7131 writeInteger( uint8_t( value ) );
7133 else if ( value <= 0xFF ) {
7135 writeInteger( uint8_t( value ) );
7137 else if ( value <= 0xFFFF ) {
7139 writeInteger( uint16_t( value ) );
7141#if ARDUINOJSON_USE_LONG_LONG
7142 else if ( value <= 0xFFFFFFFF )
7148 writeInteger( uint32_t( value ) );
7150#if ARDUINOJSON_USE_LONG_LONG
7153 writeInteger( uint64_t( value ) );
7156 return bytesWritten();
7158 size_t visitBoolean(
bool value ) {
7159 writeByte( value ? 0xC3 : 0xC2 );
7160 return bytesWritten();
7162 size_t visitNull() {
7164 return bytesWritten();
7167 size_t bytesWritten()
const {
7168 return writer_.count();
7170 void writeByte( uint8_t c ) {
7173 void writeBytes(
const uint8_t* p,
size_t n ) {
7174 writer_.write( p, n );
7176 template <
typename T>
7177 void writeInteger( T value ) {
7178 fixEndianess( value );
7179 writeBytes(
reinterpret_cast<uint8_t*
>(&value),
sizeof( value ) );
7181 CountingDecorator<TWriter> writer_;
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 );
7190inline size_t serializeMsgPack( JsonVariantConst source,
void* output,
7192 using namespace ArduinoJson::detail;
7193 return serialize<MsgPackSerializer>( source, output, size );
7195inline size_t measureMsgPack( JsonVariantConst source ) {
7196 using namespace ArduinoJson::detail;
7197 return measure<MsgPackSerializer>( source );
7199ARDUINOJSON_END_PUBLIC_NAMESPACE
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
7213using namespace ArduinoJson;
7217#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp
ostream & operator<<(ostream &out, const Cpl::Text::String &outstring)
Support stream output operator directly.