Horizon
iter_impl.hpp
1 #pragma once
2 
3 #include <ciso646> // not
4 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
5 #include <type_traits> // conditional, is_const, remove_const
6 
7 #include <nlohmann/detail/exceptions.hpp>
8 #include <nlohmann/detail/iterators/internal_iterator.hpp>
9 #include <nlohmann/detail/iterators/primitive_iterator.hpp>
10 #include <nlohmann/detail/macro_scope.hpp>
11 #include <nlohmann/detail/meta/cpp_future.hpp>
12 #include <nlohmann/detail/meta/type_traits.hpp>
13 #include <nlohmann/detail/value_t.hpp>
14 
15 namespace nlohmann
16 {
17 namespace detail
18 {
19 // forward declare, to be able to friend it later on
20 template<typename IteratorType> class iteration_proxy;
21 template<typename IteratorType> class iteration_proxy_value;
22 
39 template<typename BasicJsonType>
40 class iter_impl
41 {
43  friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
44  friend BasicJsonType;
45  friend iteration_proxy<iter_impl>;
46  friend iteration_proxy_value<iter_impl>;
47 
48  using object_t = typename BasicJsonType::object_t;
49  using array_t = typename BasicJsonType::array_t;
50  // make sure BasicJsonType is basic_json or const basic_json
51  static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
52  "iter_impl only accepts (const) basic_json");
53 
54  public:
55 
61  using iterator_category = std::bidirectional_iterator_tag;
62 
64  using value_type = typename BasicJsonType::value_type;
66  using difference_type = typename BasicJsonType::difference_type;
68  using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
69  typename BasicJsonType::const_pointer,
70  typename BasicJsonType::pointer>::type;
72  using reference =
73  typename std::conditional<std::is_const<BasicJsonType>::value,
74  typename BasicJsonType::const_reference,
75  typename BasicJsonType::reference>::type;
76 
78  iter_impl() = default;
79 
86  explicit iter_impl(pointer object) noexcept : m_object(object)
87  {
88  assert(m_object != nullptr);
89 
90  switch (m_object->m_type)
91  {
92  case value_t::object:
93  {
94  m_it.object_iterator = typename object_t::iterator();
95  break;
96  }
97 
98  case value_t::array:
99  {
100  m_it.array_iterator = typename array_t::iterator();
101  break;
102  }
103 
104  default:
105  {
107  break;
108  }
109  }
110  }
111 
129  : m_object(other.m_object), m_it(other.m_it)
130  {}
131 
139  {
140  m_object = other.m_object;
141  m_it = other.m_it;
142  return *this;
143  }
144 
150  iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
151  : m_object(other.m_object), m_it(other.m_it)
152  {}
153 
160  iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
161  {
162  m_object = other.m_object;
163  m_it = other.m_it;
164  return *this;
165  }
166 
167  private:
172  void set_begin() noexcept
173  {
174  assert(m_object != nullptr);
175 
176  switch (m_object->m_type)
177  {
178  case value_t::object:
179  {
180  m_it.object_iterator = m_object->m_value.object->begin();
181  break;
182  }
183 
184  case value_t::array:
185  {
186  m_it.array_iterator = m_object->m_value.array->begin();
187  break;
188  }
189 
190  case value_t::null:
191  {
192  // set to end so begin()==end() is true: null is empty
194  break;
195  }
196 
197  default:
198  {
200  break;
201  }
202  }
203  }
204 
209  void set_end() noexcept
210  {
211  assert(m_object != nullptr);
212 
213  switch (m_object->m_type)
214  {
215  case value_t::object:
216  {
217  m_it.object_iterator = m_object->m_value.object->end();
218  break;
219  }
220 
221  case value_t::array:
222  {
223  m_it.array_iterator = m_object->m_value.array->end();
224  break;
225  }
226 
227  default:
228  {
230  break;
231  }
232  }
233  }
234 
235  public:
241  {
242  assert(m_object != nullptr);
243 
244  switch (m_object->m_type)
245  {
246  case value_t::object:
247  {
248  assert(m_it.object_iterator != m_object->m_value.object->end());
249  return m_it.object_iterator->second;
250  }
251 
252  case value_t::array:
253  {
254  assert(m_it.array_iterator != m_object->m_value.array->end());
255  return *m_it.array_iterator;
256  }
257 
258  case value_t::null:
259  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
260 
261  default:
262  {
263  if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
264  {
265  return *m_object;
266  }
267 
268  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
269  }
270  }
271  }
272 
278  {
279  assert(m_object != nullptr);
280 
281  switch (m_object->m_type)
282  {
283  case value_t::object:
284  {
285  assert(m_it.object_iterator != m_object->m_value.object->end());
286  return &(m_it.object_iterator->second);
287  }
288 
289  case value_t::array:
290  {
291  assert(m_it.array_iterator != m_object->m_value.array->end());
292  return &*m_it.array_iterator;
293  }
294 
295  default:
296  {
297  if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
298  {
299  return m_object;
300  }
301 
302  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
303  }
304  }
305  }
306 
312  {
313  auto result = *this;
314  ++(*this);
315  return result;
316  }
317 
323  {
324  assert(m_object != nullptr);
325 
326  switch (m_object->m_type)
327  {
328  case value_t::object:
329  {
330  std::advance(m_it.object_iterator, 1);
331  break;
332  }
333 
334  case value_t::array:
335  {
336  std::advance(m_it.array_iterator, 1);
337  break;
338  }
339 
340  default:
341  {
342  ++m_it.primitive_iterator;
343  break;
344  }
345  }
346 
347  return *this;
348  }
349 
355  {
356  auto result = *this;
357  --(*this);
358  return result;
359  }
360 
366  {
367  assert(m_object != nullptr);
368 
369  switch (m_object->m_type)
370  {
371  case value_t::object:
372  {
373  std::advance(m_it.object_iterator, -1);
374  break;
375  }
376 
377  case value_t::array:
378  {
379  std::advance(m_it.array_iterator, -1);
380  break;
381  }
382 
383  default:
384  {
385  --m_it.primitive_iterator;
386  break;
387  }
388  }
389 
390  return *this;
391  }
392 
397  bool operator==(const iter_impl& other) const
398  {
399  // if objects are not the same, the comparison is undefined
400  if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
401  {
402  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
403  }
404 
405  assert(m_object != nullptr);
406 
407  switch (m_object->m_type)
408  {
409  case value_t::object:
410  return (m_it.object_iterator == other.m_it.object_iterator);
411 
412  case value_t::array:
413  return (m_it.array_iterator == other.m_it.array_iterator);
414 
415  default:
416  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
417  }
418  }
419 
424  bool operator!=(const iter_impl& other) const
425  {
426  return not operator==(other);
427  }
428 
433  bool operator<(const iter_impl& other) const
434  {
435  // if objects are not the same, the comparison is undefined
436  if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
437  {
438  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
439  }
440 
441  assert(m_object != nullptr);
442 
443  switch (m_object->m_type)
444  {
445  case value_t::object:
446  JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
447 
448  case value_t::array:
449  return (m_it.array_iterator < other.m_it.array_iterator);
450 
451  default:
452  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
453  }
454  }
455 
460  bool operator<=(const iter_impl& other) const
461  {
462  return not other.operator < (*this);
463  }
464 
469  bool operator>(const iter_impl& other) const
470  {
471  return not operator<=(other);
472  }
473 
478  bool operator>=(const iter_impl& other) const
479  {
480  return not operator<(other);
481  }
482 
488  {
489  assert(m_object != nullptr);
490 
491  switch (m_object->m_type)
492  {
493  case value_t::object:
494  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
495 
496  case value_t::array:
497  {
498  std::advance(m_it.array_iterator, i);
499  break;
500  }
501 
502  default:
503  {
504  m_it.primitive_iterator += i;
505  break;
506  }
507  }
508 
509  return *this;
510  }
511 
517  {
518  return operator+=(-i);
519  }
520 
526  {
527  auto result = *this;
528  result += i;
529  return result;
530  }
531 
537  {
538  auto result = it;
539  result += i;
540  return result;
541  }
542 
548  {
549  auto result = *this;
550  result -= i;
551  return result;
552  }
553 
558  difference_type operator-(const iter_impl& other) const
559  {
560  assert(m_object != nullptr);
561 
562  switch (m_object->m_type)
563  {
564  case value_t::object:
565  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
566 
567  case value_t::array:
568  return m_it.array_iterator - other.m_it.array_iterator;
569 
570  default:
571  return m_it.primitive_iterator - other.m_it.primitive_iterator;
572  }
573  }
574 
580  {
581  assert(m_object != nullptr);
582 
583  switch (m_object->m_type)
584  {
585  case value_t::object:
586  JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
587 
588  case value_t::array:
589  return *std::next(m_it.array_iterator, n);
590 
591  case value_t::null:
592  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
593 
594  default:
595  {
596  if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
597  {
598  return *m_object;
599  }
600 
601  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
602  }
603  }
604  }
605 
610  const typename object_t::key_type& key() const
611  {
612  assert(m_object != nullptr);
613 
614  if (JSON_HEDLEY_LIKELY(m_object->is_object()))
615  {
616  return m_it.object_iterator->first;
617  }
618 
619  JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
620  }
621 
626  reference value() const
627  {
628  return operator*();
629  }
630 
631  private:
633  pointer m_object = nullptr;
636 };
637 } // namespace detail
638 } // namespace nlohmann
nlohmann::detail::iter_impl::operator-
difference_type operator-(const iter_impl &other) const
return difference
Definition: iter_impl.hpp:558
nlohmann::detail::iter_impl::operator->
pointer operator->() const
dereference the iterator
Definition: iter_impl.hpp:277
nlohmann::detail::iter_impl::iter_impl
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition: iter_impl.hpp:150
nlohmann::detail::iter_impl::operator--
iter_impl & operator--()
pre-decrement (–it)
Definition: iter_impl.hpp:365
nlohmann::detail::iter_impl::operator=
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition: iter_impl.hpp:138
nlohmann::detail::iter_impl::operator--
iter_impl const operator--(int)
post-decrement (it–)
Definition: iter_impl.hpp:354
nlohmann::detail::iter_impl::operator==
bool operator==(const iter_impl &other) const
comparison: equal
Definition: iter_impl.hpp:397
nlohmann::detail::value_t::null
@ null
null value
nlohmann::detail::value_t::object
@ object
object (unordered set of name/value pairs)
nlohmann::detail::internal_iterator::object_iterator
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition: internal_iterator.hpp:18
nlohmann::detail::iter_impl::iter_impl
iter_impl()=default
default constructor
nlohmann
namespace for Niels Lohmann
Definition: adl_serializer.hpp:9
nlohmann::detail::primitive_iterator_t::set_end
void set_end() noexcept
set iterator to a defined past the end
Definition: primitive_iterator.hpp:42
nlohmann::detail::iter_impl::operator-
iter_impl operator-(difference_type i) const
subtract from iterator
Definition: iter_impl.hpp:547
nlohmann::detail::iter_impl::iterator_category
std::bidirectional_iterator_tag iterator_category
The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
Definition: iter_impl.hpp:61
nlohmann::detail::iter_impl::operator!=
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: iter_impl.hpp:424
nlohmann::detail::primitive_iterator_t::set_begin
void set_begin() noexcept
set iterator to a defined beginning
Definition: primitive_iterator.hpp:36
nlohmann::detail::primitive_iterator_t::is_begin
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition: primitive_iterator.hpp:48
nlohmann::detail::iter_impl
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition: iter_impl.hpp:41
nlohmann::detail::internal_iterator::array_iterator
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition: internal_iterator.hpp:20
nlohmann::detail::iter_impl::reference
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition: iter_impl.hpp:75
nlohmann::detail::iter_impl::operator++
iter_impl & operator++()
pre-increment (++it)
Definition: iter_impl.hpp:322
nlohmann::detail::iter_impl::operator>=
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: iter_impl.hpp:478
nlohmann::detail::iter_impl::iter_impl
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition: iter_impl.hpp:128
nlohmann::detail::iter_impl::operator<=
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: iter_impl.hpp:460
nlohmann::detail::iter_impl::operator++
iter_impl const operator++(int)
post-increment (it++)
Definition: iter_impl.hpp:311
nlohmann::detail::iter_impl::operator*
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: iter_impl.hpp:240
nlohmann::detail::iter_impl::operator<
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: iter_impl.hpp:433
nlohmann::detail::internal_iterator::primitive_iterator
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition: internal_iterator.hpp:22
nlohmann::detail::value_t::array
@ array
array (ordered collection of values)
nlohmann::detail::primitive_iterator_t
Definition: primitive_iterator.hpp:20
nlohmann::detail::iter_impl::iter_impl
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: iter_impl.hpp:86
nlohmann::detail::iter_impl::operator>
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: iter_impl.hpp:469
nlohmann::detail::iter_impl::operator+
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition: iter_impl.hpp:536
nlohmann::detail::iter_impl::operator=
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition: iter_impl.hpp:160
nlohmann::detail::iter_impl::operator-=
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: iter_impl.hpp:516
nlohmann::detail::internal_iterator
an iterator value
Definition: internal_iterator.hpp:16
nlohmann::detail::iter_impl::value_type
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition: iter_impl.hpp:64
nlohmann::detail::iter_impl::operator+
iter_impl operator+(difference_type i) const
add to iterator
Definition: iter_impl.hpp:525
nlohmann::detail::iter_impl::operator[]
reference operator[](difference_type n) const
access to successor
Definition: iter_impl.hpp:579
nlohmann::detail::iter_impl::difference_type
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition: iter_impl.hpp:66
nlohmann::detail::iter_impl::key
const object_t::key_type & key() const
return the key of an object iterator
Definition: iter_impl.hpp:610
nlohmann::detail::iter_impl::pointer
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition: iter_impl.hpp:70
nlohmann::detail::iter_impl::value
reference value() const
return the value of an iterator
Definition: iter_impl.hpp:626
nlohmann::detail::iter_impl::operator+=
iter_impl & operator+=(difference_type i)
add to iterator
Definition: iter_impl.hpp:487