Horizon
Loading...
Searching...
No Matches
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
14namespace nlohmann
15{
16namespace detail
17{
18// forward declare, to be able to friend it later on
19template<typename IteratorType> class iteration_proxy;
20template<typename IteratorType> class iteration_proxy_value;
21
38template<typename BasicJsonType>
40{
42 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
44 friend other_iter_impl;
45 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
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
78 iter_impl() = default;
79 ~iter_impl() = default;
80 iter_impl(iter_impl&&) noexcept = default;
81 iter_impl& operator=(iter_impl&&) noexcept = default;
82
89 explicit iter_impl(pointer object) noexcept : m_object(object)
90 {
91 JSON_ASSERT(m_object != nullptr);
92
93 switch (m_object->m_type)
94 {
95 case value_t::object:
96 {
97 m_it.object_iterator = typename object_t::iterator();
98 break;
99 }
100
101 case value_t::array:
102 {
103 m_it.array_iterator = typename array_t::iterator();
104 break;
105 }
106
107 case value_t::null:
108 case value_t::string:
109 case value_t::boolean:
113 case value_t::binary:
115 default:
116 {
118 break;
119 }
120 }
121 }
122
140 : m_object(other.m_object), m_it(other.m_it)
141 {}
142
150 {
151 if (&other != this)
152 {
153 m_object = other.m_object;
154 m_it = other.m_it;
155 }
156 return *this;
157 }
158
164 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
165 : m_object(other.m_object), m_it(other.m_it)
166 {}
167
174 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
175 {
176 m_object = other.m_object;
177 m_it = other.m_it;
178 return *this;
179 }
180
181 JSON_PRIVATE_UNLESS_TESTED:
186 void set_begin() noexcept
187 {
188 JSON_ASSERT(m_object != nullptr);
189
190 switch (m_object->m_type)
191 {
192 case value_t::object:
193 {
194 m_it.object_iterator = m_object->m_value.object->begin();
195 break;
196 }
197
198 case value_t::array:
199 {
200 m_it.array_iterator = m_object->m_value.array->begin();
201 break;
202 }
203
204 case value_t::null:
205 {
206 // set to end so begin()==end() is true: null is empty
208 break;
209 }
210
211 case value_t::string:
212 case value_t::boolean:
216 case value_t::binary:
218 default:
219 {
221 break;
222 }
223 }
224 }
225
230 void set_end() noexcept
231 {
232 JSON_ASSERT(m_object != nullptr);
233
234 switch (m_object->m_type)
235 {
236 case value_t::object:
237 {
238 m_it.object_iterator = m_object->m_value.object->end();
239 break;
240 }
241
242 case value_t::array:
243 {
244 m_it.array_iterator = m_object->m_value.array->end();
245 break;
246 }
247
248 case value_t::null:
249 case value_t::string:
250 case value_t::boolean:
254 case value_t::binary:
256 default:
257 {
259 break;
260 }
261 }
262 }
263
264 public:
270 {
271 JSON_ASSERT(m_object != nullptr);
272
273 switch (m_object->m_type)
274 {
275 case value_t::object:
276 {
277 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
278 return m_it.object_iterator->second;
279 }
280
281 case value_t::array:
282 {
283 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
284 return *m_it.array_iterator;
285 }
286
287 case value_t::null:
288 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
289
290 case value_t::string:
291 case value_t::boolean:
295 case value_t::binary:
297 default:
298 {
299 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
300 {
301 return *m_object;
302 }
303
304 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
305 }
306 }
307 }
308
314 {
315 JSON_ASSERT(m_object != nullptr);
316
317 switch (m_object->m_type)
318 {
319 case value_t::object:
320 {
321 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
322 return &(m_it.object_iterator->second);
323 }
324
325 case value_t::array:
326 {
327 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
328 return &*m_it.array_iterator;
329 }
330
331 case value_t::null:
332 case value_t::string:
333 case value_t::boolean:
337 case value_t::binary:
339 default:
340 {
341 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
342 {
343 return m_object;
344 }
345
346 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
347 }
348 }
349 }
350
355 iter_impl const operator++(int) // NOLINT(readability-const-return-type)
356 {
357 auto result = *this;
358 ++(*this);
359 return result;
360 }
361
367 {
368 JSON_ASSERT(m_object != nullptr);
369
370 switch (m_object->m_type)
371 {
372 case value_t::object:
373 {
374 std::advance(m_it.object_iterator, 1);
375 break;
376 }
377
378 case value_t::array:
379 {
380 std::advance(m_it.array_iterator, 1);
381 break;
382 }
383
384 case value_t::null:
385 case value_t::string:
386 case value_t::boolean:
390 case value_t::binary:
392 default:
393 {
395 break;
396 }
397 }
398
399 return *this;
400 }
401
406 iter_impl const operator--(int) // NOLINT(readability-const-return-type)
407 {
408 auto result = *this;
409 --(*this);
410 return result;
411 }
412
418 {
419 JSON_ASSERT(m_object != nullptr);
420
421 switch (m_object->m_type)
422 {
423 case value_t::object:
424 {
425 std::advance(m_it.object_iterator, -1);
426 break;
427 }
428
429 case value_t::array:
430 {
431 std::advance(m_it.array_iterator, -1);
432 break;
433 }
434
435 case value_t::null:
436 case value_t::string:
437 case value_t::boolean:
441 case value_t::binary:
443 default:
444 {
446 break;
447 }
448 }
449
450 return *this;
451 }
452
457 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
458 bool operator==(const IterImpl& other) const
459 {
460 // if objects are not the same, the comparison is undefined
461 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
462 {
463 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
464 }
465
466 JSON_ASSERT(m_object != nullptr);
467
468 switch (m_object->m_type)
469 {
470 case value_t::object:
471 return (m_it.object_iterator == other.m_it.object_iterator);
472
473 case value_t::array:
474 return (m_it.array_iterator == other.m_it.array_iterator);
475
476 case value_t::null:
477 case value_t::string:
478 case value_t::boolean:
482 case value_t::binary:
484 default:
485 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
486 }
487 }
488
493 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
494 bool operator!=(const IterImpl& other) const
495 {
496 return !operator==(other);
497 }
498
503 bool operator<(const iter_impl& other) const
504 {
505 // if objects are not the same, the comparison is undefined
506 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
507 {
508 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
509 }
510
511 JSON_ASSERT(m_object != nullptr);
512
513 switch (m_object->m_type)
514 {
515 case value_t::object:
516 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
517
518 case value_t::array:
519 return (m_it.array_iterator < other.m_it.array_iterator);
520
521 case value_t::null:
522 case value_t::string:
523 case value_t::boolean:
527 case value_t::binary:
529 default:
531 }
532 }
533
538 bool operator<=(const iter_impl& other) const
539 {
540 return !other.operator < (*this);
541 }
542
547 bool operator>(const iter_impl& other) const
548 {
549 return !operator<=(other);
550 }
551
556 bool operator>=(const iter_impl& other) const
557 {
558 return !operator<(other);
559 }
560
566 {
567 JSON_ASSERT(m_object != nullptr);
568
569 switch (m_object->m_type)
570 {
571 case value_t::object:
572 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
573
574 case value_t::array:
575 {
576 std::advance(m_it.array_iterator, i);
577 break;
578 }
579
580 case value_t::null:
581 case value_t::string:
582 case value_t::boolean:
586 case value_t::binary:
588 default:
589 {
591 break;
592 }
593 }
594
595 return *this;
596 }
597
603 {
604 return operator+=(-i);
605 }
606
612 {
613 auto result = *this;
614 result += i;
615 return result;
616 }
617
623 {
624 auto result = it;
625 result += i;
626 return result;
627 }
628
634 {
635 auto result = *this;
636 result -= i;
637 return result;
638 }
639
645 {
646 JSON_ASSERT(m_object != nullptr);
647
648 switch (m_object->m_type)
649 {
650 case value_t::object:
651 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
652
653 case value_t::array:
654 return m_it.array_iterator - other.m_it.array_iterator;
655
656 case value_t::null:
657 case value_t::string:
658 case value_t::boolean:
662 case value_t::binary:
664 default:
666 }
667 }
668
674 {
675 JSON_ASSERT(m_object != nullptr);
676
677 switch (m_object->m_type)
678 {
679 case value_t::object:
680 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
681
682 case value_t::array:
683 return *std::next(m_it.array_iterator, n);
684
685 case value_t::null:
686 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
687
688 case value_t::string:
689 case value_t::boolean:
693 case value_t::binary:
695 default:
696 {
697 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
698 {
699 return *m_object;
700 }
701
702 JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
703 }
704 }
705 }
706
711 const typename object_t::key_type& key() const
712 {
713 JSON_ASSERT(m_object != nullptr);
714
715 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
716 {
717 return m_it.object_iterator->first;
718 }
719
720 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
721 }
722
728 {
729 return operator*();
730 }
731
732 JSON_PRIVATE_UNLESS_TESTED:
734 pointer m_object = nullptr;
737};
738} // namespace detail
739} // 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:503
iter_impl operator-(difference_type i) const
subtract from iterator
Definition iter_impl.hpp:633
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition iter_impl.hpp:494
iter_impl const operator--(int)
post-decrement (it–)
Definition iter_impl.hpp:406
void set_end() noexcept
set the iterator past the last value
Definition iter_impl.hpp:230
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition iter_impl.hpp:67
iter_impl & operator--()
pre-decrement (–it)
Definition iter_impl.hpp:417
difference_type operator-(const iter_impl &other) const
return difference
Definition iter_impl.hpp:644
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition iter_impl.hpp:149
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
reference operator*() const
return a reference to the value pointed to by the iterator
Definition iter_impl.hpp:269
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition iter_impl.hpp:556
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
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition iter_impl.hpp:174
pointer operator->() const
dereference the iterator
Definition iter_impl.hpp:313
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition iter_impl.hpp:139
iter_impl const operator++(int)
post-increment (it++)
Definition iter_impl.hpp:355
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition iter_impl.hpp:164
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition iter_impl.hpp:736
iter_impl operator+(difference_type i) const
add to iterator
Definition iter_impl.hpp:611
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition iter_impl.hpp:622
const object_t::key_type & key() const
return the key of an object iterator
Definition iter_impl.hpp:711
bool operator==(const IterImpl &other) const
comparison: equal
Definition iter_impl.hpp:458
bool operator>(const iter_impl &other) const
comparison: greater than
Definition iter_impl.hpp:547
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition iter_impl.hpp:65
reference value() const
return the value of an iterator
Definition iter_impl.hpp:727
iter_impl & operator++()
pre-increment (++it)
Definition iter_impl.hpp:366
reference operator[](difference_type n) const
access to successor
Definition iter_impl.hpp:673
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition iter_impl.hpp:538
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
iter_impl & operator+=(difference_type i)
add to iterator
Definition iter_impl.hpp:565
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition iter_impl.hpp:602
Definition iteration_proxy.hpp:24
proxy class for the items() function
Definition iteration_proxy.hpp:122
Definition primitive_iterator.hpp:22
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition primitive_iterator.hpp:51
void set_begin() noexcept
set iterator to a defined beginning
Definition primitive_iterator.hpp:39
void set_end() noexcept
set iterator to a defined past the end
Definition primitive_iterator.hpp:45
@ number_integer
number value (signed integer)
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
namespace for Niels Lohmann
Definition adl_serializer.hpp:12
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:42