retdec
character_iterator.h
Go to the documentation of this file.
1 
7 #ifndef RETDEC_FILEFORMAT_TYPES_STRINGS_CHARACTER_ITERATOR_H
8 #define RETDEC_FILEFORMAT_TYPES_STRINGS_CHARACTER_ITERATOR_H
9 
10 #include <cctype>
11 #include <iterator>
12 
13 namespace retdec {
14 namespace fileformat {
15 
17 {
18  Little,
19  Big
20 };
21 
26 template <typename It, typename = std::enable_if_t<std::is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value>>
28 {
29  private:
30  It itr, first, last;
31  std::size_t charStep;
32 
40  It safeAdvance(std::ptrdiff_t n)
41  {
42  std::ptrdiff_t direction = n < 0 ? -1 : 1;
43  It end = direction == 1 ? last : first;
44  n = std::abs(n);
45 
46  auto orig = itr;
47 
48  // Advance N times
49  for (std::ptrdiff_t advIdx = 0; advIdx < n; ++advIdx)
50  {
51  // Use `charStep` long advance steps
52  for (std::size_t i = 0; i < charStep; ++i, std::advance(itr, direction))
53  {
54  if (itr == end)
55  return orig;
56  }
57  }
58 
59  return orig;
60  }
61 
62  bool pointsToValidCharacter(const It& charByte, const It& paddingFirst, const It& paddingLast) const
63  {
64  bool result = std::isprint(static_cast<unsigned char>(*charByte));
65 
66  for (auto itr = paddingFirst; result && itr != paddingLast; ++itr)
67  result = (*itr == '\0');
68 
69  return result;
70  }
71 
72  public:
76 
78 
84  char operator*() const
85  {
86  return static_cast<char>(*itr);
87  }
88 
95  {
96  safeAdvance(1);
97  return *this;
98  }
99 
106  {
107  auto tmp = *this;
108  safeAdvance(1);
109  return tmp;
110  }
111 
118  {
119  safeAdvance(-1);
120  return *this;
121  }
122 
129  {
130  auto tmp = *this;
131  safeAdvance(-1);
132  return tmp;
133  }
134 
140  CharacterIterator& operator+=(std::ptrdiff_t diff)
141  {
142  safeAdvance(diff);
143  return *this;
144  }
145 
151  CharacterIterator& operator-=(std::ptrdiff_t diff)
152  {
153  safeAdvance(-diff);
154  return *this;
155  }
156 
162  CharacterIterator operator+(std::ptrdiff_t diff) const
163  {
164  auto tmp = *this;
165  tmp.safeAdvance(diff);
166  return tmp;
167  }
168 
174  CharacterIterator operator-(std::ptrdiff_t diff) const
175  {
176  auto tmp = *this;
177  tmp.safeAdvance(-diff);
178  return tmp;
179  }
180 
186  std::ptrdiff_t operator-(const CharacterIterator& rhs) const
187  {
188  // We need to return 0 only if iterators are the same
189  if (itr == rhs.itr)
190  return 0;
191 
192  // If `charStep` is greater than 1 we are in risk that the size of data is not going to be congruent to `charStep`.
193  // If the difference between iterators is going to be 0, it means this happened.
194  // We need to return 1 because it you take `end - itr`, where `itr` is iterator somewhere near the end (with the real distance less than `charStep`),
195  // you still need to be able to do `itr + (end - itr)` and end up with the `end`.
196  // If this return 0, you would end up at `itr`, which is `end - 1`.
197  std::ptrdiff_t diff = (itr - rhs.itr) / charStep;
198  return diff == 0 ? 1 : diff;
199  }
200 
206  bool operator==(const CharacterIterator& rhs) const
207  {
208  return itr == rhs.itr;
209  }
210 
216  bool operator!=(const CharacterIterator& rhs) const
217  {
218  return !(*this == rhs);
219  }
220 
226  bool operator<(const CharacterIterator& rhs) const
227  {
228  return itr < rhs.itr;
229  }
230 
236  const It& getUnderlyingIterator() const
237  {
238  return itr;
239  }
240 
249  {
250  if (itr == last)
251  return false;
252 
253  if (endian == CharacterEndianness::Little)
254  return pointsToValidCharacter(itr, itr + 1, itr + charStep);
255  else if (endian == CharacterEndianness::Big)
256  return pointsToValidCharacter(itr + charStep - 1, itr, itr + charStep - 1);
257  else
258  return false;
259  }
260 };
261 
271 template <typename It>
272 CharacterIterator<It> makeCharacterIterator(It first, It last, std::size_t charStep)
273 {
274  return { first, last, charStep };
275 }
276 
287 template <typename It>
288 CharacterIterator<It> makeCharacterIterator(It itr, It first, It last, std::size_t charStep)
289 {
290  return { itr, first, last, charStep };
291 }
292 
293 } // namespace fileformat
294 } // namespace retdec
295 
296 namespace std {
297 
298 template <typename It>
299 struct iterator_traits<retdec::fileformat::CharacterIterator<It>>
300 {
301  using difference_type = std::ptrdiff_t;
302  using value_type = char;
303  using iterator_category = std::random_access_iterator_tag;
304 };
305 
306 }
307 
308 #endif
Definition: character_iterator.h:28
bool operator<(const CharacterIterator &rhs) const
Definition: character_iterator.h:226
bool pointsToValidCharacter(const It &charByte, const It &paddingFirst, const It &paddingLast) const
Definition: character_iterator.h:62
CharacterIterator(const CharacterIterator &)=default
It last
Definition: character_iterator.h:30
CharacterIterator & operator--()
Definition: character_iterator.h:117
std::size_t charStep
Definition: character_iterator.h:31
It itr
Definition: character_iterator.h:30
bool operator==(const CharacterIterator &rhs) const
Definition: character_iterator.h:206
CharacterIterator & operator++()
Definition: character_iterator.h:94
CharacterIterator operator--(int)
Definition: character_iterator.h:128
std::ptrdiff_t operator-(const CharacterIterator &rhs) const
Definition: character_iterator.h:186
char operator*() const
Definition: character_iterator.h:84
CharacterIterator operator++(int)
Definition: character_iterator.h:105
const It & getUnderlyingIterator() const
Definition: character_iterator.h:236
CharacterIterator & operator+=(std::ptrdiff_t diff)
Definition: character_iterator.h:140
CharacterIterator operator+(std::ptrdiff_t diff) const
Definition: character_iterator.h:162
CharacterIterator operator-(std::ptrdiff_t diff) const
Definition: character_iterator.h:174
CharacterIterator & operator-=(std::ptrdiff_t diff)
Definition: character_iterator.h:151
bool operator!=(const CharacterIterator &rhs) const
Definition: character_iterator.h:216
CharacterIterator(It first, It last, std::size_t charStep)
Definition: character_iterator.h:73
CharacterIterator(It itr, It first, It last, std::size_t charStep)
Definition: character_iterator.h:74
It safeAdvance(std::ptrdiff_t n)
Definition: character_iterator.h:40
bool pointsToValidCharacter(CharacterEndianness endian) const
Definition: character_iterator.h:248
CharacterIterator & operator=(const CharacterIterator &)=default
It first
Definition: character_iterator.h:30
CharacterEndianness
Definition: character_iterator.h:17
CharacterIterator< It > makeCharacterIterator(It first, It last, std::size_t charStep)
Definition: character_iterator.h:272
Definition: archive_wrapper.h:19
std::ptrdiff_t difference_type
Definition: character_iterator.h:301
std::random_access_iterator_tag iterator_category
Definition: character_iterator.h:303