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