Warning, file /include/nlohmann/detail/iterators/iter_impl.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
0012 #include <type_traits> // conditional, is_const, remove_const
0013
0014 #include <nlohmann/detail/exceptions.hpp>
0015 #include <nlohmann/detail/iterators/internal_iterator.hpp>
0016 #include <nlohmann/detail/iterators/primitive_iterator.hpp>
0017 #include <nlohmann/detail/macro_scope.hpp>
0018 #include <nlohmann/detail/meta/cpp_future.hpp>
0019 #include <nlohmann/detail/meta/type_traits.hpp>
0020 #include <nlohmann/detail/value_t.hpp>
0021
0022 NLOHMANN_JSON_NAMESPACE_BEGIN
0023 namespace detail
0024 {
0025
0026
0027 template<typename IteratorType> class iteration_proxy;
0028 template<typename IteratorType> class iteration_proxy_value;
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 template<typename BasicJsonType>
0047 class iter_impl
0048 {
0049
0050 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
0051
0052 friend other_iter_impl;
0053 friend BasicJsonType;
0054 friend iteration_proxy<iter_impl>;
0055 friend iteration_proxy_value<iter_impl>;
0056
0057 using object_t = typename BasicJsonType::object_t;
0058 using array_t = typename BasicJsonType::array_t;
0059
0060 static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
0061 "iter_impl only accepts (const) basic_json");
0062
0063 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
0064 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
0065 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
0066
0067 public:
0068
0069
0070
0071
0072
0073 using iterator_category = std::bidirectional_iterator_tag;
0074
0075
0076 using value_type = typename BasicJsonType::value_type;
0077
0078 using difference_type = typename BasicJsonType::difference_type;
0079
0080 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
0081 typename BasicJsonType::const_pointer,
0082 typename BasicJsonType::pointer>::type;
0083
0084 using reference =
0085 typename std::conditional<std::is_const<BasicJsonType>::value,
0086 typename BasicJsonType::const_reference,
0087 typename BasicJsonType::reference>::type;
0088
0089 iter_impl() = default;
0090 ~iter_impl() = default;
0091 iter_impl(iter_impl&&) noexcept = default;
0092 iter_impl& operator=(iter_impl&&) noexcept = default;
0093
0094
0095
0096
0097
0098
0099
0100 explicit iter_impl(pointer object) noexcept : m_object(object)
0101 {
0102 JSON_ASSERT(m_object != nullptr);
0103
0104 switch (m_object->m_data.m_type)
0105 {
0106 case value_t::object:
0107 {
0108 m_it.object_iterator = typename object_t::iterator();
0109 break;
0110 }
0111
0112 case value_t::array:
0113 {
0114 m_it.array_iterator = typename array_t::iterator();
0115 break;
0116 }
0117
0118 case value_t::null:
0119 case value_t::string:
0120 case value_t::boolean:
0121 case value_t::number_integer:
0122 case value_t::number_unsigned:
0123 case value_t::number_float:
0124 case value_t::binary:
0125 case value_t::discarded:
0126 default:
0127 {
0128 m_it.primitive_iterator = primitive_iterator_t();
0129 break;
0130 }
0131 }
0132 }
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150 iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
0151 : m_object(other.m_object), m_it(other.m_it)
0152 {}
0153
0154
0155
0156
0157
0158
0159
0160 iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
0161 {
0162 if (&other != this)
0163 {
0164 m_object = other.m_object;
0165 m_it = other.m_it;
0166 }
0167 return *this;
0168 }
0169
0170
0171
0172
0173
0174
0175 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
0176 : m_object(other.m_object), m_it(other.m_it)
0177 {}
0178
0179
0180
0181
0182
0183
0184
0185 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
0186 {
0187 m_object = other.m_object;
0188 m_it = other.m_it;
0189 return *this;
0190 }
0191
0192 JSON_PRIVATE_UNLESS_TESTED:
0193
0194
0195
0196
0197 void set_begin() noexcept
0198 {
0199 JSON_ASSERT(m_object != nullptr);
0200
0201 switch (m_object->m_data.m_type)
0202 {
0203 case value_t::object:
0204 {
0205 m_it.object_iterator = m_object->m_data.m_value.object->begin();
0206 break;
0207 }
0208
0209 case value_t::array:
0210 {
0211 m_it.array_iterator = m_object->m_data.m_value.array->begin();
0212 break;
0213 }
0214
0215 case value_t::null:
0216 {
0217
0218 m_it.primitive_iterator.set_end();
0219 break;
0220 }
0221
0222 case value_t::string:
0223 case value_t::boolean:
0224 case value_t::number_integer:
0225 case value_t::number_unsigned:
0226 case value_t::number_float:
0227 case value_t::binary:
0228 case value_t::discarded:
0229 default:
0230 {
0231 m_it.primitive_iterator.set_begin();
0232 break;
0233 }
0234 }
0235 }
0236
0237
0238
0239
0240
0241 void set_end() noexcept
0242 {
0243 JSON_ASSERT(m_object != nullptr);
0244
0245 switch (m_object->m_data.m_type)
0246 {
0247 case value_t::object:
0248 {
0249 m_it.object_iterator = m_object->m_data.m_value.object->end();
0250 break;
0251 }
0252
0253 case value_t::array:
0254 {
0255 m_it.array_iterator = m_object->m_data.m_value.array->end();
0256 break;
0257 }
0258
0259 case value_t::null:
0260 case value_t::string:
0261 case value_t::boolean:
0262 case value_t::number_integer:
0263 case value_t::number_unsigned:
0264 case value_t::number_float:
0265 case value_t::binary:
0266 case value_t::discarded:
0267 default:
0268 {
0269 m_it.primitive_iterator.set_end();
0270 break;
0271 }
0272 }
0273 }
0274
0275 public:
0276
0277
0278
0279
0280 reference operator*() const
0281 {
0282 JSON_ASSERT(m_object != nullptr);
0283
0284 switch (m_object->m_data.m_type)
0285 {
0286 case value_t::object:
0287 {
0288 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
0289 return m_it.object_iterator->second;
0290 }
0291
0292 case value_t::array:
0293 {
0294 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
0295 return *m_it.array_iterator;
0296 }
0297
0298 case value_t::null:
0299 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0300
0301 case value_t::string:
0302 case value_t::boolean:
0303 case value_t::number_integer:
0304 case value_t::number_unsigned:
0305 case value_t::number_float:
0306 case value_t::binary:
0307 case value_t::discarded:
0308 default:
0309 {
0310 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
0311 {
0312 return *m_object;
0313 }
0314
0315 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0316 }
0317 }
0318 }
0319
0320
0321
0322
0323
0324 pointer operator->() const
0325 {
0326 JSON_ASSERT(m_object != nullptr);
0327
0328 switch (m_object->m_data.m_type)
0329 {
0330 case value_t::object:
0331 {
0332 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
0333 return &(m_it.object_iterator->second);
0334 }
0335
0336 case value_t::array:
0337 {
0338 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
0339 return &*m_it.array_iterator;
0340 }
0341
0342 case value_t::null:
0343 case value_t::string:
0344 case value_t::boolean:
0345 case value_t::number_integer:
0346 case value_t::number_unsigned:
0347 case value_t::number_float:
0348 case value_t::binary:
0349 case value_t::discarded:
0350 default:
0351 {
0352 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
0353 {
0354 return m_object;
0355 }
0356
0357 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0358 }
0359 }
0360 }
0361
0362
0363
0364
0365
0366 iter_impl operator++(int)&
0367 {
0368 auto result = *this;
0369 ++(*this);
0370 return result;
0371 }
0372
0373
0374
0375
0376
0377 iter_impl& operator++()
0378 {
0379 JSON_ASSERT(m_object != nullptr);
0380
0381 switch (m_object->m_data.m_type)
0382 {
0383 case value_t::object:
0384 {
0385 std::advance(m_it.object_iterator, 1);
0386 break;
0387 }
0388
0389 case value_t::array:
0390 {
0391 std::advance(m_it.array_iterator, 1);
0392 break;
0393 }
0394
0395 case value_t::null:
0396 case value_t::string:
0397 case value_t::boolean:
0398 case value_t::number_integer:
0399 case value_t::number_unsigned:
0400 case value_t::number_float:
0401 case value_t::binary:
0402 case value_t::discarded:
0403 default:
0404 {
0405 ++m_it.primitive_iterator;
0406 break;
0407 }
0408 }
0409
0410 return *this;
0411 }
0412
0413
0414
0415
0416
0417 iter_impl operator--(int)&
0418 {
0419 auto result = *this;
0420 --(*this);
0421 return result;
0422 }
0423
0424
0425
0426
0427
0428 iter_impl& operator--()
0429 {
0430 JSON_ASSERT(m_object != nullptr);
0431
0432 switch (m_object->m_data.m_type)
0433 {
0434 case value_t::object:
0435 {
0436 std::advance(m_it.object_iterator, -1);
0437 break;
0438 }
0439
0440 case value_t::array:
0441 {
0442 std::advance(m_it.array_iterator, -1);
0443 break;
0444 }
0445
0446 case value_t::null:
0447 case value_t::string:
0448 case value_t::boolean:
0449 case value_t::number_integer:
0450 case value_t::number_unsigned:
0451 case value_t::number_float:
0452 case value_t::binary:
0453 case value_t::discarded:
0454 default:
0455 {
0456 --m_it.primitive_iterator;
0457 break;
0458 }
0459 }
0460
0461 return *this;
0462 }
0463
0464
0465
0466
0467
0468 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 >
0469 bool operator==(const IterImpl& other) const
0470 {
0471
0472 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
0473 {
0474 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
0475 }
0476
0477 JSON_ASSERT(m_object != nullptr);
0478
0479 switch (m_object->m_data.m_type)
0480 {
0481 case value_t::object:
0482 return (m_it.object_iterator == other.m_it.object_iterator);
0483
0484 case value_t::array:
0485 return (m_it.array_iterator == other.m_it.array_iterator);
0486
0487 case value_t::null:
0488 case value_t::string:
0489 case value_t::boolean:
0490 case value_t::number_integer:
0491 case value_t::number_unsigned:
0492 case value_t::number_float:
0493 case value_t::binary:
0494 case value_t::discarded:
0495 default:
0496 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
0497 }
0498 }
0499
0500
0501
0502
0503
0504 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 >
0505 bool operator!=(const IterImpl& other) const
0506 {
0507 return !operator==(other);
0508 }
0509
0510
0511
0512
0513
0514 bool operator<(const iter_impl& other) const
0515 {
0516
0517 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
0518 {
0519 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
0520 }
0521
0522 JSON_ASSERT(m_object != nullptr);
0523
0524 switch (m_object->m_data.m_type)
0525 {
0526 case value_t::object:
0527 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
0528
0529 case value_t::array:
0530 return (m_it.array_iterator < other.m_it.array_iterator);
0531
0532 case value_t::null:
0533 case value_t::string:
0534 case value_t::boolean:
0535 case value_t::number_integer:
0536 case value_t::number_unsigned:
0537 case value_t::number_float:
0538 case value_t::binary:
0539 case value_t::discarded:
0540 default:
0541 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
0542 }
0543 }
0544
0545
0546
0547
0548
0549 bool operator<=(const iter_impl& other) const
0550 {
0551 return !other.operator < (*this);
0552 }
0553
0554
0555
0556
0557
0558 bool operator>(const iter_impl& other) const
0559 {
0560 return !operator<=(other);
0561 }
0562
0563
0564
0565
0566
0567 bool operator>=(const iter_impl& other) const
0568 {
0569 return !operator<(other);
0570 }
0571
0572
0573
0574
0575
0576 iter_impl& operator+=(difference_type i)
0577 {
0578 JSON_ASSERT(m_object != nullptr);
0579
0580 switch (m_object->m_data.m_type)
0581 {
0582 case value_t::object:
0583 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
0584
0585 case value_t::array:
0586 {
0587 std::advance(m_it.array_iterator, i);
0588 break;
0589 }
0590
0591 case value_t::null:
0592 case value_t::string:
0593 case value_t::boolean:
0594 case value_t::number_integer:
0595 case value_t::number_unsigned:
0596 case value_t::number_float:
0597 case value_t::binary:
0598 case value_t::discarded:
0599 default:
0600 {
0601 m_it.primitive_iterator += i;
0602 break;
0603 }
0604 }
0605
0606 return *this;
0607 }
0608
0609
0610
0611
0612
0613 iter_impl& operator-=(difference_type i)
0614 {
0615 return operator+=(-i);
0616 }
0617
0618
0619
0620
0621
0622 iter_impl operator+(difference_type i) const
0623 {
0624 auto result = *this;
0625 result += i;
0626 return result;
0627 }
0628
0629
0630
0631
0632
0633 friend iter_impl operator+(difference_type i, const iter_impl& it)
0634 {
0635 auto result = it;
0636 result += i;
0637 return result;
0638 }
0639
0640
0641
0642
0643
0644 iter_impl operator-(difference_type i) const
0645 {
0646 auto result = *this;
0647 result -= i;
0648 return result;
0649 }
0650
0651
0652
0653
0654
0655 difference_type operator-(const iter_impl& other) const
0656 {
0657 JSON_ASSERT(m_object != nullptr);
0658
0659 switch (m_object->m_data.m_type)
0660 {
0661 case value_t::object:
0662 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
0663
0664 case value_t::array:
0665 return m_it.array_iterator - other.m_it.array_iterator;
0666
0667 case value_t::null:
0668 case value_t::string:
0669 case value_t::boolean:
0670 case value_t::number_integer:
0671 case value_t::number_unsigned:
0672 case value_t::number_float:
0673 case value_t::binary:
0674 case value_t::discarded:
0675 default:
0676 return m_it.primitive_iterator - other.m_it.primitive_iterator;
0677 }
0678 }
0679
0680
0681
0682
0683
0684 reference operator[](difference_type n) const
0685 {
0686 JSON_ASSERT(m_object != nullptr);
0687
0688 switch (m_object->m_data.m_type)
0689 {
0690 case value_t::object:
0691 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
0692
0693 case value_t::array:
0694 return *std::next(m_it.array_iterator, n);
0695
0696 case value_t::null:
0697 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0698
0699 case value_t::string:
0700 case value_t::boolean:
0701 case value_t::number_integer:
0702 case value_t::number_unsigned:
0703 case value_t::number_float:
0704 case value_t::binary:
0705 case value_t::discarded:
0706 default:
0707 {
0708 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
0709 {
0710 return *m_object;
0711 }
0712
0713 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
0714 }
0715 }
0716 }
0717
0718
0719
0720
0721
0722 const typename object_t::key_type& key() const
0723 {
0724 JSON_ASSERT(m_object != nullptr);
0725
0726 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
0727 {
0728 return m_it.object_iterator->first;
0729 }
0730
0731 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
0732 }
0733
0734
0735
0736
0737
0738 reference value() const
0739 {
0740 return operator*();
0741 }
0742
0743 JSON_PRIVATE_UNLESS_TESTED:
0744
0745 pointer m_object = nullptr;
0746
0747 internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
0748 };
0749
0750 }
0751 NLOHMANN_JSON_NAMESPACE_END