LIEF: Library to Instrument Executable Formats Version 2.0.0
Loading...
Searching...
No Matches
iterators.hpp
Go to the documentation of this file.
1/* Copyright 2017 - 2026 R. Thomas
2 * Copyright 2017 - 2026 Quarkslab
3 * Copyright 2017 - 2021, NVIDIA CORPORATION. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#ifndef LIEF_ITERATORS_H
18#define LIEF_ITERATORS_H
19#include <type_traits>
20#include <algorithm>
21#include <cassert>
22#include <cstddef>
23#include <functional>
24#include <iterator>
25#include <memory>
26#include <vector>
27
29
30namespace LIEF {
31
32template<class T>
33using decay_t = std::decay_t<T>;
34
35template<class T>
36using add_const_t = std::add_const_t<T>;
37
38template<class T>
39using remove_const_t = std::remove_const_t<T>;
40
41template<class T>
42using add_lvalue_reference_t = std::add_lvalue_reference_t<T>;
43
44namespace details {
51template<class T, bool = std::is_reference_v<T>>
53 public:
54 using container_t = std::remove_reference_t<T>;
55 using arg_t = T;
56
57 container_storage() = default;
58 explicit container_storage(arg_t container) :
59 container_{std::addressof(container)} {}
60
62 container_t* get() const {
63 return container_;
64 }
65
66 private:
67 container_t* container_ = nullptr;
68};
69
70template<class T>
71class container_storage<T, false> {
72 public:
73 using container_t = std::remove_const_t<T>;
75
76 container_storage() = default;
77 explicit container_storage(arg_t container) :
78 container_(std::move(container)) {}
79
80 container_t* get() const {
81 return &container_;
82 }
83
84 private:
85 mutable container_t container_;
86};
87
88template<class T>
90
91template<class Ref, class U, class IT>
92Ref deref(const IT& it) {
93 if constexpr (std::is_pointer_v<U>) {
94 assert(*it && "integrity error: nullptr");
95 return static_cast<Ref>(**it);
96 } else {
97 return const_cast<Ref>(*it);
98 }
99}
100
101template<class T, class U, class Category>
103 std::conditional_t<std::is_reference_v<T> || std::is_pointer_v<U>, Category,
104 std::input_iterator_tag>;
105}
106
119template<class T, typename U = typename decay_t<T>::value_type,
120 class ITERATOR_T = typename decay_t<T>::iterator>
122 template<class, typename, class>
123 friend class ref_iterator;
124
125 public:
126 using iterator_category = std::bidirectional_iterator_tag;
129 using value_type = std::remove_cv_t<std::remove_pointer_t<decay_t<U>>>;
130 using difference_type = ptrdiff_t;
131 using pointer = std::remove_pointer_t<U>*;
132 using reference = std::remove_pointer_t<U>&;
133
134 using container_type = T; // e.g. std::vector<Section*>&
135 using DT_VAL = U; // e.g. Section*
136 using DT = decay_t<T>; // e.g. std::vector<Section>
139
140 ref_iterator() = default;
141
143 container_{other.container_},
144 it_{other.it_},
145 distance_{other.distance_} {
146 rebase();
147 }
148
149 ref_iterator(ref_iterator&& other) noexcept :
150 container_{std::move(other.container_)},
151 it_{other.it_},
152 distance_{other.distance_} {
153 rebase();
154 other.container_ = {};
155 other.it_ = {};
156 other.distance_ = 0;
157 }
158
160 ref_iterator copy{other};
161 swap(copy);
162 return *this;
163 }
164
166 swap(other);
167 return *this;
168 }
169
170 template<class T2, typename U2, class IT2,
171 typename = std::enable_if_t<
172 !std::is_same_v<ref_iterator, ref_iterator<T2, U2, IT2>> &&
173 std::is_same_v<decay_t<T>, decay_t<T2>>
174 >>
176 distance_{other.distance_} {
177 if (auto* container = other.container_.get(); container != nullptr) {
178 if constexpr (std::is_reference_v<T>) {
179 container_ = details::container_storage<T>{const_cast<T>(*container)};
180 } else {
181 container_ = details::container_storage<T>{*container};
182 }
183 it_ = std::next(std::begin(*container_.get()), distance_);
184 }
185 }
186
187 ~ref_iterator() = default;
188
189 // NOLINTNEXTLINE(performance-unnecessary-value-param)
191 container_{std::forward<details::container_arg_t<T>>(container)},
192 it_(std::begin(*container_.get())) {}
193
194 void swap(ref_iterator& other) noexcept {
195 std::swap(container_, other.container_);
196 std::swap(it_, other.it_);
197 std::swap(distance_, other.distance_);
198 rebase();
199 other.rebase();
200 }
201
202
204 it_ = std::next(it_);
205 distance_++;
206 return *this;
207 }
208
210 ref_iterator retval = *this;
211 ++(*this);
212 return retval;
213 }
214
216 if (it_ != std::begin(*container_.get())) {
217 it_ = std::prev(it_);
218 distance_--;
219 }
220 return *this;
221 }
222
224 ref_iterator retval = *this;
225 --(*this);
226 return retval;
227 }
228
229
231 const typename ref_iterator::difference_type& movement
233 std::advance(it_, movement);
234 distance_ += movement;
235 return *this;
236 }
237
238
240 const typename ref_iterator::difference_type& movement
242 return (*this) += -movement;
243 }
244
245
246 std::enable_if_t<!std::is_const_v<ref_t>, remove_const_t<ref_t>>
247 operator[](size_t n) {
248 return const_cast<remove_const_t<ref_t>>(
249 static_cast<const ref_iterator*>(this)->operator[](n)
250 );
251 }
252
253
255 assert(n < size() && "integrity error: out of bound");
256 return details::deref<ref_t, DT_VAL>(std::next(std::begin(*container_.get()),
257 difference_type(n)));
258 }
259
261 ref_iterator tmp = *this;
262 return tmp += n;
263 }
264
265
267 ref_iterator tmp = *this;
268 return tmp -= n;
269 }
270
271
273 return distance_ - rhs.distance_;
274 }
275
276 bool operator<(const ref_iterator& rhs) const {
277 return (rhs - *this) > 0;
278 }
279
280
281 bool operator>(const ref_iterator& rhs) const {
282 return rhs < *this;
283 }
284
285
286 bool operator>=(const ref_iterator& rhs) const {
287 return !(*this < rhs);
288 }
289
290
291 bool operator<=(const ref_iterator& rhs) const {
292 return !(*this > rhs);
293 }
294
296 if (container_.get() == nullptr) {
297 return {};
298 }
299 return ref_iterator{*container_.get()};
300 }
301
303 return begin();
304 }
305
307 ref_iterator it = begin();
308 if (auto* container = it.container_.get(); container != nullptr) {
309 it.it_ = std::end(*container);
310 it.distance_ = difference_type(container->size());
311 }
312 return it;
313 }
314
316 return end();
317 }
318
319 bool is_end() const {
320 return distance_ == difference_type(size());
321 }
322
323 bool operator==(const ref_iterator& other) const {
324 // If the current iterator borrows the container we assert the equality
325 // on the **address** of the container.
326 if constexpr (std::is_reference_v<T>) {
327 return container_.get() == other.container_.get() &&
328 distance_ == other.distance_;
329 } else {
330 return size() == other.size() && distance_ == other.distance_;
331 }
332 }
333
334 bool operator!=(const ref_iterator& other) const {
335 return !(*this == other);
336 }
337
338 size_t size() const {
339 const auto* container = container_.get();
340 return container != nullptr ? container->size() : 0;
341 }
342
343 bool empty() const {
344 const auto* container = container_.get();
345 return container == nullptr || container->empty();
346 }
347
348 std::enable_if_t<!std::is_const_v<ref_t>, remove_const_t<ref_t>> operator*() {
349 return const_cast<remove_const_t<ref_t>>(
350 static_cast<const ref_iterator*>(this)->operator*()
351 );
352 }
353
357
358 std::enable_if_t<!std::is_const_v<pointer_t>, pointer_t> operator->() {
359 return const_cast<remove_const_t<pointer_t>>(
360 static_cast<const ref_iterator*>(this)->operator->()
361 );
362 }
363
365 return const_cast<add_const_t<pointer_t>>(&(operator*()));
366 }
367
368 protected:
369 // If the container is owned by this iterator, make `it_` point in this
370 // container and not in the one it has been copied from
371 void rebase() {
372 if constexpr (!std::is_reference_v<T>) {
373 it_ = std::next(std::begin(*container_.get()), distance_);
374 }
375 }
376
377 details::container_storage<T> container_;
378 ITERATOR_T it_{};
379 typename ref_iterator::difference_type distance_{};
380};
381
382
384template<class T, typename U = typename decay_t<T>::value_type,
385 class CT = std::add_const_t<T>>
388
389
391template<class T, typename U = typename decay_t<T>::value_type,
392 class ITERATOR_T = typename decay_t<T>::iterator>
394
395 public:
396 using iterator_category = std::forward_iterator_tag;
399 using value_type = std::remove_cv_t<std::remove_pointer_t<decay_t<U>>>;
400 using difference_type = ptrdiff_t;
401 using pointer = std::remove_pointer_t<U>*;
402 using reference = std::remove_pointer_t<U>&;
403
404 using container_type = T;
405 using DT_VAL = U;
406 using DT = decay_t<T>;
409 using filter_t = std::function<bool(const typename DT::value_type&)>;
410
413 filter_iterator() = default;
414
416 size_c_{other.size_c_},
417 size_cached_{other.size_cached_},
418 container_{other.container_},
419 it_{other.it_},
420 filters_{other.filters_},
421 distance_{other.distance_} {
422 rebase();
423 }
424
426 size_c_{other.size_c_},
427 size_cached_{other.size_cached_},
428 container_{std::move(other.container_)},
429 it_{other.it_},
430 filters_{std::move(other.filters_)},
431 distance_{other.distance_} {
432 rebase();
433 other.size_c_ = 0;
434 other.size_cached_ = false;
435 other.container_ = {};
436 other.it_ = {};
437 other.distance_ = 0;
438 }
439
441 filter_iterator copy{other};
442 swap(copy);
443 return *this;
444 }
445
447 swap(other);
448 return *this;
449 }
450
451 ~filter_iterator() = default;
452
453 // NOLINTNEXTLINE(performance-unnecessary-value-param)
455 container_{std::forward<details::container_arg_t<T>>(container)},
456 it_(std::begin(*container_.get())),
457 filters_{} {
458 filters_.push_back(std::move(filter));
459
460 if (it_ != std::end(*container_.get()) && !match()) {
461 next();
462 }
463 }
464
465 // NOLINTNEXTLINE(performance-unnecessary-value-param)
467 const std::vector<filter_t>& filters) :
468 container_{std::forward<details::container_arg_t<T>>(container)},
469 it_(std::begin(*container_.get())),
470 filters_{filters} {
471 if (it_ != std::end(*container_.get()) && !match()) {
472 next();
473 }
474 }
475
476 // NOLINTNEXTLINE(performance-unnecessary-value-param)
478 container_{std::forward<details::container_arg_t<T>>(container)},
479 it_(std::begin(*container_.get())),
480 filters_{} {}
481
482 void swap(filter_iterator& other) noexcept {
483 std::swap(container_, other.container_);
484 std::swap(it_, other.it_);
485 std::swap(filters_, other.filters_);
486 std::swap(size_c_, other.size_c_);
487 std::swap(size_cached_, other.size_cached_);
488 std::swap(distance_, other.distance_);
489 rebase();
490 other.rebase();
491 }
492
493
495 filters_.push_back(func);
496 size_c_ = 0;
497 size_cached_ = false;
498 return *this;
499 }
500
502 next();
503 return *this;
504 }
505
507 filter_iterator retval = *this;
508 ++(*this);
509 return retval;
510 }
511
513 if (container_.get() == nullptr) {
514 return {};
515 }
516 return {*container_.get(), filters_};
517 }
518
520 return begin();
521 }
522
524 if (container_.get() == nullptr) {
525 return {};
526 }
527
528 // we don't need filter for the end iterator
529 filter_iterator it_end{*container_.get()};
530
531 it_end.it_ = std::end(*it_end.container_.get());
532 it_end.distance_ = difference_type(it_end.container_size());
533
534 return it_end;
535 }
536
538 return end();
539 }
540
541 bool is_end() const {
542 return distance_ == difference_type(container_size());
543 }
544
545 std::enable_if_t<!std::is_const_v<ref_t>, remove_const_t<ref_t>> operator*() {
546 return const_cast<remove_const_t<ref_t>>(
547 static_cast<const filter_iterator*>(this)->operator*()
548 );
549 }
550
554
555
556 std::enable_if_t<!std::is_const_v<ref_t>, remove_const_t<ref_t>>
557 operator[](size_t n) {
558 return const_cast<remove_const_t<ref_t>>(
559 static_cast<const filter_iterator*>(this)->operator[](n)
560 );
561 }
562
564 assert(n < size() && "integrity error: out of bound");
565
566 auto it = begin();
567 std::advance(it, n);
568
569 return details::deref<ref_t, DT_VAL>(std::next(std::begin(*container_.get()),
570 it.distance_));
571 }
572
573
574 std::enable_if_t<!std::is_const_v<pointer_t>, pointer_t> operator->() {
575 return const_cast<remove_const_t<pointer_t>>(
576 static_cast<const filter_iterator*>(this)->operator->()
577 );
578 }
579
581 return const_cast<add_const_t<pointer_t>>(&(operator*()));
582 }
583
584 size_t size() const {
585 if (filters_.empty()) {
586 return container_size();
587 }
588
589 if (size_cached_) {
590 return size_c_;
591 }
592 filter_iterator it = begin();
593 size_t size = 0;
594
595 auto end_iter = it.end();
596 for (; it != end_iter; ++it) {
597 ++size;
598 }
599 size_c_ = size;
600 size_cached_ = true;
601 return size_c_;
602 }
603
604
605 bool empty() const {
606 if (filters_.empty()) {
607 return container_size() == 0;
608 }
609
610 if (size_cached_) {
611 return size_c_ == 0;
612 }
613
614 return begin() == end();
615 }
616
617
618 bool operator==(const filter_iterator& other) const {
619 if constexpr (std::is_reference_v<T>) {
620 return container_.get() == other.container_.get() &&
621 distance_ == other.distance_;
622 } else {
623 return container_size() == other.container_size() &&
624 distance_ == other.distance_;
625 }
626 }
627
628 bool operator!=(const filter_iterator& other) const {
629 return !(*this == other);
630 }
631
632 protected:
633 size_t container_size() const {
634 const auto* container = container_.get();
635 return container != nullptr ? container->size() : 0;
636 }
637
638 bool match() const {
639 return std::all_of(std::begin(filters_), std::end(filters_),
640 [this](const filter_t& f) { return f(*it_); });
641 }
642
643 void next() {
644 if (it_ == std::end(*container_.get())) {
645 distance_ = difference_type(container_size());
646 return;
647 }
648
649 do {
650 it_ = std::next(it_);
651 distance_++;
652 } while (it_ != std::end(*container_.get()) && !match());
653 }
654
655 void rebase() {
656 if constexpr (!std::is_reference_v<T>) {
657 it_ = std::next(std::begin(*container_.get()), distance_);
658 }
659 }
660
661
662 mutable size_t size_c_ = 0;
663 mutable bool size_cached_ = false;
664 details::container_storage<T> container_;
665 ITERATOR_T it_{};
666 std::vector<filter_t> filters_;
667 typename filter_iterator::difference_type distance_ = 0;
668};
669
671template<class T, typename U = typename decay_t<T>::value_type,
672 class CT = std::add_const_t<T>>
675
676// ----------------------------------------------------------------------------
677// This part is taken from LLVM
678// ----------------------------------------------------------------------------
679
680template<typename IteratorT>
682 public:
683 using IteratorTy = IteratorT;
684 using IteratorDecayTy = std::decay_t<IteratorT>;
685
686 template<class T>
687 iterator_range(T&& it_begin, T&& it_end) :
688 begin_(std::forward<T>(it_begin)),
689 end_(std::forward<T>(it_end)) {}
690
691 IteratorT begin() const {
692 return begin_;
693 }
694 IteratorT end() const {
695 return end_;
696 }
697 bool empty() const {
698 return begin_ == end_;
699 }
700
701 class ReferenceProxy {
703
704 IteratorDecayTy it_;
705
706 explicit ReferenceProxy(IteratorDecayTy it) :
707 it_(std::move(it)) {}
708
709 public:
710 using reference = decltype(*std::declval<const IteratorDecayTy&>());
711
712 operator reference() const {
713 return *it_;
714 }
715
716 template<class It = IteratorDecayTy>
717 auto operator->() const -> decltype(&*std::declval<const It&>()) {
718 return &*it_;
719 }
720 };
721
722 ReferenceProxy at(typename IteratorDecayTy::difference_type pos) const {
723 static_assert(IsRandomAccess, "at() needs random access iterator");
724 auto it = begin_;
725 std::advance(it, pos);
726 return ReferenceProxy(std::move(it));
727 }
728
729 ReferenceProxy operator[](typename IteratorDecayTy::difference_type pos) const {
730 return at(pos);
731 }
732
733 std::ptrdiff_t size() const {
734 return std::distance(begin_, end_);
735 }
736
737 protected:
738 static constexpr bool IsRandomAccess =
739 std::is_base_of_v<std::random_access_iterator_tag,
740 typename IteratorDecayTy::iterator_category>;
741 static constexpr bool IsBidirectional =
742 std::is_base_of_v<std::bidirectional_iterator_tag,
743 typename IteratorDecayTy::iterator_category>;
744
745 private:
746 IteratorT begin_;
747 IteratorT end_;
748};
749
750template<class T>
752 return iterator_range<T>(std::forward<T>(x), std::forward<T>(y));
753}
754
755}
756
757#if LIEF_HAS_STD_RANGES
758template<typename IteratorT>
759inline constexpr bool
760 std::ranges::enable_borrowed_range<LIEF::iterator_range<IteratorT>> = true;
761
762// A {ref,filter}_iterator that borrows its container is cheap to
763// copy and can be used as a view.
764
765template<class T, typename U, class IT>
766inline constexpr bool std::ranges::enable_view<LIEF::ref_iterator<T, U, IT>> =
767 std::is_reference_v<T>;
768
769template<class T, typename U, class IT>
770inline constexpr bool std::ranges::enable_view<LIEF::filter_iterator<T, U, IT>> =
771 std::is_reference_v<T>;
772
773// The references returned by the iterators of a borrowed range must outlive
774// the range.
775
776template<class T, typename U, class IT>
777inline constexpr bool
778 std::ranges::enable_borrowed_range<LIEF::ref_iterator<T, U, IT>> =
779 std::is_reference_v<T> || std::is_pointer_v<U>;
780
781template<class T, typename U, class IT>
782inline constexpr bool
783 std::ranges::enable_borrowed_range<LIEF::filter_iterator<T, U, IT>> =
784 std::is_reference_v<T> || std::is_pointer_v<U>;
785#endif
786
787namespace LIEF {
788
789
847template<typename DerivedT, typename IteratorCategoryT, typename T,
848 typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T*,
849 typename ReferenceT = T&>
850class iterator_facade_base {
851 friend DerivedT;
852 iterator_facade_base() = default;
853
854 public:
855 using iterator_category = IteratorCategoryT;
856 using value_type = T;
857 using difference_type = DifferenceTypeT;
858 using pointer = PointerT;
859 using reference = ReferenceT;
860
861 protected:
862 static constexpr bool IsRandomAccess =
863 std::is_base_of_v<std::random_access_iterator_tag, IteratorCategoryT>;
864 static constexpr bool IsBidirectional =
865 std::is_base_of_v<std::bidirectional_iterator_tag, IteratorCategoryT>;
866
872 class ReferenceProxy {
873 friend iterator_facade_base;
874
875 DerivedT I;
876
877 ReferenceProxy(DerivedT I) :
878 I(std::move(I)) {}
879
880 public:
881 operator ReferenceT() const {
882 return *I;
883 }
884 };
885
890 class PointerProxy {
892
893 ReferenceT R;
894
895 template<typename RefT>
896 PointerProxy(RefT&& R) : // NOLINT(bugprone-forwarding-reference-overload)
897 R(std::forward<RefT>(R)) {}
898
899 public:
900 PointerT operator->() const {
901 return &R;
902 }
903 };
904
905 public:
906 DerivedT operator+(DifferenceTypeT n) const {
907 static_assert(std::is_base_of_v<iterator_facade_base, DerivedT>,
908 "Must pass the derived type to this template!");
909 static_assert(IsRandomAccess,
910 "The '+' operator is only defined for random access iterators.");
911 DerivedT tmp = *static_cast<const DerivedT*>(this);
912 tmp += n;
913 return tmp;
914 }
915 friend DerivedT operator+(DifferenceTypeT n, const DerivedT& i) {
916 static_assert(IsRandomAccess,
917 "The '+' operator is only defined for random access iterators.");
918 return i + n;
919 }
920 DerivedT operator-(DifferenceTypeT n) const {
921 static_assert(IsRandomAccess,
922 "The '-' operator is only defined for random access iterators.");
923 DerivedT tmp = *static_cast<const DerivedT*>(this);
924 tmp -= n;
925 return tmp;
926 }
927
929 static_assert(std::is_base_of_v<iterator_facade_base, DerivedT>,
930 "Must pass the derived type to this template!");
931 return static_cast<DerivedT*>(this)->operator+=(1);
932 }
934 DerivedT tmp = *static_cast<DerivedT*>(this);
935 ++*static_cast<DerivedT*>(this);
936 return tmp;
937 }
939 static_assert(
940 IsBidirectional,
941 "The decrement operator is only defined for bidirectional iterators."
942 );
943 return static_cast<DerivedT*>(this)->operator-=(1);
944 }
946 static_assert(
947 IsBidirectional,
948 "The decrement operator is only defined for bidirectional iterators."
949 );
950 DerivedT tmp = *static_cast<DerivedT*>(this);
951 --*static_cast<DerivedT*>(this);
952 return tmp;
953 }
954
955#ifndef __cpp_impl_three_way_comparison
956 bool operator!=(const DerivedT& RHS) const {
957 return !(static_cast<const DerivedT&>(*this) == RHS);
958 }
959#endif
960
961 bool operator>(const DerivedT& RHS) const {
962 static_assert(
963 IsRandomAccess,
964 "Relational operators are only defined for random access iterators."
965 );
966 return !(static_cast<const DerivedT&>(*this) < RHS) &&
967 !(static_cast<const DerivedT&>(*this) == RHS);
968 }
969 bool operator<=(const DerivedT& RHS) const {
970 static_assert(
971 IsRandomAccess,
972 "Relational operators are only defined for random access iterators."
973 );
974 return !(static_cast<const DerivedT&>(*this) > RHS);
975 }
976 bool operator>=(const DerivedT& RHS) const {
977 static_assert(
978 IsRandomAccess,
979 "Relational operators are only defined for random access iterators."
980 );
981 return !(static_cast<const DerivedT&>(*this) < RHS);
982 }
983
984 PointerProxy operator->() const {
985 return static_cast<const DerivedT*>(this)->operator*();
986 }
987 ReferenceProxy operator[](DifferenceTypeT n) const {
988 static_assert(IsRandomAccess,
989 "Subscripting is only defined for random access iterators.");
990 return static_cast<const DerivedT*>(this)->operator+(n);
991 }
992};
993
999template<typename DerivedT, typename WrappedIteratorT,
1000 typename IteratorCategoryT =
1001 typename std::iterator_traits<WrappedIteratorT>::iterator_category,
1002 typename T = typename std::iterator_traits<WrappedIteratorT>::value_type,
1003 typename DifferenceTypeT =
1004 typename std::iterator_traits<WrappedIteratorT>::difference_type,
1005 typename PointerT = std::conditional_t<
1006 std::is_same_v<T, typename std::iterator_traits<WrappedIteratorT>::
1007 value_type>,
1008 typename std::iterator_traits<WrappedIteratorT>::pointer, T*
1009 >,
1010 typename ReferenceT = std::conditional_t<
1011 std::is_same_v<T, typename std::iterator_traits<WrappedIteratorT>::
1012 value_type>,
1013 typename std::iterator_traits<WrappedIteratorT>::reference, T&
1014 >>
1015class iterator_adaptor_base
1016 : public iterator_facade_base<DerivedT, IteratorCategoryT, T, DifferenceTypeT,
1017 PointerT, ReferenceT> {
1018 using BaseT = typename iterator_adaptor_base::iterator_facade_base;
1019
1020 protected:
1021 WrappedIteratorT I;
1022
1023 iterator_adaptor_base() = default;
1024
1025 explicit iterator_adaptor_base(WrappedIteratorT u) :
1026 I(std::move(u)) {
1027 static_assert(std::is_base_of_v<iterator_adaptor_base, DerivedT>,
1028 "Must pass the derived type to this template!");
1029 }
1030
1031 const WrappedIteratorT& wrapped() const {
1032 return I;
1033 }
1034
1035 public:
1036 using difference_type = DifferenceTypeT;
1037
1039 static_assert(
1040 BaseT::IsRandomAccess,
1041 "The '+=' operator is only defined for random access iterators."
1042 );
1043 I += n;
1044 return *static_cast<DerivedT*>(this);
1045 }
1047 static_assert(
1048 BaseT::IsRandomAccess,
1049 "The '-=' operator is only defined for random access iterators."
1050 );
1051 I -= n;
1052 return *static_cast<DerivedT*>(this);
1053 }
1054 using BaseT::operator-;
1056 static_assert(BaseT::IsRandomAccess,
1057 "The '-' operator is only defined for random access iterators.");
1058 return I - RHS.I;
1059 }
1060
1061 // We have to explicitly provide ++ and -- rather than letting the facade
1062 // forward to += because WrappedIteratorT might not support +=.
1063 using BaseT::operator++;
1065 ++I;
1066 return *static_cast<DerivedT*>(this);
1067 }
1068 using BaseT::operator--;
1070 static_assert(
1071 BaseT::IsBidirectional,
1072 "The decrement operator is only defined for bidirectional iterators."
1073 );
1074 --I;
1075 return *static_cast<DerivedT*>(this);
1076 }
1077
1078 friend bool operator==(const iterator_adaptor_base& LHS,
1079 const iterator_adaptor_base& RHS) {
1080 return LHS.I == RHS.I;
1081 }
1082 friend bool operator<(const iterator_adaptor_base& LHS,
1083 const iterator_adaptor_base& RHS) {
1084 static_assert(
1085 BaseT::IsRandomAccess,
1086 "Relational operators are only defined for random access iterators."
1087 );
1088 return LHS.I < RHS.I;
1089 }
1090
1091 ReferenceT operator*() const {
1092 return *I;
1093 }
1094};
1095
1105template<typename WrappedIteratorT,
1106 typename T =
1107 std::remove_reference_t<decltype(**std::declval<WrappedIteratorT>())>>
1109 : iterator_adaptor_base<
1110 pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT,
1111 typename std::iterator_traits<WrappedIteratorT>::iterator_category, T
1112 > {
1113 pointee_iterator() = default;
1114 template<typename U>
1115 pointee_iterator(U&& u) : // NOLINT(bugprone-forwarding-reference-overload)
1116 pointee_iterator::iterator_adaptor_base(std::forward<U>(u)) {}
1117
1118 T& operator*() const {
1119 return **this->I;
1120 }
1121};
1122
1123template<typename RangeT,
1124 typename WrappedIteratorT = decltype(std::begin(std::declval<RangeT>()))>
1125iterator_range<pointee_iterator<WrappedIteratorT>>
1126 make_pointee_range(RangeT&& Range) {
1127 using PointeeIteratorT = pointee_iterator<WrappedIteratorT>;
1128 return make_range(PointeeIteratorT(std::begin(std::forward<RangeT>(Range))),
1129 PointeeIteratorT(std::end(std::forward<RangeT>(Range))));
1130}
1131
1132template<typename WrappedIteratorT,
1133 typename T = decltype(&*std::declval<WrappedIteratorT>())>
1135 : public iterator_adaptor_base<
1136 pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT,
1137 typename std::iterator_traits<WrappedIteratorT>::iterator_category, T
1138 > {
1139 mutable T Ptr;
1140
1141 public:
1142 pointer_iterator() = default;
1143
1144 explicit pointer_iterator(WrappedIteratorT u) :
1145 pointer_iterator::iterator_adaptor_base(std::move(u)) {}
1146
1147 T& operator*() const {
1148 return Ptr = &*this->I;
1149 }
1150};
1151
1152template<typename RangeT,
1153 typename WrappedIteratorT = decltype(std::begin(std::declval<RangeT>()))>
1154iterator_range<pointer_iterator<WrappedIteratorT>>
1155 make_pointer_range(RangeT&& Range) {
1156 using PointerIteratorT = pointer_iterator<WrappedIteratorT>;
1157 return make_range(PointerIteratorT(std::begin(std::forward<RangeT>(Range))),
1158 PointerIteratorT(std::end(std::forward<RangeT>(Range))));
1159}
1160
1161template<typename WrappedIteratorT,
1162 typename T1 =
1163 std::remove_reference_t<decltype(**std::declval<WrappedIteratorT>())>,
1164 typename T2 = std::add_pointer_t<T1>>
1167}
1168
1169#endif
container_t arg_t
Definition iterators.hpp:74
container_t * get() const
Definition iterators.hpp:80
std::remove_const_t< T > container_t
Definition iterators.hpp:73
container_storage(arg_t container)
Definition iterators.hpp:77
Storage of the container iterated by a ref_iterator or a filter_iterator.
Definition iterators.hpp:52
container_t * get() const
The container or a nullptr if the storage is default-constructed.
Definition iterators.hpp:62
T arg_t
Definition iterators.hpp:55
container_storage(arg_t container)
Definition iterators.hpp:58
std::remove_reference_t< T > container_t
Definition iterators.hpp:54
Iterator which returns a ref on container's values given predicates.
Definition iterators.hpp:393
std::enable_if_t<!std::is_const_v< pointer_t >, pointer_t > operator->()
Definition iterators.hpp:574
bool operator==(const filter_iterator &other) const
Definition iterators.hpp:618
add_const_t< ref_t > operator[](size_t n) const
Definition iterators.hpp:563
filter_iterator cend() const
Definition iterators.hpp:537
std::forward_iterator_tag iterator_category
Definition iterators.hpp:396
std::enable_if_t<!std::is_const_v< ref_t >, remove_const_t< ref_t > > operator*()
Definition iterators.hpp:545
filter_iterator & operator=(const filter_iterator &other)
Definition iterators.hpp:440
filter_iterator(details::container_arg_t< T > container, filter_t filter)
Definition iterators.hpp:454
add_const_t< ref_t > operator*() const
Definition iterators.hpp:551
void swap(filter_iterator &other) noexcept
Definition iterators.hpp:482
filter_iterator & operator++()
Definition iterators.hpp:501
filter_iterator(details::container_arg_t< T > container, const std::vector< filter_t > &filters)
Definition iterators.hpp:466
filter_iterator end() const
Definition iterators.hpp:523
typename filter_iterator::pointer pointer_t
Definition iterators.hpp:408
std::remove_pointer_t< Symbol * > * pointer
Definition iterators.hpp:401
typename filter_iterator::reference ref_t
Definition iterators.hpp:407
filter_iterator(const filter_iterator &other)
Definition iterators.hpp:415
bool is_end() const
Definition iterators.hpp:541
filter_iterator begin() const
Definition iterators.hpp:512
bool empty() const
Definition iterators.hpp:605
std::enable_if_t<!std::is_const_v< ref_t >, remove_const_t< ref_t > > operator[](size_t n)
Definition iterators.hpp:557
Symbol * DT_VAL
Definition iterators.hpp:405
ptrdiff_t difference_type
Definition iterators.hpp:400
~filter_iterator()=default
add_const_t< pointer_t > operator->() const
Definition iterators.hpp:580
std::remove_cv_t< std::remove_pointer_t< decay_t< Symbol * > > > value_type
Definition iterators.hpp:399
filter_iterator()=default
Create an iterator that is not associated with a container. It behaves as an empty range.
size_t size() const
Definition iterators.hpp:584
bool operator!=(const filter_iterator &other) const
Definition iterators.hpp:628
filter_iterator(details::container_arg_t< T > container)
Definition iterators.hpp:477
std::function< bool(const typename DT::value_type &)> filter_t
Definition iterators.hpp:409
std::remove_pointer_t< Symbol * > & reference
Definition iterators.hpp:402
details::iterator_concept_t< symbols_t &, Symbol *, std::forward_iterator_tag > iterator_concept
Definition iterators.hpp:397
filter_iterator(filter_iterator &&other) noexcept
Definition iterators.hpp:425
symbols_t & container_type
Definition iterators.hpp:404
filter_iterator operator++(int)
Definition iterators.hpp:506
decay_t< symbols_t & > DT
Definition iterators.hpp:406
filter_iterator cbegin() const
Definition iterators.hpp:519
filter_iterator & def(filter_t func)
Definition iterators.hpp:494
filter_iterator & operator=(filter_iterator &&other) noexcept
Definition iterators.hpp:446
DerivedT & operator++()
Definition iterators.hpp:1064
DerivedT & operator--()
Definition iterators.hpp:1069
DerivedT & operator-=(difference_type n)
Definition iterators.hpp:1046
ReferenceT operator*() const
Definition iterators.hpp:1091
friend bool operator<(const iterator_adaptor_base &LHS, const iterator_adaptor_base &RHS)
Definition iterators.hpp:1082
friend bool operator==(const iterator_adaptor_base &LHS, const iterator_adaptor_base &RHS)
Definition iterators.hpp:1078
DifferenceTypeT difference_type
Definition iterators.hpp:1036
DerivedT & operator+=(difference_type n)
Definition iterators.hpp:1038
difference_type operator-(const DerivedT &RHS) const
Definition iterators.hpp:1055
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
Definition iterators.hpp:850
DifferenceTypeT difference_type
Definition iterators.hpp:857
PointerProxy operator->() const
Definition iterators.hpp:984
DerivedT & operator--()
Definition iterators.hpp:938
DerivedT operator++(int)
Definition iterators.hpp:933
T value_type
Definition iterators.hpp:856
friend DerivedT
Definition iterators.hpp:851
friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i)
Definition iterators.hpp:915
bool operator>(const DerivedT &RHS) const
Definition iterators.hpp:961
ReferenceProxy operator[](DifferenceTypeT n) const
Definition iterators.hpp:987
ReferenceT reference
Definition iterators.hpp:859
bool operator>=(const DerivedT &RHS) const
Definition iterators.hpp:976
DerivedT operator-(DifferenceTypeT n) const
Definition iterators.hpp:920
DerivedT & operator++()
Definition iterators.hpp:928
PointerT pointer
Definition iterators.hpp:858
DerivedT operator--(int)
Definition iterators.hpp:945
IteratorCategoryT iterator_category
Definition iterators.hpp:855
DerivedT operator+(DifferenceTypeT n) const
Definition iterators.hpp:906
bool operator!=(const DerivedT &RHS) const
Definition iterators.hpp:956
bool operator<=(const DerivedT &RHS) const
Definition iterators.hpp:969
decltype(*std::declval< const IteratorDecayTy & >()) reference
Definition iterators.hpp:710
auto operator->() const -> decltype(&*std::declval< const It & >())
Definition iterators.hpp:717
friend iterator_range
Definition iterators.hpp:702
Definition iterators.hpp:681
IteratorT begin() const
Definition iterators.hpp:691
ReferenceProxy at(typename IteratorDecayTy::difference_type pos) const
Definition iterators.hpp:722
std::decay_t< assembly::Instruction::Iterator > IteratorDecayTy
Definition iterators.hpp:684
iterator_range(T &&it_begin, T &&it_end)
Definition iterators.hpp:687
IteratorT end() const
Definition iterators.hpp:694
bool empty() const
Definition iterators.hpp:697
ReferenceProxy operator[](typename IteratorDecayTy::difference_type pos) const
Definition iterators.hpp:729
assembly::Instruction::Iterator IteratorTy
Definition iterators.hpp:683
std::ptrdiff_t size() const
Definition iterators.hpp:733
Definition iterators.hpp:1138
T & operator*() const
Definition iterators.hpp:1147
pointer_iterator(WrappedIteratorT u)
Definition iterators.hpp:1144
Iterator which returns reference on container's values.
Definition iterators.hpp:121
bool operator<=(const ref_iterator &rhs) const
Definition iterators.hpp:291
ref_iterator & operator--()
Definition iterators.hpp:215
add_const_t< ref_t > operator*() const
Definition iterators.hpp:354
size_t size() const
Definition iterators.hpp:338
ref_iterator & operator++()
Definition iterators.hpp:203
void swap(ref_iterator &other) noexcept
Definition iterators.hpp:194
bool operator<(const ref_iterator &rhs) const
Definition iterators.hpp:276
ref_iterator operator-(typename ref_iterator::difference_type n) const
Definition iterators.hpp:266
ref_iterator operator++(int)
Definition iterators.hpp:209
ref_iterator begin() const
Definition iterators.hpp:295
sections_t container_type
Definition iterators.hpp:134
typename ref_iterator::reference ref_t
Definition iterators.hpp:137
ref_iterator operator--(int)
Definition iterators.hpp:223
ref_iterator cend() const
Definition iterators.hpp:315
ref_iterator(const ref_iterator &other)
Definition iterators.hpp:142
ref_iterator & operator+=(const typename ref_iterator::difference_type &movement)
Definition iterators.hpp:230
std::enable_if_t<!std::is_const_v< ref_t >, remove_const_t< ref_t > > operator[](size_t n)
Definition iterators.hpp:247
std::remove_pointer_t< typename decay_t< sections_t >::value_type > & reference
Definition iterators.hpp:132
std::bidirectional_iterator_tag iterator_category
Definition iterators.hpp:126
std::enable_if_t<!std::is_const_v< ref_t >, remove_const_t< ref_t > > operator*()
Definition iterators.hpp:348
ref_iterator(ref_iterator &&other) noexcept
Definition iterators.hpp:149
ptrdiff_t difference_type
Definition iterators.hpp:130
ref_iterator(details::container_arg_t< T > container)
Definition iterators.hpp:190
ref_iterator operator+(typename ref_iterator::difference_type n) const
Definition iterators.hpp:260
ref_iterator cbegin() const
Definition iterators.hpp:302
bool empty() const
Definition iterators.hpp:343
std::remove_cv_t< std::remove_pointer_t< decay_t< typename decay_t< sections_t >::value_type > > > value_type
Definition iterators.hpp:129
ref_iterator & operator=(ref_iterator &&other) noexcept
Definition iterators.hpp:165
bool operator!=(const ref_iterator &other) const
Definition iterators.hpp:334
ref_iterator()=default
bool operator>(const ref_iterator &rhs) const
Definition iterators.hpp:281
bool operator>=(const ref_iterator &rhs) const
Definition iterators.hpp:286
ref_iterator end() const
Definition iterators.hpp:306
ref_iterator & operator-=(const typename ref_iterator::difference_type &movement)
Definition iterators.hpp:239
ref_iterator(const ref_iterator< T2, U2, IT2 > &other)
Definition iterators.hpp:175
add_const_t< ref_t > operator[](size_t n) const
Definition iterators.hpp:254
std::remove_pointer_t< typename decay_t< sections_t >::value_type > * pointer
Definition iterators.hpp:131
std::enable_if_t<!std::is_const_v< pointer_t >, pointer_t > operator->()
Definition iterators.hpp:358
ref_iterator::difference_type operator-(const ref_iterator &rhs) const
Definition iterators.hpp:272
typename decay_t< sections_t >::value_type DT_VAL
Definition iterators.hpp:135
typename ref_iterator::pointer pointer_t
Definition iterators.hpp:138
details::iterator_concept_t< sections_t, typename decay_t< sections_t >::value_type, std::bidirectional_iterator_tag > iterator_concept
Definition iterators.hpp:127
friend class ref_iterator
Definition iterators.hpp:123
bool is_end() const
Definition iterators.hpp:319
~ref_iterator()=default
add_const_t< pointer_t > operator->() const
Definition iterators.hpp:364
ref_iterator & operator=(const ref_iterator &other)
Definition iterators.hpp:159
bool operator==(const ref_iterator &other) const
Definition iterators.hpp:323
decay_t< sections_t > DT
Definition iterators.hpp:136
#define LIEF_LIFETIMEBOUND
Definition compiler_attributes.hpp:72
@ T
Definition AcceleratorCodes.hpp:97
Definition Abstract/DebugInfo.hpp:27
Ref deref(const IT &it)
Definition iterators.hpp:92
typename container_storage< T >::arg_t container_arg_t
Definition iterators.hpp:89
std::conditional_t< std::is_reference_v< T >||std::is_pointer_v< U >, Category, std::input_iterator_tag > iterator_concept_t
Definition iterators.hpp:102
LIEF namespace.
Definition Abstract/Binary.hpp:42
filter_iterator< CT, U, typename decay_t< CT >::const_iterator > const_filter_iterator
Iterator which returns a const ref on container's values given predicates.
Definition iterators.hpp:673
iterator_range< pointee_iterator< WrappedIteratorT > > make_pointee_range(RangeT &&Range)
Definition iterators.hpp:1126
iterator_range< T > make_range(T &&x, T &&y)
Definition iterators.hpp:751
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterators.hpp:1155
std::remove_const_t< T > remove_const_t
Definition iterators.hpp:39
ref_iterator< CT, U, typename decay_t< CT >::const_iterator > const_ref_iterator
Iterator which returns a const ref on container's values.
Definition iterators.hpp:386
pointer_iterator< pointee_iterator< WrappedIteratorT, T1 >, T2 > raw_pointer_iterator
Definition iterators.hpp:1165
std::decay_t< T > decay_t
Definition iterators.hpp:33
std::add_const_t< T > add_const_t
Definition iterators.hpp:36
std::add_lvalue_reference_t< T > add_lvalue_reference_t
Definition iterators.hpp:42
An iterator type that allows iterating over the pointees via some other iterator.
Definition iterators.hpp:1112
T & operator*() const
Definition iterators.hpp:1118
pointee_iterator(U &&u)
Definition iterators.hpp:1115