VariantRef.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. // ArduinoJson - arduinojson.org
  2. // Copyright Benoit Blanchon 2014-2020
  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/Operators/VariantOperators.hpp>
  10. #include <ArduinoJson/Polyfills/type_traits.hpp>
  11. #include <ArduinoJson/Variant/VariantAs.hpp>
  12. #include <ArduinoJson/Variant/VariantFunctions.hpp>
  13. #include <ArduinoJson/Variant/VariantRef.hpp>
  14. namespace ARDUINOJSON_NAMESPACE {
  15. // Forward declarations.
  16. class ArrayRef;
  17. class ObjectRef;
  18. template <typename, typename>
  19. class MemberProxy;
  20. // Contains the methods shared by VariantRef and VariantConstRef
  21. template <typename TData>
  22. class VariantRefBase {
  23. public:
  24. // Tells wether the variant has the specified type.
  25. // Returns true if the variant has type type T, false otherwise.
  26. //
  27. // bool is<char>() const;
  28. // bool is<signed char>() const;
  29. // bool is<signed short>() const;
  30. // bool is<signed int>() const;
  31. // bool is<signed long>() const;
  32. // bool is<unsigned char>() const;
  33. // bool is<unsigned short>() const;
  34. // bool is<unsigned int>() const;
  35. // bool is<unsigned long>() const;
  36. template <typename T>
  37. FORCE_INLINE typename enable_if<is_integral<T>::value, bool>::type is()
  38. const {
  39. return variantIsInteger<T>(_data);
  40. }
  41. //
  42. // bool is<double>() const;
  43. // bool is<float>() const;
  44. template <typename T>
  45. FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
  46. const {
  47. return variantIsFloat(_data);
  48. }
  49. //
  50. // bool is<bool>() const
  51. template <typename T>
  52. FORCE_INLINE typename enable_if<is_same<T, bool>::value, bool>::type is()
  53. const {
  54. return variantIsBoolean(_data);
  55. }
  56. //
  57. // bool is<const char*>() const;
  58. // bool is<char*>() const;
  59. // bool is<std::string>() const;
  60. // bool is<String>() const;
  61. template <typename T>
  62. FORCE_INLINE typename enable_if<is_same<T, const char *>::value ||
  63. is_same<T, char *>::value ||
  64. IsWriteableString<T>::value,
  65. bool>::type
  66. is() const {
  67. return variantIsString(_data);
  68. }
  69. //
  70. // bool is<ArrayRef> const;
  71. // bool is<const ArrayRef> const;
  72. template <typename T>
  73. FORCE_INLINE typename enable_if<
  74. is_same<typename remove_const<T>::type, ArrayRef>::value, bool>::type
  75. is() const {
  76. return variantIsArray(_data);
  77. }
  78. //
  79. // bool is<ObjectRef> const;
  80. // bool is<const ObjectRef> const;
  81. template <typename T>
  82. FORCE_INLINE typename enable_if<
  83. is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type
  84. is() const {
  85. return variantIsObject(_data);
  86. }
  87. #if ARDUINOJSON_HAS_NULLPTR
  88. //
  89. // bool is<nullptr_t> const;
  90. template <typename T>
  91. FORCE_INLINE
  92. typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type
  93. is() const {
  94. return variantIsNull(_data);
  95. }
  96. #endif
  97. FORCE_INLINE bool isNull() const {
  98. return variantIsNull(_data);
  99. }
  100. FORCE_INLINE bool isUndefined() const {
  101. return !_data;
  102. }
  103. FORCE_INLINE size_t memoryUsage() const {
  104. return _data ? _data->memoryUsage() : 0;
  105. }
  106. FORCE_INLINE size_t nesting() const {
  107. return _data ? _data->nesting() : 0;
  108. }
  109. size_t size() const {
  110. return variantSize(_data);
  111. }
  112. protected:
  113. VariantRefBase(TData *data) : _data(data) {}
  114. TData *_data;
  115. };
  116. // A variant that can be a any value serializable to a JSON value.
  117. //
  118. // It can be set to:
  119. // - a boolean
  120. // - a char, short, int or a long (signed or unsigned)
  121. // - a string (const char*)
  122. // - a reference to a ArrayRef or ObjectRef
  123. class VariantRef : public VariantRefBase<VariantData>,
  124. public VariantOperators<VariantRef>,
  125. public Visitable {
  126. typedef VariantRefBase<VariantData> base_type;
  127. friend class VariantConstRef;
  128. public:
  129. // Intenal use only
  130. FORCE_INLINE VariantRef(MemoryPool *pool, VariantData *data)
  131. : base_type(data), _pool(pool) {}
  132. // Creates an uninitialized VariantRef
  133. FORCE_INLINE VariantRef() : base_type(0), _pool(0) {}
  134. FORCE_INLINE void clear() const {
  135. return variantSetNull(_data);
  136. }
  137. // set(bool value)
  138. FORCE_INLINE bool set(bool value) const {
  139. return variantSetBoolean(_data, value);
  140. }
  141. // set(double value);
  142. // set(float value);
  143. template <typename T>
  144. FORCE_INLINE bool set(
  145. T value,
  146. typename enable_if<is_floating_point<T>::value>::type * = 0) const {
  147. return variantSetFloat(_data, static_cast<Float>(value));
  148. }
  149. // set(char)
  150. // set(signed short)
  151. // set(signed int)
  152. // set(signed long)
  153. // set(signed char)
  154. template <typename T>
  155. FORCE_INLINE bool set(
  156. T value,
  157. typename enable_if<is_integral<T>::value && is_signed<T>::value>::type * =
  158. 0) const {
  159. return variantSetSignedInteger(_data, value);
  160. }
  161. // set(unsigned short)
  162. // set(unsigned int)
  163. // set(unsigned long)
  164. template <typename T>
  165. FORCE_INLINE bool set(
  166. T value, typename enable_if<is_integral<T>::value &&
  167. is_unsigned<T>::value>::type * = 0) const {
  168. return variantSetUnsignedInteger(_data, static_cast<UInt>(value));
  169. }
  170. // set(SerializedValue<const char *>)
  171. FORCE_INLINE bool set(SerializedValue<const char *> value) const {
  172. return variantSetLinkedRaw(_data, value);
  173. }
  174. // set(SerializedValue<std::string>)
  175. // set(SerializedValue<String>)
  176. // set(SerializedValue<const __FlashStringHelper*>)
  177. template <typename T>
  178. FORCE_INLINE bool set(
  179. SerializedValue<T> value,
  180. typename enable_if<!is_same<const char *, T>::value>::type * = 0) const {
  181. return variantSetOwnedRaw(_data, value, _pool);
  182. }
  183. // set(const std::string&)
  184. // set(const String&)
  185. template <typename T>
  186. FORCE_INLINE bool set(
  187. const T &value,
  188. typename enable_if<IsString<T>::value>::type * = 0) const {
  189. return variantSetOwnedString(_data, adaptString(value), _pool);
  190. }
  191. // set(char*)
  192. // set(const __FlashStringHelper*)
  193. template <typename T>
  194. FORCE_INLINE bool set(
  195. T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
  196. return variantSetOwnedString(_data, adaptString(value), _pool);
  197. }
  198. // set(const char*);
  199. FORCE_INLINE bool set(const char *value) const {
  200. return variantSetLinkedString(_data, value);
  201. }
  202. // set(VariantRef)
  203. // set(VariantConstRef)
  204. // set(ArrayRef)
  205. // set(ArrayConstRef)
  206. // set(ObjectRef)
  207. // set(ObjecConstRef)
  208. // set(const JsonDocument&)
  209. template <typename TVariant>
  210. typename enable_if<IsVisitable<TVariant>::value, bool>::type set(
  211. const TVariant &value) const;
  212. // Get the variant as the specified type.
  213. //
  214. // std::string as<std::string>() const;
  215. // String as<String>() const;
  216. template <typename T>
  217. FORCE_INLINE typename enable_if<!is_same<T, ArrayRef>::value &&
  218. !is_same<T, ObjectRef>::value &&
  219. !is_same<T, VariantRef>::value,
  220. typename VariantAs<T>::type>::type
  221. as() const {
  222. return variantAs<T>(_data);
  223. }
  224. //
  225. // ArrayRef as<ArrayRef>() const;
  226. // const ArrayRef as<const ArrayRef>() const;
  227. template <typename T>
  228. FORCE_INLINE typename enable_if<is_same<T, ArrayRef>::value, T>::type as()
  229. const;
  230. //
  231. // ObjectRef as<ObjectRef>() const;
  232. // const ObjectRef as<const ObjectRef>() const;
  233. template <typename T>
  234. FORCE_INLINE typename enable_if<is_same<T, ObjectRef>::value, T>::type as()
  235. const;
  236. //
  237. // VariantRef as<VariantRef> const;
  238. template <typename T>
  239. FORCE_INLINE typename enable_if<is_same<T, VariantRef>::value, T>::type as()
  240. const {
  241. return *this;
  242. }
  243. template <typename Visitor>
  244. void accept(Visitor &visitor) const {
  245. variantAccept(_data, visitor);
  246. }
  247. FORCE_INLINE bool operator==(VariantRef lhs) const {
  248. return variantEquals(_data, lhs._data);
  249. }
  250. FORCE_INLINE bool operator!=(VariantRef lhs) const {
  251. return !variantEquals(_data, lhs._data);
  252. }
  253. // Change the type of the variant
  254. //
  255. // ArrayRef to<ArrayRef>()
  256. template <typename T>
  257. typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type to() const;
  258. //
  259. // ObjectRef to<ObjectRef>()
  260. template <typename T>
  261. typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type to() const;
  262. //
  263. // ObjectRef to<VariantRef>()
  264. template <typename T>
  265. typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
  266. const;
  267. VariantRef addElement() const;
  268. FORCE_INLINE VariantRef getElement(size_t) const;
  269. FORCE_INLINE VariantRef getOrAddElement(size_t) const;
  270. // getMember(const char*) const
  271. // getMember(const __FlashStringHelper*) const
  272. template <typename TChar>
  273. FORCE_INLINE VariantRef getMember(TChar *) const;
  274. // getMember(const std::string&) const
  275. // getMember(const String&) const
  276. template <typename TString>
  277. FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
  278. getMember(const TString &) const;
  279. // getOrAddMember(char*) const
  280. // getOrAddMember(const char*) const
  281. // getOrAddMember(const __FlashStringHelper*) const
  282. template <typename TChar>
  283. FORCE_INLINE VariantRef getOrAddMember(TChar *) const;
  284. // getOrAddMember(const std::string&) const
  285. // getOrAddMember(const String&) const
  286. template <typename TString>
  287. FORCE_INLINE VariantRef getOrAddMember(const TString &) const;
  288. FORCE_INLINE void remove(size_t index) const {
  289. if (_data)
  290. _data->remove(index);
  291. }
  292. // remove(char*) const
  293. // remove(const char*) const
  294. // remove(const __FlashStringHelper*) const
  295. template <typename TChar>
  296. FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
  297. TChar *key) const {
  298. if (_data)
  299. _data->remove(adaptString(key));
  300. }
  301. // remove(const std::string&) const
  302. // remove(const String&) const
  303. template <typename TString>
  304. FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
  305. const TString &key) const {
  306. if (_data)
  307. _data->remove(adaptString(key));
  308. }
  309. private:
  310. MemoryPool *_pool;
  311. }; // namespace ARDUINOJSON_NAMESPACE
  312. class VariantConstRef : public VariantRefBase<const VariantData>,
  313. public VariantOperators<VariantConstRef>,
  314. public Visitable {
  315. typedef VariantRefBase<const VariantData> base_type;
  316. friend class VariantRef;
  317. public:
  318. VariantConstRef() : base_type(0) {}
  319. VariantConstRef(const VariantData *data) : base_type(data) {}
  320. VariantConstRef(VariantRef var) : base_type(var._data) {}
  321. template <typename Visitor>
  322. void accept(Visitor &visitor) const {
  323. variantAccept(_data, visitor);
  324. }
  325. // Get the variant as the specified type.
  326. //
  327. template <typename T>
  328. FORCE_INLINE typename VariantConstAs<T>::type as() const {
  329. return variantAs<typename VariantConstAs<T>::type>(_data);
  330. }
  331. FORCE_INLINE VariantConstRef getElement(size_t) const;
  332. FORCE_INLINE VariantConstRef operator[](size_t index) const {
  333. return getElement(index);
  334. }
  335. // getMember(const std::string&) const
  336. // getMember(const String&) const
  337. template <typename TString>
  338. FORCE_INLINE VariantConstRef getMember(const TString &key) const {
  339. return VariantConstRef(
  340. objectGetMember(variantAsObject(_data), adaptString(key)));
  341. }
  342. // getMember(char*) const
  343. // getMember(const char*) const
  344. // getMember(const __FlashStringHelper*) const
  345. template <typename TChar>
  346. FORCE_INLINE VariantConstRef getMember(TChar *key) const {
  347. const CollectionData *obj = variantAsObject(_data);
  348. return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0);
  349. }
  350. // operator[](const std::string&) const
  351. // operator[](const String&) const
  352. template <typename TString>
  353. FORCE_INLINE
  354. typename enable_if<IsString<TString>::value, VariantConstRef>::type
  355. operator[](const TString &key) const {
  356. return getMember(key);
  357. }
  358. // operator[](char*) const
  359. // operator[](const char*) const
  360. // operator[](const __FlashStringHelper*) const
  361. template <typename TChar>
  362. FORCE_INLINE
  363. typename enable_if<IsString<TChar *>::value, VariantConstRef>::type
  364. operator[](TChar *key) const {
  365. return getMember(key);
  366. }
  367. FORCE_INLINE bool operator==(VariantConstRef lhs) const {
  368. return variantEquals(_data, lhs._data);
  369. }
  370. FORCE_INLINE bool operator!=(VariantConstRef lhs) const {
  371. return !variantEquals(_data, lhs._data);
  372. }
  373. };
  374. } // namespace ARDUINOJSON_NAMESPACE