Array.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. //
  2. // Array.h
  3. //
  4. // Library: JSON
  5. // Package: JSON
  6. // Module: Array
  7. //
  8. // Definition of the Array class.
  9. //
  10. // Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #ifndef JSON_Array_INCLUDED
  16. #define JSON_Array_INCLUDED
  17. #include "Poco/JSON/JSON.h"
  18. #include "Poco/SharedPtr.h"
  19. #include "Poco/Dynamic/Var.h"
  20. #include <vector>
  21. #include <sstream>
  22. namespace Poco {
  23. namespace JSON {
  24. class Object;
  25. class JSON_API Array
  26. /// Represents a JSON array. Array provides a representation
  27. /// based on shared pointers and optimized for performance. It is possible to
  28. /// convert Array to Poco::Dynamic::Array. Conversion requires copying and therefore
  29. /// has performance penalty; the benefit is in improved syntax, eg:
  30. ///
  31. /// // use pointers to avoid copying
  32. /// using namespace Poco::JSON;
  33. /// std::string json = "[ {\"test\" : 0}, { \"test1\" : [1, 2, 3], \"test2\" : 4 } ]";
  34. /// Parser parser;
  35. /// Var result = parser.parse(json);
  36. /// Array::Ptr arr = result.extract<Array::Ptr>();
  37. /// Object::Ptr object = arr->getObject(0); // object == {\"test\" : 0}
  38. /// int i = object->getElement<int>("test"); // i == 0;
  39. /// Object::Ptr subObject = *arr->getObject(1); // subObject == {\"test\" : 0}
  40. /// Array subArr::Ptr = subObject->getArray("test1"); // subArr == [1, 2, 3]
  41. /// i = result = subArr->get(0); // i == 1;
  42. ///
  43. /// // copy/convert to Poco::Dynamic::Array
  44. /// Poco::Dynamic::Array da = *arr;
  45. /// i = da[0]["test"]; // i == 0
  46. /// i = da[1]["test1"][1]; // i == 2
  47. /// i = da[1]["test2"]; // i == 4
  48. /// ----
  49. {
  50. public:
  51. using ValueVec = std::vector<Dynamic::Var>;
  52. using Iterator = std::vector<Dynamic::Var>::iterator;
  53. using ConstIterator = std::vector<Dynamic::Var>::const_iterator;
  54. using Ptr = SharedPtr<Array>;
  55. Array(int options = 0);
  56. /// Creates an empty Array.
  57. ///
  58. /// If JSON_ESCAPE_UNICODE is specified, when the object is
  59. /// stringified, all unicode characters will be escaped in the
  60. /// resulting string.
  61. Array(const Array& copy);
  62. /// Creates an Array by copying another one.
  63. Array(Array&& other) noexcept;
  64. /// Move constructor
  65. Array& operator = (const Array& other);
  66. /// Assignment operator.
  67. Array& operator = (Array&& other) noexcept;
  68. /// Move assignment operator.
  69. ~Array();
  70. /// Destroys the Array.
  71. void setEscapeUnicode(bool escape = true);
  72. /// Sets the flag for escaping unicode.
  73. bool getEscapeUnicode() const;
  74. /// Returns the flag for escaping unicode.
  75. ValueVec::const_iterator begin() const;
  76. /// Returns the begin iterator for values.
  77. ValueVec::const_iterator end() const;
  78. /// Returns the end iterator for values.
  79. Dynamic::Var get(unsigned int index) const;
  80. /// Retrieves the element at the given index.
  81. /// Will return an empty value when the element doesn't exist.
  82. Array::Ptr getArray(unsigned int index) const;
  83. /// Retrieves an array. When the element is not
  84. /// an Array or doesn't exist, an empty SharedPtr is returned.
  85. template<typename T>
  86. T getElement(unsigned int index) const
  87. /// Retrieves an element and tries to convert it to the
  88. /// template type. The convert<T> method of
  89. /// Dynamic is called which can also throw
  90. /// exceptions for invalid values.
  91. /// Note: This will not work for an array or an object.
  92. {
  93. Dynamic::Var value = get(index);
  94. return value.convert<T>();
  95. }
  96. SharedPtr<Object> getObject(unsigned int index) const;
  97. /// Retrieves an object. When the element is not
  98. /// an object or doesn't exist, an empty SharedPtr is returned.
  99. std::size_t size() const;
  100. /// Returns the size of the array.
  101. bool isArray(unsigned int index) const;
  102. /// Returns true when the element is an array.
  103. bool isArray(const Dynamic::Var& value) const;
  104. /// Returns true when the element is an array.
  105. bool isArray(ConstIterator& value) const;
  106. /// Returns true when the element is an array.
  107. bool isNull(unsigned int index) const;
  108. /// Returns true when the element is null or
  109. /// when the element doesn't exist.
  110. bool isObject(unsigned int index) const;
  111. /// Returns true when the element is an object.
  112. bool isObject(const Dynamic::Var& value) const;
  113. /// Returns true when the element is an object.
  114. bool isObject(ConstIterator& value) const;
  115. /// Returns true when the element is an object.
  116. template<typename T>
  117. T optElement(unsigned int index, const T& def) const
  118. /// Returns the element at the given index. When
  119. /// the element is null, doesn't exist or can't
  120. /// be converted to the given type, the default
  121. /// value will be returned
  122. {
  123. T value = def;
  124. if (index < _values.size())
  125. {
  126. try
  127. {
  128. value = _values[index].convert<T>();
  129. }
  130. catch (...)
  131. {
  132. // Default value is returned.
  133. }
  134. }
  135. return value;
  136. }
  137. Array& add(const Dynamic::Var& value);
  138. /// Add the given value to the array
  139. Array& set(unsigned int index, const Dynamic::Var& value);
  140. /// Update the element on the given index to specified value
  141. void stringify(std::ostream& out, unsigned int indent = 0, int step = -1) const;
  142. /// Prints the array to out. When indent has zero value,
  143. /// the array will be printed without newline breaks and spaces between elements.
  144. void remove(unsigned int index);
  145. /// Removes the element on the given index.
  146. operator const Poco::Dynamic::Array& () const;
  147. /// Conversion operator to Dynamic::Array.
  148. static Poco::Dynamic::Array makeArray(const JSON::Array::Ptr& arr);
  149. /// Utility function for creation of array.
  150. void clear();
  151. /// Clears the contents of the array.
  152. private:
  153. void resetDynArray() const;
  154. typedef SharedPtr<Poco::Dynamic::Array> ArrayPtr;
  155. ValueVec _values;
  156. mutable ArrayPtr _pArray;
  157. mutable bool _modified;
  158. // Note:
  159. // The reason we have this flag here (rather than as argument to stringify())
  160. // is because Array can be returned stringified from a Dynamic::Var:toString(),
  161. // so it must know whether to escape unicode or not.
  162. bool _escapeUnicode;
  163. };
  164. //
  165. // inlines
  166. //
  167. inline void Array::setEscapeUnicode(bool escape)
  168. {
  169. _escapeUnicode = escape;
  170. }
  171. inline bool Array::getEscapeUnicode() const
  172. {
  173. return _escapeUnicode;
  174. }
  175. inline Array::ValueVec::const_iterator Array::begin() const
  176. {
  177. return _values.begin();
  178. }
  179. inline Array::ValueVec::const_iterator Array::end() const
  180. {
  181. return _values.end();
  182. }
  183. inline std::size_t Array::size() const
  184. {
  185. return static_cast<std::size_t>(_values.size());
  186. }
  187. inline bool Array::isArray(unsigned int index) const
  188. {
  189. Dynamic::Var value = get(index);
  190. return isArray(value);
  191. }
  192. inline bool Array::isArray(const Dynamic::Var& value) const
  193. {
  194. return value.type() == typeid(Array::Ptr);
  195. }
  196. inline bool Array::isArray(ConstIterator& it) const
  197. {
  198. return it!= end() && isArray(*it);
  199. }
  200. inline Array& Array::add(const Dynamic::Var& value)
  201. {
  202. _values.push_back(value);
  203. _modified = true;
  204. return *this;
  205. }
  206. inline Array& Array::set(unsigned int index, const Dynamic::Var& value)
  207. {
  208. if (index >= _values.size()) _values.resize(index + 1);
  209. _values[index] = value;
  210. _modified = true;
  211. return *this;
  212. }
  213. inline void Array::remove(unsigned int index)
  214. {
  215. _values.erase(_values.begin() + index);
  216. }
  217. } } // namespace Poco::JSON
  218. namespace Poco {
  219. namespace Dynamic {
  220. template <>
  221. class VarHolderImpl<JSON::Array::Ptr>: public VarHolder
  222. {
  223. public:
  224. VarHolderImpl(const JSON::Array::Ptr& val): _val(val)
  225. {
  226. }
  227. ~VarHolderImpl()
  228. {
  229. }
  230. const std::type_info& type() const
  231. {
  232. return typeid(JSON::Array::Ptr);
  233. }
  234. void convert(Int8&) const
  235. {
  236. throw BadCastException();
  237. }
  238. void convert(Int16&) const
  239. {
  240. throw BadCastException();
  241. }
  242. void convert(Int32&) const
  243. {
  244. throw BadCastException();
  245. }
  246. void convert(Int64&) const
  247. {
  248. throw BadCastException();
  249. }
  250. void convert(UInt8&) const
  251. {
  252. throw BadCastException();
  253. }
  254. void convert(UInt16&) const
  255. {
  256. throw BadCastException();
  257. }
  258. void convert(UInt32&) const
  259. {
  260. throw BadCastException();
  261. }
  262. void convert(UInt64&) const
  263. {
  264. throw BadCastException();
  265. }
  266. void convert(bool& value) const
  267. {
  268. value = !_val.isNull() && _val->size() > 0;
  269. }
  270. void convert(float&) const
  271. {
  272. throw BadCastException();
  273. }
  274. void convert(double&) const
  275. {
  276. throw BadCastException();
  277. }
  278. void convert(char&) const
  279. {
  280. throw BadCastException();
  281. }
  282. void convert(std::string& s) const
  283. {
  284. std::ostringstream oss;
  285. _val->stringify(oss, 2);
  286. s = oss.str();
  287. }
  288. void convert(DateTime& /*val*/) const
  289. {
  290. throw BadCastException("Cannot convert Array to DateTime");
  291. }
  292. void convert(LocalDateTime& /*ldt*/) const
  293. {
  294. throw BadCastException("Cannot convert Array to LocalDateTime");
  295. }
  296. void convert(Timestamp& /*ts*/) const
  297. {
  298. throw BadCastException("Cannot convert Array to Timestamp");
  299. }
  300. VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
  301. {
  302. return cloneHolder(pVarHolder, _val);
  303. }
  304. const JSON::Array::Ptr& value() const
  305. {
  306. return _val;
  307. }
  308. bool isInteger() const
  309. {
  310. return false;
  311. }
  312. bool isSigned() const
  313. {
  314. return false;
  315. }
  316. bool isNumeric() const
  317. {
  318. return false;
  319. }
  320. bool isString() const
  321. {
  322. return false;
  323. }
  324. private:
  325. JSON::Array::Ptr _val;
  326. };
  327. template <>
  328. class VarHolderImpl<JSON::Array>: public VarHolder
  329. {
  330. public:
  331. VarHolderImpl(const JSON::Array& val): _val(val)
  332. {
  333. }
  334. ~VarHolderImpl()
  335. {
  336. }
  337. const std::type_info& type() const
  338. {
  339. return typeid(JSON::Array);
  340. }
  341. void convert(Int8&) const
  342. {
  343. throw BadCastException();
  344. }
  345. void convert(Int16&) const
  346. {
  347. throw BadCastException();
  348. }
  349. void convert(Int32&) const
  350. {
  351. throw BadCastException();
  352. }
  353. void convert(Int64&) const
  354. {
  355. throw BadCastException();
  356. }
  357. void convert(UInt8&) const
  358. {
  359. throw BadCastException();
  360. }
  361. void convert(UInt16&) const
  362. {
  363. throw BadCastException();
  364. }
  365. void convert(UInt32&) const
  366. {
  367. throw BadCastException();
  368. }
  369. void convert(UInt64&) const
  370. {
  371. throw BadCastException();
  372. }
  373. void convert(bool& value) const
  374. {
  375. value = _val.size() > 0;
  376. }
  377. void convert(float&) const
  378. {
  379. throw BadCastException();
  380. }
  381. void convert(double&) const
  382. {
  383. throw BadCastException();
  384. }
  385. void convert(char&) const
  386. {
  387. throw BadCastException();
  388. }
  389. void convert(std::string& s) const
  390. {
  391. std::ostringstream oss;
  392. _val.stringify(oss, 2);
  393. s = oss.str();
  394. }
  395. void convert(DateTime& /*val*/) const
  396. {
  397. throw BadCastException("Cannot convert Array to DateTime");
  398. }
  399. void convert(LocalDateTime& /*ldt*/) const
  400. {
  401. throw BadCastException("Cannot convert Array to LocalDateTime");
  402. }
  403. void convert(Timestamp& /*ts*/) const
  404. {
  405. throw BadCastException("Cannot convert Array to Timestamp");
  406. }
  407. VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
  408. {
  409. return cloneHolder(pVarHolder, _val);
  410. }
  411. const JSON::Array& value() const
  412. {
  413. return _val;
  414. }
  415. bool isInteger() const
  416. {
  417. return false;
  418. }
  419. bool isSigned() const
  420. {
  421. return false;
  422. }
  423. bool isNumeric() const
  424. {
  425. return false;
  426. }
  427. bool isString() const
  428. {
  429. return false;
  430. }
  431. private:
  432. JSON::Array _val;
  433. };
  434. } } // namespace Poco::Dynamic
  435. #endif // JSON_Array_INCLUDED