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.hpp>
12 #include <nlohmann/detail/value_t.hpp>
13 
14 namespace nlohmann
15 {
16 namespace detail
17 {
18 // forward declare, to be able to friend it later on
19 template<typename IteratorType> class iteration_proxy;
20 
41 template<typename BasicJsonType>
42 class iter_impl
43 {
45  friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
46  friend BasicJsonType;
48 
49  using object_t = typename BasicJsonType::object_t;
50  using array_t = typename BasicJsonType::array_t;
51  // make sure BasicJsonType is basic_json or const basic_json
52  static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
53  "iter_impl only accepts (const) basic_json");
54 
55  public:
56 
62  using iterator_category = std::bidirectional_iterator_tag;
63 
65  using value_type = typename BasicJsonType::value_type;
67  using difference_type = typename BasicJsonType::difference_type;
69  using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
70  typename BasicJsonType::const_pointer,
71  typename BasicJsonType::pointer>::type;
73  using reference =
74  typename std::conditional<std::is_const<BasicJsonType>::value,
75  typename BasicJsonType::const_reference,
76  typename BasicJsonType::reference>::type;
77 
79  iter_impl() = default;
80 
87  explicit iter_impl(pointer object) noexcept : m_object(object)
88  {
89  assert(m_object != nullptr);
90 
91  switch (m_object->m_type)
92  {
93  case value_t::object:
94  {
95  m_it.object_iterator = typename object_t::iterator();
96  break;
97  }
98 
99  case value_t::array:
100  {
101  m_it.array_iterator = typename array_t::iterator();
102  break;
103  }
104 
105  default:
106  {
108  break;
109  }
110  }
111  }
112 
127  iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
128  : m_object(other.m_object), m_it(other.m_it) {}
129 
136  iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
137  {
138  m_object = other.m_object;
139  m_it = other.m_it;
140  return *this;
141  }
142 
143  private:
148  void set_begin() noexcept
149  {
150  assert(m_object != nullptr);
151 
152  switch (m_object->m_type)
153  {
154  case value_t::object:
155  {
156  m_it.object_iterator = m_object->m_value.object->begin();
157  break;
158  }
159 
160  case value_t::array:
161  {
162  m_it.array_iterator = m_object->m_value.array->begin();
163  break;
164  }
165 
166  case value_t::null:
167  {
168  // set to end so begin()==end() is true: null is empty
170  break;
171  }
172 
173  default:
174  {
176  break;
177  }
178  }
179  }
180 
185  void set_end() noexcept
186  {
187  assert(m_object != nullptr);
188 
189  switch (m_object->m_type)
190  {
191  case value_t::object:
192  {
193  m_it.object_iterator = m_object->m_value.object->end();
194  break;
195  }
196 
197  case value_t::array:
198  {
199  m_it.array_iterator = m_object->m_value.array->end();
200  break;
201  }
202 
203  default:
204  {
206  break;
207  }
208  }
209  }
210 
211  public:
217  {
218  assert(m_object != nullptr);
219 
220  switch (m_object->m_type)
221  {
222  case value_t::object:
223  {
224  assert(m_it.object_iterator != m_object->m_value.object->end());
225  return m_it.object_iterator->second;
226  }
227 
228  case value_t::array:
229  {
230  assert(m_it.array_iterator != m_object->m_value.array->end());
231  return *m_it.array_iterator;
232  }
233 
234  case value_t::null:
235  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
236 
237  default:
238  {
239  if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
240  {
241  return *m_object;
242  }
243 
244  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
245  }
246  }
247  }
248 
254  {
255  assert(m_object != nullptr);
256 
257  switch (m_object->m_type)
258  {
259  case value_t::object:
260  {
261  assert(m_it.object_iterator != m_object->m_value.object->end());
262  return &(m_it.object_iterator->second);
263  }
264 
265  case value_t::array:
266  {
267  assert(m_it.array_iterator != m_object->m_value.array->end());
268  return &*m_it.array_iterator;
269  }
270 
271  default:
272  {
273  if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
274  {
275  return m_object;
276  }
277 
278  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
279  }
280  }
281  }
282 
288  {
289  auto result = *this;
290  ++(*this);
291  return result;
292  }
293 
299  {
300  assert(m_object != nullptr);
301 
302  switch (m_object->m_type)
303  {
304  case value_t::object:
305  {
306  std::advance(m_it.object_iterator, 1);
307  break;
308  }
309 
310  case value_t::array:
311  {
312  std::advance(m_it.array_iterator, 1);
313  break;
314  }
315 
316  default:
317  {
318  ++m_it.primitive_iterator;
319  break;
320  }
321  }
322 
323  return *this;
324  }
325 
331  {
332  auto result = *this;
333  --(*this);
334  return result;
335  }
336 
342  {
343  assert(m_object != nullptr);
344 
345  switch (m_object->m_type)
346  {
347  case value_t::object:
348  {
349  std::advance(m_it.object_iterator, -1);
350  break;
351  }
352 
353  case value_t::array:
354  {
355  std::advance(m_it.array_iterator, -1);
356  break;
357  }
358 
359  default:
360  {
361  --m_it.primitive_iterator;
362  break;
363  }
364  }
365 
366  return *this;
367  }
368 
373  bool operator==(const iter_impl& other) const
374  {
375  // if objects are not the same, the comparison is undefined
376  if (JSON_UNLIKELY(m_object != other.m_object))
377  {
378  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
379  }
380 
381  assert(m_object != nullptr);
382 
383  switch (m_object->m_type)
384  {
385  case value_t::object:
386  return (m_it.object_iterator == other.m_it.object_iterator);
387 
388  case value_t::array:
389  return (m_it.array_iterator == other.m_it.array_iterator);
390 
391  default:
392  return (m_it.primitive_iterator == other.m_it.primitive_iterator);
393  }
394  }
395 
400  bool operator!=(const iter_impl& other) const
401  {
402  return not operator==(other);
403  }
404 
409  bool operator<(const iter_impl& other) const
410  {
411  // if objects are not the same, the comparison is undefined
412  if (JSON_UNLIKELY(m_object != other.m_object))
413  {
414  JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
415  }
416 
417  assert(m_object != nullptr);
418 
419  switch (m_object->m_type)
420  {
421  case value_t::object:
422  JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
423 
424  case value_t::array:
425  return (m_it.array_iterator < other.m_it.array_iterator);
426 
427  default:
428  return (m_it.primitive_iterator < other.m_it.primitive_iterator);
429  }
430  }
431 
436  bool operator<=(const iter_impl& other) const
437  {
438  return not other.operator < (*this);
439  }
440 
445  bool operator>(const iter_impl& other) const
446  {
447  return not operator<=(other);
448  }
449 
454  bool operator>=(const iter_impl& other) const
455  {
456  return not operator<(other);
457  }
458 
464  {
465  assert(m_object != nullptr);
466 
467  switch (m_object->m_type)
468  {
469  case value_t::object:
470  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
471 
472  case value_t::array:
473  {
474  std::advance(m_it.array_iterator, i);
475  break;
476  }
477 
478  default:
479  {
480  m_it.primitive_iterator += i;
481  break;
482  }
483  }
484 
485  return *this;
486  }
487 
493  {
494  return operator+=(-i);
495  }
496 
502  {
503  auto result = *this;
504  result += i;
505  return result;
506  }
507 
513  {
514  auto result = it;
515  result += i;
516  return result;
517  }
518 
524  {
525  auto result = *this;
526  result -= i;
527  return result;
528  }
529 
534  difference_type operator-(const iter_impl& other) const
535  {
536  assert(m_object != nullptr);
537 
538  switch (m_object->m_type)
539  {
540  case value_t::object:
541  JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
542 
543  case value_t::array:
544  return m_it.array_iterator - other.m_it.array_iterator;
545 
546  default:
547  return m_it.primitive_iterator - other.m_it.primitive_iterator;
548  }
549  }
550 
556  {
557  assert(m_object != nullptr);
558 
559  switch (m_object->m_type)
560  {
561  case value_t::object:
562  JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
563 
564  case value_t::array:
565  return *std::next(m_it.array_iterator, n);
566 
567  case value_t::null:
568  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
569 
570  default:
571  {
572  if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
573  {
574  return *m_object;
575  }
576 
577  JSON_THROW(invalid_iterator::create(214, "cannot get value"));
578  }
579  }
580  }
581 
586  typename object_t::key_type key() const
587  {
588  assert(m_object != nullptr);
589 
590  if (JSON_LIKELY(m_object->is_object()))
591  {
592  return m_it.object_iterator->first;
593  }
594 
595  JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators"));
596  }
597 
602  reference value() const
603  {
604  return operator*();
605  }
606 
607  private:
609  pointer m_object = nullptr;
612 };
613 }
614 }
nlohmann::detail::iter_impl::operator-
difference_type operator-(const iter_impl &other) const
return difference
Definition: iter_impl.hpp:534
nlohmann::detail::iter_impl::operator->
pointer operator->() const
dereference the iterator
Definition: iter_impl.hpp:253
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:127
nlohmann::detail::iter_impl::operator--
iter_impl & operator--()
pre-decrement (–it)
Definition: iter_impl.hpp:341
nlohmann::detail::iter_impl::operator++
const iter_impl operator++(int)
post-increment (it++)
Definition: iter_impl.hpp:287
nlohmann::detail::iter_impl::operator==
bool operator==(const iter_impl &other) const
comparison: equal
Definition: iter_impl.hpp:373
nlohmann::detail::value_t::null
null value
nlohmann::detail::value_t::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
namespace for Niels Lohmann
Definition: adl_serializer.hpp:8
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:523
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:62
nlohmann::detail::iter_impl::key
object_t::key_type key() const
return the key of an object iterator
Definition: iter_impl.hpp:586
nlohmann::detail::iter_impl::operator!=
bool operator!=(const iter_impl &other) const
comparison: not equal
Definition: iter_impl.hpp:400
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
Definition: iter_impl.hpp:42
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:76
nlohmann::detail::iter_impl::operator++
iter_impl & operator++()
pre-increment (++it)
Definition: iter_impl.hpp:298
nlohmann::detail::iter_impl::operator>=
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition: iter_impl.hpp:454
nlohmann::detail::iter_impl::operator<=
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition: iter_impl.hpp:436
nlohmann::detail::iter_impl::operator*
reference operator*() const
return a reference to the value pointed to by the iterator
Definition: iter_impl.hpp:216
nlohmann::detail::iter_impl::operator<
bool operator<(const iter_impl &other) const
comparison: smaller
Definition: iter_impl.hpp:409
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 (ordered collection of values)
nlohmann::detail::primitive_iterator_t
Definition: primitive_iterator.hpp:19
nlohmann::detail::iter_impl::iter_impl
iter_impl(pointer object) noexcept
constructor for a given JSON instance
Definition: iter_impl.hpp:87
nlohmann::detail::iter_impl::iter_impl
iter_impl()=default
default constructor
Definition: iter_impl.hpp:45
nlohmann::detail::iter_impl::operator>
bool operator>(const iter_impl &other) const
comparison: greater than
Definition: iter_impl.hpp:445
nlohmann::detail::is_basic_json
Definition: meta.hpp:28
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:512
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:136
nlohmann::detail::iter_impl::operator-=
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition: iter_impl.hpp:492
nlohmann::detail::internal_iterator
an iterator value
Definition: internal_iterator.hpp:15
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:65
nlohmann::detail::iter_impl::operator+
iter_impl operator+(difference_type i) const
add to iterator
Definition: iter_impl.hpp:501
nlohmann::detail::iter_impl::operator[]
reference operator[](difference_type n) const
access to successor
Definition: iter_impl.hpp:555
nlohmann::detail::iter_impl::difference_type
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition: iter_impl.hpp:67
nlohmann::detail::iteration_proxy
proxy class for the items() function
Definition: iter_impl.hpp:19
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:71
nlohmann::detail::iter_impl::operator--
const iter_impl operator--(int)
post-decrement (it–)
Definition: iter_impl.hpp:330
nlohmann::detail::iter_impl::value
reference value() const
return the value of an iterator
Definition: iter_impl.hpp:602
nlohmann::detail::iter_impl::operator+=
iter_impl & operator+=(difference_type i)
add to iterator
Definition: iter_impl.hpp:463