json_iterator.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. // Copyright (c) 2018-2020 Jsonxx - Nomango
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. #pragma once
  21. #include <cstddef>
  22. #include <iterator>
  23. #include "json_value.hpp"
  24. namespace jsonxx {
  25. //
  26. // iterator for basic_json
  27. //
  28. struct primitive_iterator {
  29. using difference_type = std::ptrdiff_t;
  30. inline primitive_iterator(int it = 0) : it_(it) {}
  31. inline void set_begin() { it_ = 0; }
  32. inline void set_end() { it_ = 1; }
  33. inline primitive_iterator &operator++() {
  34. ++it_;
  35. return *this;
  36. }
  37. inline primitive_iterator operator++(int) {
  38. primitive_iterator old(it_);
  39. ++(*this);
  40. return old;
  41. }
  42. inline primitive_iterator &operator--() {
  43. --it_;
  44. return (*this);
  45. }
  46. inline primitive_iterator operator--(int) {
  47. primitive_iterator old = (*this);
  48. --(*this);
  49. return old;
  50. }
  51. inline bool operator==(primitive_iterator const &other) const { return it_ == other.it_; }
  52. inline bool operator!=(primitive_iterator const &other) const { return !(*this == other); }
  53. inline const primitive_iterator operator+(difference_type off) const { return primitive_iterator(it_ + off); }
  54. inline const primitive_iterator operator-(difference_type off) const { return primitive_iterator(it_ - off); }
  55. inline primitive_iterator &operator+=(difference_type off) {
  56. it_ += off;
  57. return (*this);
  58. }
  59. inline primitive_iterator &operator-=(difference_type off) {
  60. it_ -= off;
  61. return (*this);
  62. }
  63. inline difference_type operator-(primitive_iterator const &other) const { return it_ - other.it_; }
  64. inline bool operator<(primitive_iterator const &other) const { return it_ < other.it_; }
  65. inline bool operator<=(primitive_iterator const &other) const { return it_ <= other.it_; }
  66. inline bool operator>(primitive_iterator const &other) const { return it_ > other.it_; }
  67. inline bool operator>=(primitive_iterator const &other) const { return it_ >= other.it_; }
  68. private:
  69. int it_;
  70. };
  71. template<typename _BasicJsonTy>
  72. struct internal_iterator {
  73. typename _BasicJsonTy::array_type::iterator array_iter;
  74. typename _BasicJsonTy::object_type::iterator object_iter;
  75. primitive_iterator original_iter = 0; // for other types
  76. };
  77. template<typename _BasicJsonTy>
  78. struct iterator_impl {
  79. friend _BasicJsonTy;
  80. using string_type = typename _BasicJsonTy::string_type;
  81. using char_type = typename _BasicJsonTy::char_type;
  82. using integer_type = typename _BasicJsonTy::integer_type;
  83. using float_type = typename _BasicJsonTy::float_type;
  84. using boolean_type = typename _BasicJsonTy::boolean_type;
  85. using array_type = typename _BasicJsonTy::array_type;
  86. using object_type = typename _BasicJsonTy::object_type;
  87. using value_type = _BasicJsonTy;
  88. using difference_type = std::ptrdiff_t;
  89. using iterator_category = std::bidirectional_iterator_tag;
  90. using pointer = value_type *;
  91. using reference = value_type &;
  92. inline iterator_impl(pointer json = nullptr) : data_(json) {}
  93. inline reference operator*() const {
  94. check_data();
  95. check_iterator();
  96. switch (data_->type()) {
  97. case json_type::object:
  98. return (it_.object_iter->second);
  99. case json_type::array:
  100. return (*it_.array_iter);
  101. default:
  102. return *data_;
  103. }
  104. }
  105. inline pointer operator->() const {
  106. check_data();
  107. check_iterator();
  108. switch (data_->type()) {
  109. case json_type::object:
  110. return &(it_.object_iter->second);
  111. case json_type::array:
  112. return &(*it_.array_iter);
  113. default:
  114. return data_;
  115. }
  116. }
  117. inline const typename object_type::key_type &key() const {
  118. check_data();
  119. check_iterator();
  120. if (!data_->is_object())
  121. throw json_invalid_iterator("cannot use key() with non-object type");
  122. return it_.object_iter->first;
  123. }
  124. inline reference value() const {
  125. return operator*();
  126. }
  127. inline void set_begin() {
  128. check_data();
  129. switch (data_->type()) {
  130. case json_type::object: {
  131. it_.object_iter = data_->value_.data.object->begin();
  132. break;
  133. }
  134. case json_type::array: {
  135. it_.array_iter = data_->value_.data.vector->begin();
  136. break;
  137. }
  138. default: {
  139. it_.original_iter.set_begin();
  140. break;
  141. }
  142. }
  143. }
  144. inline void set_end() {
  145. check_data();
  146. switch (data_->type()) {
  147. case json_type::object: {
  148. it_.object_iter = data_->value_.data.object->end();
  149. break;
  150. }
  151. case json_type::array: {
  152. it_.array_iter = data_->value_.data.vector->end();
  153. break;
  154. }
  155. default: {
  156. it_.original_iter.set_end();
  157. break;
  158. }
  159. }
  160. }
  161. inline iterator_impl operator++(int) {
  162. iterator_impl old = (*this);
  163. ++(*this);
  164. return old;
  165. }
  166. inline iterator_impl &operator++() {
  167. check_data();
  168. switch (data_->type()) {
  169. case json_type::object: {
  170. std::advance(it_.object_iter, 1);
  171. break;
  172. }
  173. case json_type::array: {
  174. std::advance(it_.array_iter, 1);
  175. break;
  176. }
  177. default: {
  178. ++it_.original_iter;
  179. break;
  180. }
  181. }
  182. return *this;
  183. }
  184. inline iterator_impl operator--(int) {
  185. iterator_impl old = (*this);
  186. --(*this);
  187. return old;
  188. }
  189. inline iterator_impl &operator--() {
  190. check_data();
  191. switch (data_->type()) {
  192. case json_type::object: {
  193. std::advance(it_.object_iter, -1);
  194. break;
  195. }
  196. case json_type::array: {
  197. std::advance(it_.array_iter, -1);
  198. break;
  199. }
  200. default: {
  201. --it_.original_iter;
  202. break;
  203. }
  204. }
  205. }
  206. inline const iterator_impl operator-(difference_type off) const { return operator+(-off); }
  207. inline const iterator_impl operator+(difference_type off) const {
  208. iterator_impl ret(*this);
  209. ret += off;
  210. return ret;
  211. }
  212. inline iterator_impl &operator-=(difference_type off) { return operator+=(-off); }
  213. inline iterator_impl &operator+=(difference_type off) {
  214. check_data();
  215. switch (data_->type()) {
  216. case json_type::object: {
  217. throw json_invalid_iterator("cannot use offsets with object type");
  218. break;
  219. }
  220. case json_type::array: {
  221. std::advance(it_.array_iter, off);
  222. break;
  223. }
  224. default: {
  225. it_.original_iter += off;
  226. break;
  227. }
  228. }
  229. return *this;
  230. }
  231. inline bool operator!=(iterator_impl const &other) const { return !(*this == other); }
  232. inline bool operator==(iterator_impl const &other) const {
  233. check_data();
  234. other.check_data();
  235. if (data_ != other.data_)
  236. throw json_invalid_iterator("cannot compare iterators of different objects");
  237. switch (data_->type()) {
  238. case json_type::object: {
  239. return it_.object_iter == other.it_.object_iter;
  240. }
  241. case json_type::array: {
  242. return it_.array_iter == other.it_.array_iter;
  243. }
  244. default: {
  245. return it_.original_iter == other.it_.original_iter;
  246. }
  247. }
  248. }
  249. inline bool operator>(iterator_impl const &other) const { return other.operator<(*this); }
  250. inline bool operator>=(iterator_impl const &other) const { return !operator<(other); }
  251. inline bool operator<=(iterator_impl const &other) const { return !other.operator<(*this); }
  252. inline bool operator<(iterator_impl const &other) const {
  253. check_data();
  254. other.check_data();
  255. if (data_ != other.data_)
  256. throw json_invalid_iterator("cannot compare iterators of different objects");
  257. switch (data_->type()) {
  258. case json_type::object:
  259. throw json_invalid_iterator("cannot compare iterators with object type");
  260. case json_type::array:
  261. return it_.array_iter < other.it_.array_iter;
  262. default:
  263. return it_.original_iter < other.it_.original_iter;
  264. }
  265. }
  266. private:
  267. inline void check_data() const {
  268. if (data_ == nullptr) {
  269. throw json_invalid_iterator("iterator contains an empty object");
  270. }
  271. }
  272. inline void check_iterator() const {
  273. switch (data_->type()) {
  274. case json_type::object:
  275. if (it_.object_iter == data_->value_.data.object->end()) {
  276. throw std::out_of_range("iterator out of range");
  277. }
  278. break;
  279. case json_type::array:
  280. if (it_.array_iter == data_->value_.data.vector->end()) {
  281. throw std::out_of_range("iterator out of range");
  282. }
  283. break;
  284. default:
  285. if (it_.original_iter == 1) {
  286. throw std::out_of_range("iterator out of range");
  287. }
  288. break;
  289. }
  290. }
  291. private:
  292. pointer data_;
  293. internal_iterator<_BasicJsonTy> it_;
  294. };
  295. } // namespace Jsonxx