VariantRef.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. // ArduinoJson - arduinojson.org
  2. // Copyright Benoit Blanchon 2014-2021
  3. // MIT License
  4. #pragma once
  5. #include <stddef.h>
  6. #include <stdint.h> // for uint8_t
  7. #include <ArduinoJson/Memory/MemoryPool.hpp>
  8. #include <ArduinoJson/Misc/Visitable.hpp>
  9. #include <ArduinoJson/Polyfills/type_traits.hpp>
  10. #include <ArduinoJson/Strings/StringAdapters.hpp>
  11. #include <ArduinoJson/Variant/VariantAs.hpp>
  12. #include <ArduinoJson/Variant/VariantFunctions.hpp>
  13. #include <ArduinoJson/Variant/VariantIs.hpp>
  14. #include <ArduinoJson/Variant/VariantOperators.hpp>
  15. #include <ArduinoJson/Variant/VariantRef.hpp>
  16. #include <ArduinoJson/Variant/VariantShortcuts.hpp>
  17. #include <ArduinoJson/Variant/VariantTag.hpp>
  18. namespace ARDUINOJSON_NAMESPACE {
  19. // Forward declarations.
  20. class ArrayRef;
  21. class ObjectRef;
  22. // Contains the methods shared by VariantRef and VariantConstRef
  23. template <typename TData>
  24. class VariantRefBase : public VariantTag {
  25. public:
  26. template <typename T>
  27. FORCE_INLINE bool is() const {
  28. return variantIs<T>(_data);
  29. }
  30. FORCE_INLINE bool isNull() const {
  31. return variantIsNull(_data);
  32. }
  33. FORCE_INLINE bool isUndefined() const {
  34. return !_data;
  35. }
  36. FORCE_INLINE size_t memoryUsage() const {
  37. return _data ? _data->memoryUsage() : 0;
  38. }
  39. FORCE_INLINE size_t nesting() const {
  40. return _data ? _data->nesting() : 0;
  41. }
  42. size_t size() const {
  43. return variantSize(_data);
  44. }
  45. protected:
  46. VariantRefBase(TData *data) : _data(data) {}
  47. TData *_data;
  48. };
  49. // A variant that can be a any value serializable to a JSON value.
  50. //
  51. // It can be set to:
  52. // - a boolean
  53. // - a char, short, int or a long (signed or unsigned)
  54. // - a string (const char*)
  55. // - a reference to a ArrayRef or ObjectRef
  56. class VariantRef : public VariantRefBase<VariantData>,
  57. public VariantOperators<VariantRef>,
  58. public VariantShortcuts<VariantRef>,
  59. public Visitable {
  60. typedef VariantRefBase<VariantData> base_type;
  61. friend class VariantConstRef;
  62. public:
  63. // Intenal use only
  64. FORCE_INLINE VariantRef(MemoryPool *pool, VariantData *data)
  65. : base_type(data), _pool(pool) {}
  66. // Creates an uninitialized VariantRef
  67. FORCE_INLINE VariantRef() : base_type(0), _pool(0) {}
  68. FORCE_INLINE void clear() const {
  69. return variantSetNull(_data);
  70. }
  71. // set(bool value)
  72. template <typename T>
  73. FORCE_INLINE bool set(
  74. T value, typename enable_if<is_same<T, bool>::value>::type * = 0) const {
  75. return variantSetBoolean(_data, value);
  76. }
  77. // set(double value);
  78. // set(float value);
  79. template <typename T>
  80. FORCE_INLINE bool set(
  81. T value,
  82. typename enable_if<is_floating_point<T>::value>::type * = 0) const {
  83. return variantSetFloat(_data, static_cast<Float>(value));
  84. }
  85. // set(char)
  86. // set(signed short)
  87. // set(signed int)
  88. // set(signed long)
  89. // set(signed char)
  90. // set(unsigned short)
  91. // set(unsigned int)
  92. // set(unsigned long)
  93. template <typename T>
  94. FORCE_INLINE bool set(
  95. T value,
  96. typename enable_if<is_integral<T>::value && !is_same<bool, T>::value &&
  97. !is_same<char, T>::value>::type * = 0) const {
  98. return variantSetInteger<T>(_data, value);
  99. }
  100. // set(SerializedValue<const char *>)
  101. FORCE_INLINE bool set(SerializedValue<const char *> value) const {
  102. return variantSetLinkedRaw(_data, value);
  103. }
  104. // set(SerializedValue<std::string>)
  105. // set(SerializedValue<String>)
  106. // set(SerializedValue<const __FlashStringHelper*>)
  107. template <typename T>
  108. FORCE_INLINE bool set(
  109. SerializedValue<T> value,
  110. typename enable_if<!is_same<const char *, T>::value>::type * = 0) const {
  111. return variantSetOwnedRaw(_data, value, _pool);
  112. }
  113. // set(const std::string&)
  114. // set(const String&)
  115. template <typename T>
  116. FORCE_INLINE bool set(
  117. const T &value,
  118. typename enable_if<IsString<T>::value>::type * = 0) const {
  119. return variantSetString(_data, adaptString(value), _pool);
  120. }
  121. // set(char*)
  122. // set(const __FlashStringHelper*)
  123. // set(const char*)
  124. template <typename T>
  125. FORCE_INLINE bool set(
  126. T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
  127. return variantSetString(_data, adaptString(value), _pool);
  128. }
  129. // set(VariantRef)
  130. // set(VariantConstRef)
  131. // set(ArrayRef)
  132. // set(ArrayConstRef)
  133. // set(ObjectRef)
  134. // set(ObjecConstRef)
  135. // set(const JsonDocument&)
  136. template <typename TVariant>
  137. typename enable_if<IsVisitable<TVariant>::value, bool>::type set(
  138. const TVariant &value) const;
  139. // set(enum value)
  140. template <typename T>
  141. FORCE_INLINE bool set(
  142. T value, typename enable_if<is_enum<T>::value>::type * = 0) const {
  143. return variantSetInteger(_data, static_cast<Integer>(value));
  144. }
  145. #if ARDUINOJSON_HAS_NULLPTR
  146. // set(nullptr_t)
  147. FORCE_INLINE bool set(decltype(nullptr)) const {
  148. variantSetNull(_data);
  149. return true;
  150. }
  151. #endif
  152. template <typename T>
  153. FORCE_INLINE T as() const {
  154. /********************************************************************
  155. ** THIS IS NOT A BUG IN THE LIBRARY **
  156. ** -------------------------------- **
  157. ** Get a compilation error pointing here? **
  158. ** It doesn't mean the error *is* here. **
  159. ** Often, it's because you try to extract the wrong value type. **
  160. ** **
  161. ** For example: **
  162. ** char* name = doc["name"]; **
  163. ** char age = doc["age"]; **
  164. ** auto city = doc["city"].as<char*>() **
  165. ** Instead, use: **
  166. ** const char* name = doc["name"]; **
  167. ** int8_t age = doc["age"]; **
  168. ** auto city = doc["city"].as<const char*>() **
  169. ********************************************************************/
  170. return variantAs<T>(_data, _pool);
  171. }
  172. template <typename T>
  173. FORCE_INLINE operator T() const {
  174. return variantAs<T>(_data, _pool);
  175. }
  176. template <typename TVisitor>
  177. typename TVisitor::result_type accept(TVisitor &visitor) const {
  178. return variantAccept(_data, visitor);
  179. }
  180. // Change the type of the variant
  181. //
  182. // ArrayRef to<ArrayRef>()
  183. template <typename T>
  184. typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type to() const;
  185. //
  186. // ObjectRef to<ObjectRef>()
  187. template <typename T>
  188. typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type to() const;
  189. //
  190. // ObjectRef to<VariantRef>()
  191. template <typename T>
  192. typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
  193. const;
  194. VariantRef addElement() const;
  195. FORCE_INLINE VariantRef getElement(size_t) const;
  196. FORCE_INLINE VariantRef getOrAddElement(size_t) const;
  197. // getMember(const char*) const
  198. // getMember(const __FlashStringHelper*) const
  199. template <typename TChar>
  200. FORCE_INLINE VariantRef getMember(TChar *) const;
  201. // getMember(const std::string&) const
  202. // getMember(const String&) const
  203. template <typename TString>
  204. FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
  205. getMember(const TString &) const;
  206. // getOrAddMember(char*) const
  207. // getOrAddMember(const char*) const
  208. // getOrAddMember(const __FlashStringHelper*) const
  209. template <typename TChar>
  210. FORCE_INLINE VariantRef getOrAddMember(TChar *) const;
  211. // getOrAddMember(const std::string&) const
  212. // getOrAddMember(const String&) const
  213. template <typename TString>
  214. FORCE_INLINE VariantRef getOrAddMember(const TString &) const;
  215. FORCE_INLINE void remove(size_t index) const {
  216. if (_data)
  217. _data->remove(index);
  218. }
  219. // remove(char*) const
  220. // remove(const char*) const
  221. // remove(const __FlashStringHelper*) const
  222. template <typename TChar>
  223. FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
  224. TChar *key) const {
  225. if (_data)
  226. _data->remove(adaptString(key));
  227. }
  228. // remove(const std::string&) const
  229. // remove(const String&) const
  230. template <typename TString>
  231. FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
  232. const TString &key) const {
  233. if (_data)
  234. _data->remove(adaptString(key));
  235. }
  236. private:
  237. MemoryPool *_pool;
  238. }; // namespace ARDUINOJSON_NAMESPACE
  239. class VariantConstRef : public VariantRefBase<const VariantData>,
  240. public VariantOperators<VariantConstRef>,
  241. public VariantShortcuts<VariantConstRef>,
  242. public Visitable {
  243. typedef VariantRefBase<const VariantData> base_type;
  244. friend class VariantRef;
  245. public:
  246. VariantConstRef() : base_type(0) {}
  247. VariantConstRef(const VariantData *data) : base_type(data) {}
  248. VariantConstRef(VariantRef var) : base_type(var._data) {}
  249. template <typename TVisitor>
  250. typename TVisitor::result_type accept(TVisitor &visitor) const {
  251. return variantAccept(_data, visitor);
  252. }
  253. template <typename T>
  254. FORCE_INLINE T as() const {
  255. return variantAs<T>(_data);
  256. }
  257. template <typename T>
  258. FORCE_INLINE operator T() const {
  259. return variantAs<T>(_data);
  260. }
  261. FORCE_INLINE VariantConstRef getElement(size_t) const;
  262. FORCE_INLINE VariantConstRef operator[](size_t index) const {
  263. return getElement(index);
  264. }
  265. // getMember(const std::string&) const
  266. // getMember(const String&) const
  267. template <typename TString>
  268. FORCE_INLINE VariantConstRef getMember(const TString &key) const {
  269. return VariantConstRef(
  270. objectGetMember(variantAsObject(_data), adaptString(key)));
  271. }
  272. // getMember(char*) const
  273. // getMember(const char*) const
  274. // getMember(const __FlashStringHelper*) const
  275. template <typename TChar>
  276. FORCE_INLINE VariantConstRef getMember(TChar *key) const {
  277. const CollectionData *obj = variantAsObject(_data);
  278. return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0);
  279. }
  280. // operator[](const std::string&) const
  281. // operator[](const String&) const
  282. template <typename TString>
  283. FORCE_INLINE
  284. typename enable_if<IsString<TString>::value, VariantConstRef>::type
  285. operator[](const TString &key) const {
  286. return getMember(key);
  287. }
  288. // operator[](char*) const
  289. // operator[](const char*) const
  290. // operator[](const __FlashStringHelper*) const
  291. template <typename TChar>
  292. FORCE_INLINE
  293. typename enable_if<IsString<TChar *>::value, VariantConstRef>::type
  294. operator[](TChar *key) const {
  295. return getMember(key);
  296. }
  297. };
  298. } // namespace ARDUINOJSON_NAMESPACE