]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentelemetry-cpp/third_party/nlohmann-json/include/nlohmann/detail/iterators/iter_impl.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / third_party / nlohmann-json / include / nlohmann / detail / iterators / 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
22 /*!
23 @brief a template for a bidirectional iterator for the @ref basic_json class
24 This class implements a both iterators (iterator and const_iterator) for the
25 @ref basic_json class.
26 @note An iterator is called *initialized* when a pointer to a JSON value has
27 been set (e.g., by a constructor or a copy assignment). If the iterator is
28 default-constructed, it is *uninitialized* and most methods are undefined.
29 **The library uses assertions to detect calls on uninitialized iterators.**
30 @requirement The class satisfies the following concept requirements:
31 -
32 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
33 The iterator that can be moved can be moved in both directions (i.e.
34 incremented and decremented).
35 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
36 iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
37 */
38 template<typename BasicJsonType>
39 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
40 {
41 /// the iterator with BasicJsonType of different const-ness
42 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
43 /// allow basic_json to access private members
44 friend other_iter_impl;
45 friend BasicJsonType;
46 friend iteration_proxy<iter_impl>;
47 friend iteration_proxy_value<iter_impl>;
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
57 /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
58 /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
59 /// A user-defined iterator should provide publicly accessible typedefs named
60 /// iterator_category, value_type, difference_type, pointer, and reference.
61 /// Note that value_type is required to be non-const, even for constant iterators.
62 using iterator_category = std::bidirectional_iterator_tag;
63
64 /// the type of the values when the iterator is dereferenced
65 using value_type = typename BasicJsonType::value_type;
66 /// a type to represent differences between iterators
67 using difference_type = typename BasicJsonType::difference_type;
68 /// defines a pointer to the type iterated over (value_type)
69 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
70 typename BasicJsonType::const_pointer,
71 typename BasicJsonType::pointer>::type;
72 /// defines a reference to the type iterated over (value_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
83 /*!
84 @brief constructor for a given JSON instance
85 @param[in] object pointer to a JSON object for this iterator
86 @pre object != nullptr
87 @post The iterator is initialized; i.e. `m_object != nullptr`.
88 */
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:
110 case value_t::number_integer:
111 case value_t::number_unsigned:
112 case value_t::number_float:
113 case value_t::binary:
114 case value_t::discarded:
115 default:
116 {
117 m_it.primitive_iterator = primitive_iterator_t();
118 break;
119 }
120 }
121 }
122
123 /*!
124 @note The conventional copy constructor and copy assignment are implicitly
125 defined. Combined with the following converting constructor and
126 assignment, they support: (1) copy from iterator to iterator, (2)
127 copy from const iterator to const iterator, and (3) conversion from
128 iterator to const iterator. However conversion from const iterator
129 to iterator is not defined.
130 */
131
132 /*!
133 @brief const copy constructor
134 @param[in] other const iterator to copy from
135 @note This copy constructor had to be defined explicitly to circumvent a bug
136 occurring on msvc v19.0 compiler (VS 2015) debug build. For more
137 information refer to: https://github.com/nlohmann/json/issues/1608
138 */
139 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
140 : m_object(other.m_object), m_it(other.m_it)
141 {}
142
143 /*!
144 @brief converting assignment
145 @param[in] other const iterator to copy from
146 @return const/non-const iterator
147 @note It is not checked whether @a other is initialized.
148 */
149 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
150 {
151 if (&other != this)
152 {
153 m_object = other.m_object;
154 m_it = other.m_it;
155 }
156 return *this;
157 }
158
159 /*!
160 @brief converting constructor
161 @param[in] other non-const iterator to copy from
162 @note It is not checked whether @a other is initialized.
163 */
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
168 /*!
169 @brief converting assignment
170 @param[in] other non-const iterator to copy from
171 @return const/non-const iterator
172 @note It is not checked whether @a other is initialized.
173 */
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:
182 /*!
183 @brief set the iterator to the first value
184 @pre The iterator is initialized; i.e. `m_object != nullptr`.
185 */
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
207 m_it.primitive_iterator.set_end();
208 break;
209 }
210
211 case value_t::string:
212 case value_t::boolean:
213 case value_t::number_integer:
214 case value_t::number_unsigned:
215 case value_t::number_float:
216 case value_t::binary:
217 case value_t::discarded:
218 default:
219 {
220 m_it.primitive_iterator.set_begin();
221 break;
222 }
223 }
224 }
225
226 /*!
227 @brief set the iterator past the last value
228 @pre The iterator is initialized; i.e. `m_object != nullptr`.
229 */
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:
251 case value_t::number_integer:
252 case value_t::number_unsigned:
253 case value_t::number_float:
254 case value_t::binary:
255 case value_t::discarded:
256 default:
257 {
258 m_it.primitive_iterator.set_end();
259 break;
260 }
261 }
262 }
263
264 public:
265 /*!
266 @brief return a reference to the value pointed to by the iterator
267 @pre The iterator is initialized; i.e. `m_object != nullptr`.
268 */
269 reference operator*() const
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:
292 case value_t::number_integer:
293 case value_t::number_unsigned:
294 case value_t::number_float:
295 case value_t::binary:
296 case value_t::discarded:
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
309 /*!
310 @brief dereference the iterator
311 @pre The iterator is initialized; i.e. `m_object != nullptr`.
312 */
313 pointer operator->() const
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:
334 case value_t::number_integer:
335 case value_t::number_unsigned:
336 case value_t::number_float:
337 case value_t::binary:
338 case value_t::discarded:
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
351 /*!
352 @brief post-increment (it++)
353 @pre The iterator is initialized; i.e. `m_object != nullptr`.
354 */
355 iter_impl const operator++(int) // NOLINT(readability-const-return-type)
356 {
357 auto result = *this;
358 ++(*this);
359 return result;
360 }
361
362 /*!
363 @brief pre-increment (++it)
364 @pre The iterator is initialized; i.e. `m_object != nullptr`.
365 */
366 iter_impl& operator++()
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:
387 case value_t::number_integer:
388 case value_t::number_unsigned:
389 case value_t::number_float:
390 case value_t::binary:
391 case value_t::discarded:
392 default:
393 {
394 ++m_it.primitive_iterator;
395 break;
396 }
397 }
398
399 return *this;
400 }
401
402 /*!
403 @brief post-decrement (it--)
404 @pre The iterator is initialized; i.e. `m_object != nullptr`.
405 */
406 iter_impl const operator--(int) // NOLINT(readability-const-return-type)
407 {
408 auto result = *this;
409 --(*this);
410 return result;
411 }
412
413 /*!
414 @brief pre-decrement (--it)
415 @pre The iterator is initialized; i.e. `m_object != nullptr`.
416 */
417 iter_impl& operator--()
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:
438 case value_t::number_integer:
439 case value_t::number_unsigned:
440 case value_t::number_float:
441 case value_t::binary:
442 case value_t::discarded:
443 default:
444 {
445 --m_it.primitive_iterator;
446 break;
447 }
448 }
449
450 return *this;
451 }
452
453 /*!
454 @brief comparison: equal
455 @pre The iterator is initialized; i.e. `m_object != nullptr`.
456 */
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:
479 case value_t::number_integer:
480 case value_t::number_unsigned:
481 case value_t::number_float:
482 case value_t::binary:
483 case value_t::discarded:
484 default:
485 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
486 }
487 }
488
489 /*!
490 @brief comparison: not equal
491 @pre The iterator is initialized; i.e. `m_object != nullptr`.
492 */
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
499 /*!
500 @brief comparison: smaller
501 @pre The iterator is initialized; i.e. `m_object != nullptr`.
502 */
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:
524 case value_t::number_integer:
525 case value_t::number_unsigned:
526 case value_t::number_float:
527 case value_t::binary:
528 case value_t::discarded:
529 default:
530 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
531 }
532 }
533
534 /*!
535 @brief comparison: less than or equal
536 @pre The iterator is initialized; i.e. `m_object != nullptr`.
537 */
538 bool operator<=(const iter_impl& other) const
539 {
540 return !other.operator < (*this);
541 }
542
543 /*!
544 @brief comparison: greater than
545 @pre The iterator is initialized; i.e. `m_object != nullptr`.
546 */
547 bool operator>(const iter_impl& other) const
548 {
549 return !operator<=(other);
550 }
551
552 /*!
553 @brief comparison: greater than or equal
554 @pre The iterator is initialized; i.e. `m_object != nullptr`.
555 */
556 bool operator>=(const iter_impl& other) const
557 {
558 return !operator<(other);
559 }
560
561 /*!
562 @brief add to iterator
563 @pre The iterator is initialized; i.e. `m_object != nullptr`.
564 */
565 iter_impl& operator+=(difference_type i)
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:
583 case value_t::number_integer:
584 case value_t::number_unsigned:
585 case value_t::number_float:
586 case value_t::binary:
587 case value_t::discarded:
588 default:
589 {
590 m_it.primitive_iterator += i;
591 break;
592 }
593 }
594
595 return *this;
596 }
597
598 /*!
599 @brief subtract from iterator
600 @pre The iterator is initialized; i.e. `m_object != nullptr`.
601 */
602 iter_impl& operator-=(difference_type i)
603 {
604 return operator+=(-i);
605 }
606
607 /*!
608 @brief add to iterator
609 @pre The iterator is initialized; i.e. `m_object != nullptr`.
610 */
611 iter_impl operator+(difference_type i) const
612 {
613 auto result = *this;
614 result += i;
615 return result;
616 }
617
618 /*!
619 @brief addition of distance and iterator
620 @pre The iterator is initialized; i.e. `m_object != nullptr`.
621 */
622 friend iter_impl operator+(difference_type i, const iter_impl& it)
623 {
624 auto result = it;
625 result += i;
626 return result;
627 }
628
629 /*!
630 @brief subtract from iterator
631 @pre The iterator is initialized; i.e. `m_object != nullptr`.
632 */
633 iter_impl operator-(difference_type i) const
634 {
635 auto result = *this;
636 result -= i;
637 return result;
638 }
639
640 /*!
641 @brief return difference
642 @pre The iterator is initialized; i.e. `m_object != nullptr`.
643 */
644 difference_type operator-(const iter_impl& other) const
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:
659 case value_t::number_integer:
660 case value_t::number_unsigned:
661 case value_t::number_float:
662 case value_t::binary:
663 case value_t::discarded:
664 default:
665 return m_it.primitive_iterator - other.m_it.primitive_iterator;
666 }
667 }
668
669 /*!
670 @brief access to successor
671 @pre The iterator is initialized; i.e. `m_object != nullptr`.
672 */
673 reference operator[](difference_type n) const
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:
690 case value_t::number_integer:
691 case value_t::number_unsigned:
692 case value_t::number_float:
693 case value_t::binary:
694 case value_t::discarded:
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
707 /*!
708 @brief return the key of an object iterator
709 @pre The iterator is initialized; i.e. `m_object != nullptr`.
710 */
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
723 /*!
724 @brief return the value of an iterator
725 @pre The iterator is initialized; i.e. `m_object != nullptr`.
726 */
727 reference value() const
728 {
729 return operator*();
730 }
731
732 JSON_PRIVATE_UNLESS_TESTED:
733 /// associated JSON instance
734 pointer m_object = nullptr;
735 /// the actual iterator of the associated instance
736 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
737 };
738 } // namespace detail
739 } // namespace nlohmann