Minh Nguyen / ArduinoJson
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers VariantRef.hpp Source File

VariantRef.hpp

00001 // ArduinoJson - arduinojson.org
00002 // Copyright Benoit Blanchon 2014-2021
00003 // MIT License
00004 
00005 #pragma once
00006 
00007 #include <stddef.h>
00008 #include <stdint.h>  // for uint8_t
00009 
00010 #include <ArduinoJson/Memory/MemoryPool.hpp>
00011 #include <ArduinoJson/Misc/Visitable.hpp>
00012 #include <ArduinoJson/Polyfills/type_traits.hpp>
00013 #include <ArduinoJson/Strings/StringAdapters.hpp>
00014 #include <ArduinoJson/Variant/VariantAs.hpp>
00015 #include <ArduinoJson/Variant/VariantFunctions.hpp>
00016 #include <ArduinoJson/Variant/VariantOperators.hpp>
00017 #include <ArduinoJson/Variant/VariantRef.hpp>
00018 #include <ArduinoJson/Variant/VariantShortcuts.hpp>
00019 #include <ArduinoJson/Variant/VariantTag.hpp>
00020 
00021 namespace ARDUINOJSON_NAMESPACE {
00022 
00023 // Forward declarations.
00024 class ArrayRef;
00025 class ObjectRef;
00026 
00027 // Contains the methods shared by VariantRef and VariantConstRef
00028 template <typename TData>
00029 class VariantRefBase : public VariantTag {
00030  public:
00031   // Tells wether the variant has the specified type.
00032   // Returns true if the variant has type type T, false otherwise.
00033   //
00034   // bool is<char>() const;
00035   // bool is<signed char>() const;
00036   // bool is<signed short>() const;
00037   // bool is<signed int>() const;
00038   // bool is<signed long>() const;
00039   // bool is<unsigned char>() const;
00040   // bool is<unsigned short>() const;
00041   // bool is<unsigned int>() const;
00042   // bool is<unsigned long>() const;
00043   template <typename T>
00044   FORCE_INLINE
00045       typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
00046                          bool>::type
00047       is() const {
00048     return variantIsInteger<T>(_data);
00049   }
00050   //
00051   // bool is<double>() const;
00052   // bool is<float>() const;
00053   template <typename T>
00054   FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
00055       const {
00056     return variantIsFloat(_data);
00057   }
00058   //
00059   // bool is<bool>() const
00060   template <typename T>
00061   FORCE_INLINE typename enable_if<is_same<T, bool>::value, bool>::type is()
00062       const {
00063     return variantIsBoolean(_data);
00064   }
00065   //
00066   // bool is<const char*>() const;
00067   // bool is<char*>() const;
00068   // bool is<std::string>() const;
00069   // bool is<String>() const;
00070   template <typename T>
00071   FORCE_INLINE typename enable_if<is_same<T, const char *>::value ||
00072                                       is_same<T, char *>::value ||
00073                                       IsWriteableString<T>::value,
00074                                   bool>::type
00075   is() const {
00076     return variantIsString(_data);
00077   }
00078   //
00079   // bool is<ArrayRef> const;
00080   // bool is<const ArrayRef> const;
00081   template <typename T>
00082   FORCE_INLINE typename enable_if<
00083       is_same<typename remove_const<T>::type, ArrayRef>::value, bool>::type
00084   is() const {
00085     return variantIsArray(_data);
00086   }
00087   //
00088   // bool is<ObjectRef> const;
00089   // bool is<const ObjectRef> const;
00090   template <typename T>
00091   FORCE_INLINE typename enable_if<
00092       is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type
00093   is() const {
00094     return variantIsObject(_data);
00095   }
00096 #if ARDUINOJSON_HAS_NULLPTR
00097   //
00098   // bool is<nullptr_t> const;
00099   template <typename T>
00100   FORCE_INLINE
00101       typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type
00102       is() const {
00103     return variantIsNull(_data);
00104   }
00105 #endif
00106   // bool is<enum>() const;
00107   template <typename T>
00108   FORCE_INLINE typename enable_if<is_enum<T>::value, bool>::type is() const {
00109     return variantIsInteger<int>(_data);
00110   }
00111 
00112   FORCE_INLINE bool isNull() const {
00113     return variantIsNull(_data);
00114   }
00115 
00116   FORCE_INLINE bool isUndefined() const {
00117     return !_data;
00118   }
00119 
00120   FORCE_INLINE size_t memoryUsage() const {
00121     return _data ? _data->memoryUsage() : 0;
00122   }
00123 
00124   FORCE_INLINE size_t nesting() const {
00125     return _data ? _data->nesting() : 0;
00126   }
00127 
00128   size_t size() const {
00129     return variantSize(_data);
00130   }
00131 
00132  protected:
00133   VariantRefBase(TData *data) : _data(data) {}
00134   TData *_data;
00135 };
00136 
00137 // A variant that can be a any value serializable to a JSON value.
00138 //
00139 // It can be set to:
00140 // - a boolean
00141 // - a char, short, int or a long (signed or unsigned)
00142 // - a string (const char*)
00143 // - a reference to a ArrayRef or ObjectRef
00144 class VariantRef : public VariantRefBase<VariantData>,
00145                    public VariantOperators<VariantRef>,
00146                    public VariantShortcuts<VariantRef>,
00147                    public Visitable {
00148   typedef VariantRefBase<VariantData> base_type;
00149   friend class VariantConstRef;
00150 
00151  public:
00152   // Intenal use only
00153   FORCE_INLINE VariantRef(MemoryPool *pool, VariantData *data)
00154       : base_type(data), _pool(pool) {}
00155 
00156   // Creates an uninitialized VariantRef
00157   FORCE_INLINE VariantRef() : base_type(0), _pool(0) {}
00158 
00159   FORCE_INLINE void clear() const {
00160     return variantSetNull(_data);
00161   }
00162 
00163   // set(bool value)
00164   template <typename T>
00165   FORCE_INLINE bool set(
00166       T value, typename enable_if<is_same<T, bool>::value>::type * = 0) const {
00167     return variantSetBoolean(_data, value);
00168   }
00169 
00170   // set(double value);
00171   // set(float value);
00172   template <typename T>
00173   FORCE_INLINE bool set(
00174       T value,
00175       typename enable_if<is_floating_point<T>::value>::type * = 0) const {
00176     return variantSetFloat(_data, static_cast<Float>(value));
00177   }
00178 
00179   // set(char)
00180   // set(signed short)
00181   // set(signed int)
00182   // set(signed long)
00183   // set(signed char)
00184   // set(unsigned short)
00185   // set(unsigned int)
00186   // set(unsigned long)
00187   template <typename T>
00188   FORCE_INLINE bool set(
00189       T value, typename enable_if<is_integral<T>::value &&
00190                                   !is_same<bool, T>::value>::type * = 0) const {
00191     return variantSetInteger<T>(_data, value);
00192   }
00193 
00194   // set(SerializedValue<const char *>)
00195   FORCE_INLINE bool set(SerializedValue<const char *> value) const {
00196     return variantSetLinkedRaw(_data, value);
00197   }
00198 
00199   // set(SerializedValue<std::string>)
00200   // set(SerializedValue<String>)
00201   // set(SerializedValue<const __FlashStringHelper*>)
00202   template <typename T>
00203   FORCE_INLINE bool set(
00204       SerializedValue<T> value,
00205       typename enable_if<!is_same<const char *, T>::value>::type * = 0) const {
00206     return variantSetOwnedRaw(_data, value, _pool);
00207   }
00208 
00209   // set(const std::string&)
00210   // set(const String&)
00211   template <typename T>
00212   FORCE_INLINE bool set(
00213       const T &value,
00214       typename enable_if<IsString<T>::value>::type * = 0) const {
00215     return variantSetString(_data, adaptString(value), _pool);
00216   }
00217   // set(char*)
00218   // set(const __FlashStringHelper*)
00219   // set(const char*)
00220   template <typename T>
00221   FORCE_INLINE bool set(
00222       T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
00223     return variantSetString(_data, adaptString(value), _pool);
00224   }
00225 
00226   // set(VariantRef)
00227   // set(VariantConstRef)
00228   // set(ArrayRef)
00229   // set(ArrayConstRef)
00230   // set(ObjectRef)
00231   // set(ObjecConstRef)
00232   // set(const JsonDocument&)
00233   template <typename TVariant>
00234   typename enable_if<IsVisitable<TVariant>::value, bool>::type set(
00235       const TVariant &value) const;
00236 
00237   // set(enum value)
00238   template <typename T>
00239   FORCE_INLINE bool set(
00240       T value, typename enable_if<is_enum<T>::value>::type * = 0) const {
00241     return variantSetInteger(_data, static_cast<Integer>(value));
00242   }
00243 
00244 #if ARDUINOJSON_HAS_NULLPTR
00245   // set(nullptr_t)
00246   FORCE_INLINE bool set(decltype(nullptr)) const {
00247     variantSetNull(_data);
00248     return true;
00249   }
00250 #endif
00251 
00252   template <typename T>
00253   FORCE_INLINE typename VariantAs<T>::type as() const {
00254     return variantAs<typename VariantAs<T>::type>(_data, _pool);
00255   }
00256 
00257   template <typename T>
00258   FORCE_INLINE operator T() const {
00259     return variantAs<T>(_data, _pool);
00260   }
00261 
00262   template <typename TVisitor>
00263   typename TVisitor::result_type accept(TVisitor &visitor) const {
00264     return variantAccept(_data, visitor);
00265   }
00266 
00267   // Change the type of the variant
00268   //
00269   // ArrayRef to<ArrayRef>()
00270   template <typename T>
00271   typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type to() const;
00272   //
00273   // ObjectRef to<ObjectRef>()
00274   template <typename T>
00275   typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type to() const;
00276   //
00277   // ObjectRef to<VariantRef>()
00278   template <typename T>
00279   typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
00280       const;
00281 
00282   VariantRef addElement() const;
00283 
00284   FORCE_INLINE VariantRef getElement(size_t) const;
00285 
00286   FORCE_INLINE VariantRef getOrAddElement(size_t) const;
00287 
00288   // getMember(const char*) const
00289   // getMember(const __FlashStringHelper*) const
00290   template <typename TChar>
00291   FORCE_INLINE VariantRef getMember(TChar *) const;
00292 
00293   // getMember(const std::string&) const
00294   // getMember(const String&) const
00295   template <typename TString>
00296   FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
00297   getMember(const TString &) const;
00298 
00299   // getOrAddMember(char*) const
00300   // getOrAddMember(const char*) const
00301   // getOrAddMember(const __FlashStringHelper*) const
00302   template <typename TChar>
00303   FORCE_INLINE VariantRef getOrAddMember(TChar *) const;
00304 
00305   // getOrAddMember(const std::string&) const
00306   // getOrAddMember(const String&) const
00307   template <typename TString>
00308   FORCE_INLINE VariantRef getOrAddMember(const TString &) const;
00309 
00310   FORCE_INLINE void remove(size_t index) const {
00311     if (_data)
00312       _data->remove(index);
00313   }
00314   // remove(char*) const
00315   // remove(const char*) const
00316   // remove(const __FlashStringHelper*) const
00317   template <typename TChar>
00318   FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
00319       TChar *key) const {
00320     if (_data)
00321       _data->remove(adaptString(key));
00322   }
00323   // remove(const std::string&) const
00324   // remove(const String&) const
00325   template <typename TString>
00326   FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
00327       const TString &key) const {
00328     if (_data)
00329       _data->remove(adaptString(key));
00330   }
00331 
00332  private:
00333   MemoryPool *_pool;
00334 };  // namespace ARDUINOJSON_NAMESPACE
00335 
00336 class VariantConstRef : public VariantRefBase<const VariantData>,
00337                         public VariantOperators<VariantConstRef>,
00338                         public VariantShortcuts<VariantConstRef>,
00339                         public Visitable {
00340   typedef VariantRefBase<const VariantData> base_type;
00341   friend class VariantRef;
00342 
00343  public:
00344   VariantConstRef() : base_type(0) {}
00345   VariantConstRef(const VariantData *data) : base_type(data) {}
00346   VariantConstRef(VariantRef var) : base_type(var._data) {}
00347 
00348   template <typename TVisitor>
00349   typename TVisitor::result_type accept(TVisitor &visitor) const {
00350     return variantAccept(_data, visitor);
00351   }
00352 
00353   template <typename T>
00354   FORCE_INLINE typename VariantConstAs<T>::type as() const {
00355     return variantAs<typename VariantConstAs<T>::type>(_data);
00356   }
00357 
00358   template <typename T>
00359   FORCE_INLINE operator T() const {
00360     return variantAs<T>(_data);
00361   }
00362 
00363   FORCE_INLINE VariantConstRef getElement(size_t) const;
00364 
00365   FORCE_INLINE VariantConstRef operator[](size_t index) const {
00366     return getElement(index);
00367   }
00368 
00369   // getMember(const std::string&) const
00370   // getMember(const String&) const
00371   template <typename TString>
00372   FORCE_INLINE VariantConstRef getMember(const TString &key) const {
00373     return VariantConstRef(
00374         objectGetMember(variantAsObject(_data), adaptString(key)));
00375   }
00376 
00377   // getMember(char*) const
00378   // getMember(const char*) const
00379   // getMember(const __FlashStringHelper*) const
00380   template <typename TChar>
00381   FORCE_INLINE VariantConstRef getMember(TChar *key) const {
00382     const CollectionData *obj = variantAsObject(_data);
00383     return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0);
00384   }
00385 
00386   // operator[](const std::string&) const
00387   // operator[](const String&) const
00388   template <typename TString>
00389   FORCE_INLINE
00390       typename enable_if<IsString<TString>::value, VariantConstRef>::type
00391       operator[](const TString &key) const {
00392     return getMember(key);
00393   }
00394 
00395   // operator[](char*) const
00396   // operator[](const char*) const
00397   // operator[](const __FlashStringHelper*) const
00398   template <typename TChar>
00399   FORCE_INLINE
00400       typename enable_if<IsString<TChar *>::value, VariantConstRef>::type
00401       operator[](TChar *key) const {
00402     return getMember(key);
00403   }
00404 };
00405 }  // namespace ARDUINOJSON_NAMESPACE