LIEF: Library to Instrument Executable Formats Version 0.15.0
Loading...
Searching...
No Matches
iterators.hpp
1/* Copyright 2017 - 2024 R. Thomas
2 * Copyright 2017 - 2024 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 <ostream>
20#include <cmath>
21#include <cstddef>
22#include <cassert>
23#include <iterator>
24#include <functional>
25#include <algorithm>
26#include <type_traits>
27#include <vector>
28
29
30namespace LIEF {
31
32template<class T>
33using decay_t = typename std::decay<T>::type;
34
35template<class T>
36using add_const_t = typename std::add_const<T>::type;
37
38template<class T>
39using remove_const_t = typename std::remove_const<T>::type;
40
41template< class T >
42using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
43
44
46template<class T, typename U = typename decay_t<T>::value_type,
47 class ITERATOR_T = typename decay_t<T>::iterator>
49 public:
50 using iterator_category = std::bidirectional_iterator_tag;
51 using value_type = decay_t<U>;
52 using difference_type = ptrdiff_t;
53 using pointer = typename std::remove_pointer<U>::type*;
54 using reference = typename std::remove_pointer<U>::type&;
55
56 using container_type = T; // e.g. std::vector<Section*>&
57 using DT_VAL = U; // e.g. Section*
58 using DT = decay_t<T>; // e.g. std::vector<Section>
59 using ref_t = typename ref_iterator::reference;
60 using pointer_t = typename ref_iterator::pointer;
61
62 ref_iterator(T container) :
63 container_{std::forward<T>(container)}
64 {
65 it_ = std::begin(container_);
66 }
67
68 ref_iterator(const ref_iterator& copy) :
69 container_{copy.container_},
70 it_{std::begin(container_)},
71 distance_{copy.distance_}
72 {
73 std::advance(it_, distance_);
74 }
75
76
77 ref_iterator& operator=(ref_iterator other) {
78 swap(other);
79 return *this;
80 }
81
82 void swap(ref_iterator& other) {
83 std::swap(const_cast<add_lvalue_reference_t<remove_const_t<DT>>>(container_),
84 const_cast<add_lvalue_reference_t<remove_const_t<DT>>>(other.container_));
85 std::swap(it_, other.it_);
86 std::swap(distance_, other.distance_);
87 }
88
89
90 ref_iterator& operator++() {
91 it_ = std::next(it_);
92 distance_++;
93 return *this;
94 }
95
96 ref_iterator operator++(int) {
97 ref_iterator retval = *this;
98 ++(*this);
99 return retval;
100 }
101
102 ref_iterator& operator--() {
103 if (it_ != std::begin(container_)) {
104 it_ = std::prev(it_);
105 distance_--;
106 }
107 return *this;
108 }
109
110 ref_iterator operator--(int) {
111 ref_iterator retval = *this;
112 --(*this);
113 return retval;
114 }
115
116
117 ref_iterator& operator+=(const typename ref_iterator::difference_type& movement) {
118 std::advance(it_, movement);
119 distance_ += movement;
120 return *this;
121 }
122
123
124 ref_iterator& operator-=(const typename ref_iterator::difference_type& movement) {
125 return (*this) += -movement;
126 }
127
128
129 typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
130 operator[](size_t n) {
131 return const_cast<remove_const_t<ref_t>>(static_cast<const ref_iterator*>(this)->operator[](n));
132 }
133
134
135 add_const_t<ref_t> operator[](size_t n) const {
136 assert(n < size() && "integrity error: out of bound");
137
138 auto* no_const_this = const_cast<ref_iterator*>(this);
139
140 typename ref_iterator::difference_type saved_dist = std::distance(std::begin(no_const_this->container_), no_const_this->it_);
141 no_const_this->it_ = std::begin(no_const_this->container_);
142 std::advance(no_const_this->it_, n);
143
144 auto&& v = const_cast<add_const_t<ref_t>>(no_const_this->operator*());
145
146 no_const_this->it_ = std::begin(no_const_this->container_);
147 std::advance(no_const_this->it_, saved_dist);
148
149 return v;
150 }
151
152 ref_iterator operator+(typename ref_iterator::difference_type n) const {
153 ref_iterator tmp = *this;
154 return tmp += n;
155 }
156
157
158 ref_iterator operator-(typename ref_iterator::difference_type n) const {
159 ref_iterator tmp = *this;
160 return tmp -= n;
161 }
162
163
164 typename ref_iterator::difference_type operator-(const ref_iterator& rhs) const {
165 return distance_ - rhs.distance_;
166 }
167
168 bool operator<(const ref_iterator& rhs) const {
169 return (rhs - *this) > 0;
170 }
171
172
173 bool operator>(const ref_iterator& rhs) const {
174 return rhs < *this;
175 }
176
177
178 bool operator>=(const ref_iterator& rhs) const {
179 return !(*this < rhs);
180 }
181
182
183 bool operator<=(const ref_iterator& rhs) const {
184 return !(*this > rhs);
185 }
186
187 ref_iterator begin() const {
188 return container_;
189 }
190
191 ref_iterator cbegin() const {
192 return begin();
193 }
194
195 ref_iterator end() const {
196 ref_iterator it = ref_iterator{container_};
197 it.it_ = std::end(it.container_);
198 it.distance_ = it.size();
199 return it;
200 }
201
202 ref_iterator cend() const {
203 return end();
204 }
205
206 bool operator==(const ref_iterator& other) const {
207 return (size() == other.size() && distance_ == other.distance_);
208 }
209
210 bool operator!=(const ref_iterator& other) const {
211 return !(*this == other);
212 }
213
214 size_t size() const {
215 return container_.size();
216 }
217
218 bool empty() const {
219 return container_.empty();
220 }
221
222 typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
223 operator*() {
224 return const_cast<remove_const_t<ref_t>>(static_cast<const ref_iterator*>(this)->operator*());
225 }
226
227 template<typename V = DT_VAL>
228 typename std::enable_if<std::is_pointer<V>::value, add_const_t<ref_t>>::type
229 operator*() const {
230 assert(*it_ && "integrity error: nullptr");
231 return const_cast<add_const_t<ref_t>>(static_cast<ref_t>(**it_));
232 }
233
234 template<typename V = DT_VAL>
235 typename std::enable_if<!std::is_pointer<V>::value, add_const_t<ref_t>>::type
236 operator*() const {
237 return const_cast<add_const_t<ref_t>>(*(it_));
238 }
239
240
241 typename std::enable_if<!std::is_const<pointer_t>::value, pointer_t>::type
242 operator->() {
243 return const_cast<remove_const_t<pointer_t>>(static_cast<const ref_iterator*>(this)->operator->());
244 }
245
246 add_const_t<pointer_t> operator->() const {
247 return const_cast<add_const_t<pointer_t>>(&(operator*()));
248 }
249
250 protected:
251 T container_;
252 ITERATOR_T it_;
253 typename ref_iterator::difference_type distance_{};
254};
255
256
258template<class T, typename U = typename decay_t<T>::value_type, class CT = typename std::add_const<T>::type>
260
261
263template<class T, typename U = typename decay_t<T>::value_type,
264 class ITERATOR_T = typename decay_t<T>::iterator>
266
267 public:
268 using iterator_category = std::forward_iterator_tag;
269 using value_type = decay_t<U>;
270 using difference_type = ptrdiff_t;
271 using pointer = typename std::remove_pointer<U>::type*;
272 using reference = typename std::remove_pointer<U>::type&;
273
274 using container_type = T;
275 using DT_VAL = U;
276 using DT = decay_t<T>;
277 using ref_t = typename filter_iterator::reference;
278 using pointer_t = typename filter_iterator::pointer;
279 using filter_t = std::function<bool (const typename DT::value_type&)>;
280
281 filter_iterator(T container, filter_t filter) :
282 container_{std::forward<T>(container)},
283 filters_{}
284 {
285
286 it_ = std::begin(container_);
287
288 filters_.push_back(filter),
289 it_ = std::begin(container_);
290
291 if (it_ != std::end(container_)) {
292 if (!std::all_of(std::begin(filters_), std::end(filters_), [this] (const filter_t& f) {return f(*it_);})) {
293 next();
294 }
295 }
296 }
297
298 filter_iterator(T container, const std::vector<filter_t>& filters) :
299 container_{std::forward<T>(container)},
300 filters_{filters}
301 {
302
303 it_ = std::begin(container_);
304
305 if (it_ != std::end(container_)) {
306 if (!std::all_of(std::begin(filters_), std::end(filters_), [this] (const filter_t& f) {return f(*it_);})) {
307 next();
308 }
309 }
310 }
311
312 filter_iterator(T container) :
313 container_{std::forward<T>(container)},
314 filters_{}
315 {
316 it_ = std::begin(container_);
317 }
318
319 filter_iterator(const filter_iterator& copy) :
320 container_{copy.container_},
321 it_{std::begin(container_)},
322 filters_{copy.filters_},
323 distance_{copy.distance_}
324 {
325 std::advance(it_, distance_);
326 }
327
328 filter_iterator& operator=(filter_iterator other) {
329 swap(other);
330 return *this;
331 }
332
333 void swap(filter_iterator& other) {
334 std::swap(const_cast<remove_const_t<DT>&>(container_), const_cast<remove_const_t<DT>&>(other.container_));
335 std::swap(it_, other.it_);
336 std::swap(filters_, other.filters_);
337 std::swap(size_c_, other.size_c_);
338 std::swap(distance_, other.distance_);
339 }
340
341
342 filter_iterator& def(filter_t func) {
343 filters_.push_back(func);
344 size_c_ = 0;
345 return *this;
346 }
347
348 filter_iterator& operator++() {
349 next();
350 return *this;
351 }
352
353 filter_iterator operator++(int) {
354 filter_iterator retval = *this;
355 ++(*this);
356 return retval;
357 }
358
359 filter_iterator begin() const {
360 return {container_, filters_};
361 }
362
363 filter_iterator cbegin() const {
364 return begin();
365 }
366
367 filter_iterator end() const {
368 // we don't need filter for the end iterator
369 filter_iterator it_end{container_};
370
371 it_end.it_ = it_end.container_.end();
372 it_end.distance_ = it_end.container_.size();
373
374 return it_end;
375 }
376
377 filter_iterator cend() const {
378 return end();
379 }
380
381 typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
382 operator*() {
383 return const_cast<remove_const_t<ref_t>>(static_cast<const filter_iterator*>(this)->operator*());
384 }
385
386 template<typename V = DT_VAL>
387 typename std::enable_if<std::is_pointer<V>::value, add_const_t<ref_t>>::type
388 operator*() const {
389 assert(*it_ && "integrity error: nullptr");
390 return const_cast<add_const_t<ref_t>>(static_cast<ref_t>(**it_));
391 }
392
393 template<typename V = DT_VAL>
394 typename std::enable_if<!std::is_pointer<V>::value, add_const_t<ref_t>>::type
395 operator*() const {
396 return const_cast<add_const_t<ref_t>>(*(it_));
397 }
398
399
400 typename std::enable_if<!std::is_const<ref_t>::value, remove_const_t<ref_t>>::type
401 operator[](size_t n) {
402 return const_cast<remove_const_t<ref_t>>(static_cast<const filter_iterator*>(this)->operator[](n));
403 }
404
405 add_const_t<ref_t> operator[](size_t n) const {
406 assert(n < size() && "integrity error: out of bound");
407
408 auto it = begin();
409 std::advance(it, n);
410 return const_cast<add_const_t<ref_t>>(*it);
411 }
412
413
414 typename std::enable_if<!std::is_const<pointer_t>::value, pointer_t>::type
415 operator->() {
416 return const_cast<remove_const_t<pointer_t>>(static_cast<const filter_iterator*>(this)->operator->());
417 }
418
419 add_const_t<pointer_t> operator->() const {
420 return const_cast<add_const_t<pointer_t>>(&(operator*()));
421 }
422
423 size_t size() const {
424 if (filters_.empty()) {
425 return container_.size();
426 }
427
428 if (size_c_ > 0) {
429 return size_c_;
430 }
431 filter_iterator it = begin();
432 size_t size = 0;
433
434 auto end_iter = std::end(it);
435 for (; it != end_iter; ++it) ++size;
436 size_c_ = size;
437 return size_c_;
438 }
439
440
441 bool empty() const {
442 return size() == 0;
443 }
444
445
446 bool operator==(const filter_iterator& other) const {
447 return (container_.size() == other.container_.size() && distance_ == other.distance_);
448 }
449
450 bool operator!=(const filter_iterator& other) const {
451 return !(*this == other);
452 }
453
454 protected:
455 void next() {
456 if (it_ == std::end(container_)) {
457 distance_ = container_.size();
458 return;
459 }
460
461 do {
462 it_ = std::next(it_);
463 distance_++;
464 } while(it_ != std::end(container_) &&
465 !std::all_of(std::begin(filters_), std::end(filters_),
466 [this] (const filter_t& f) { return f(*it_); }));
467
468 }
469
470
471 mutable size_t size_c_ = 0;
472 T container_;
473 ITERATOR_T it_;
474 std::vector<filter_t> filters_;
475 typename filter_iterator::difference_type distance_ = 0;
476};
477
479template<class T, typename U = typename decay_t<T>::value_type,
480 class CT = typename std::add_const<T>::type>
482
483}
484
485#endif
Iterator which return a ref on container's values given predicates.
Definition iterators.hpp:265
Iterator which returns reference on container's values.
Definition iterators.hpp:48
LIEF namespace.
Definition Abstract/Binary.hpp:32