qxLib
string_view_iterator.inl
Go to the documentation of this file.
1 /**
2 
3  @file string_view_iterator.inl
4  @author Khrapov
5  @date 24.10.2023
6  @copyright © Nick Khrapov, 2023. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 template<class char_t, bool bForwardIterator>
15  value_type svFull,
16  char_t chDelimiter,
17  flags<delimiter_inclusion_flags> eDelimiterInclusionFlags) noexcept
18  : m_svFull(svFull)
19  , m_nCurrentBegin(bForwardIterator ? 0 : m_svFull.size())
20  , m_nCurrentEnd(m_nCurrentBegin)
21  , m_chDelimiter(chDelimiter)
22  , m_eDelimiterInclusionFlags(eDelimiterInclusionFlags)
23 {
24  next(true);
25 }
26 
27 template<class char_t, bool bForwardIterator>
29 {
30  return m_nCurrentBegin != m_nCurrentEnd;
31 }
32 
33 template<class char_t, bool bForwardIterator>
35  begin(value_type svFull, char_t chDelimiter, flags<delimiter_inclusion_flags> eDelimiterInclusionFlags) noexcept
36 {
37  return base_string_view_iterator(svFull, chDelimiter, eDelimiterInclusionFlags);
38 }
39 
40 template<class char_t, bool bForwardIterator>
42  value_type svFull,
43  char_t chDelimiter,
44  flags<delimiter_inclusion_flags> eDelimiterInclusionFlags) noexcept
45 {
46  size_t nEnd = bForwardIterator ? svFull.size() : 0;
47  return base_string_view_iterator(svFull, nEnd, nEnd, chDelimiter, eDelimiterInclusionFlags);
48 }
49 
50 template<class char_t, bool bForwardIterator>
51 constexpr typename base_string_view_iterator<char_t, bForwardIterator>::value_type base_string_view_iterator<
52  char_t,
53  bForwardIterator>::operator*() const noexcept
54 {
55  auto itBegin = m_svFull.cbegin() + m_nCurrentBegin;
56  if (m_eDelimiterInclusionFlags.contains(delimiter_inclusion_flags::begin))
57  while (itBegin != m_svFull.cbegin() && *(itBegin - 1) == m_chDelimiter)
58  --itBegin;
59 
60  auto itEnd = m_svFull.cbegin() + m_nCurrentEnd;
61  if (m_eDelimiterInclusionFlags.contains(delimiter_inclusion_flags::end))
62  while (itEnd != m_svFull.cend() && *(itEnd) == m_chDelimiter)
63  ++itEnd;
64 
65  return value_type(itBegin, itEnd);
66 }
67 
68 template<class char_t, bool bForwardIterator>
69 constexpr base_string_view_iterator<char_t, bForwardIterator>& base_string_view_iterator<char_t, bForwardIterator>::
70  operator++() noexcept
71 {
72  next(true);
73  return *this;
74 }
75 
76 template<class char_t, bool bForwardIterator>
77 constexpr base_string_view_iterator<char_t, bForwardIterator> base_string_view_iterator<char_t, bForwardIterator>::
78  operator++(int) const noexcept
79 {
80  base_string_view_iterator it(*this);
81  ++it;
82  return it;
83 }
84 
85 template<class char_t, bool bForwardIterator>
86 constexpr base_string_view_iterator<char_t, bForwardIterator>& base_string_view_iterator<char_t, bForwardIterator>::
87  operator--() noexcept
88 {
89  next(false);
90  return *this;
91 }
92 
93 template<class char_t, bool bForwardIterator>
94 constexpr base_string_view_iterator<char_t, bForwardIterator> base_string_view_iterator<char_t, bForwardIterator>::
95  operator--(int) const noexcept
96 {
97  base_string_view_iterator it(*this);
98  --it;
99  return it;
100 }
101 
102 template<class char_t, bool bForwardIterator>
104  value_type svFull,
105  size_t nCurrentBegin,
106  size_t nCurrentEnd,
107  char_t chDelimiter,
108  flags<delimiter_inclusion_flags> eDelimiterInclusionFlags) noexcept
109  : m_svFull(svFull)
110  , m_nCurrentBegin(nCurrentBegin)
111  , m_nCurrentEnd(nCurrentEnd)
112  , m_chDelimiter(chDelimiter)
113  , m_eDelimiterInclusionFlags(eDelimiterInclusionFlags)
114 {
115 }
116 
117 template<class char_t, bool bForwardIterator>
118 constexpr void base_string_view_iterator<char_t, bForwardIterator>::next(bool bForwardDirection) noexcept
119 {
120  const bool bRealDirectionIsForward = bForwardIterator == bForwardDirection;
121  const size_t nForwardEnd = m_svFull.size();
122  constexpr size_t nBackwardEnd = static_cast<size_t>(-1);
123  const size_t nEnd = bRealDirectionIsForward ? nForwardEnd : nBackwardEnd;
124 
125  auto move_next = [bRealDirectionIsForward](size_t nPos) -> size_t
126  {
127  return bRealDirectionIsForward ? nPos + 1 : nPos - 1;
128  };
129 
130  size_t nSearchStart = bRealDirectionIsForward ? m_nCurrentEnd : m_nCurrentBegin - 1;
131 
132  // if *this == end() and we move to begin(), shift from end()
133  if (bRealDirectionIsForward && nSearchStart == nBackwardEnd
134  || !bRealDirectionIsForward && nSearchStart == nForwardEnd)
135  {
136  nSearchStart = move_next(nSearchStart);
137  }
138 
139  // skip all "start" delimiters
140  while (nSearchStart != nEnd && m_svFull[nSearchStart] == m_chDelimiter)
141  {
142  nSearchStart = move_next(nSearchStart);
143  }
144 
145  // find the "end" delimiter if any
146  size_t nSearchPos = nEnd;
147  if (nSearchStart != nEnd)
148  {
149  if (const size_t nDelimiterPos = bRealDirectionIsForward ? m_svFull.find(m_chDelimiter, nSearchStart)
150  : m_svFull.rfind(m_chDelimiter, nSearchStart);
151  nDelimiterPos != value_type::npos)
152  {
153  nSearchPos = nDelimiterPos;
154  }
155  }
156 
157  if (bRealDirectionIsForward)
158  {
159  m_nCurrentBegin = nSearchStart;
160  m_nCurrentEnd = nSearchPos;
161  }
162  else
163  {
164  m_nCurrentBegin = nSearchPos + 1;
165  m_nCurrentEnd = nSearchStart + 1;
166  }
167 }
168 
169 } // namespace qx
Iterator class that allows to iterate over a string view using a delimiter character.
constexpr static base_string_view_iterator end(value_type svFull, char_t chDelimiter, flags< delimiter_inclusion_flags > eDelimiterInclusionFlags=delimiter_inclusion_flags::none) noexcept
Return iterator to end.
constexpr base_string_view_iterator(value_type svFull, char_t chDelimiter, flags< delimiter_inclusion_flags > eDelimiterInclusionFlags=delimiter_inclusion_flags::none) noexcept
base_string_view_iterator object constructor
constexpr static base_string_view_iterator begin(value_type svFull, char_t chDelimiter, flags< delimiter_inclusion_flags > eDelimiterInclusionFlags=delimiter_inclusion_flags::none) noexcept
Return iterator to beginning.