CsString  2.0.0
cs_string_iterator.h
1 /***********************************************************************
2 *
3 * Copyright (c) 2017-2025 Barbara Geller
4 * Copyright (c) 2017-2025 Ansel Sermersheim
5 *
6 * This file is part of CsString.
7 *
8 * CsString is free software which is released under the BSD 2-Clause license.
9 * For license details refer to the LICENSE provided with this project.
10 *
11 * CsString is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 *
15 * https://opensource.org/licenses/BSD-2-Clause
16 *
17 ***********************************************************************/
18 
19 #ifndef LIB_CS_STRING_ITERATOR_H
20 #define LIB_CS_STRING_ITERATOR_H
21 
22 #include <cs_char.h>
23 
24 #include <compare>
25 #include <cstddef>
26 #include <vector>
27 
28 namespace CsString {
29 
30 class LIB_CS_STRING_EXPORT CsCharArrow
31 {
32  public:
33  CsCharArrow (CsChar c)
34  : m_data(c)
35  { }
36 
37  const CsChar *operator->() const {
38  return &m_data;
39  }
40 
41  private:
42  CsChar m_data;
43 };
44 
45 template <typename E, typename A>
46 class CsStringIterator
47 {
48  using v_iter = typename std::vector<typename E::storage_unit, A>::const_iterator;
49 
50  public:
51  using difference_type = std::ptrdiff_t;
52  using pointer = CsChar *;
53  using reference = CsChar;
54  using size_type = std::ptrdiff_t;
55  using value_type = CsChar;
56  using iterator_category = std::random_access_iterator_tag;
57 
58  CsStringIterator() = default;
59 
60  CsChar operator*() const;
61  CsCharArrow operator->() const;
62 
63  CsChar operator[](size_type n) const;
64 
65  std::strong_ordering operator<=>(const CsStringIterator &other) const {
66 
67  if (m_iter < other.m_iter) {
68  return std::strong_ordering::less;
69 
70  } else if (m_iter > other.m_iter) {
71  return std::strong_ordering::greater;
72 
73  } else {
74  return std::strong_ordering::equal;
75 
76  }
77  }
78 
79  bool operator==(const CsStringIterator &other) const {
80  return m_iter == other.m_iter;
81  }
82 
83  // math
84  CsStringIterator &operator+=(size_type n);
85  CsStringIterator &operator-=(size_type n);
86 
87  CsStringIterator operator+(size_type n) const;
88  CsStringIterator &operator++();
89  CsStringIterator operator++(int);
90 
91  CsStringIterator operator-(size_type n) const;
92  size_type operator-(CsStringIterator other) const;
93  CsStringIterator &operator--();
94  CsStringIterator operator--(int);
95 
96  typename std::pair<v_iter, v_iter> codePointRange() const;
97 
98  CsStringIterator advance_storage(size_type n) const;
99  v_iter codePointBegin() const;
100  v_iter codePointEnd() const;
101 
102  private:
103  explicit CsStringIterator(v_iter data);
104  v_iter m_iter;
105 
106  friend class CsBasicString<E, A>;
107 };
108 
109 template <typename E, typename A>
110 CsChar CsStringIterator<E,A>::operator*() const
111 {
112  return E::getCodePoint(m_iter);
113 }
114 
115 template <typename E, typename A>
116 CsCharArrow CsStringIterator<E,A>::operator->() const
117 {
118  return E::getCodePoint(m_iter);
119 }
120 
121 template <typename E, typename A>
122 CsChar CsStringIterator<E,A>:: operator[](size_type n) const
123 {
124  // calls operator+()
125  return *(*this + n);
126 }
127 
128 // math
129 template <typename E, typename A>
130 CsStringIterator<E,A> &CsStringIterator<E,A>::operator+=(size_type n)
131 {
132  m_iter += E::walk(n, m_iter);
133  return *this;
134 }
135 
136 template <typename E, typename A>
137 CsStringIterator<E,A> &CsStringIterator<E,A>::operator-=(size_type n)
138 {
139  m_iter += E::walk(-n, m_iter);
140  return *this;
141 }
142 
143 template <typename E, typename A>
144 CsStringIterator<E,A> CsStringIterator<E,A>::operator+(size_type n) const
145 {
146  auto iter = m_iter + E::walk(n, m_iter);
147  return CsStringIterator(iter);
148 }
149 
150 template <typename E, typename A>
151 CsStringIterator<E,A> &CsStringIterator<E,A>::operator++()
152 {
153  m_iter += E::walk(1, m_iter);
154  return *this;
155 }
156 
157 template <typename E, typename A>
158 CsStringIterator<E,A> CsStringIterator<E,A>::operator++(int)
159 {
160  CsStringIterator retval = *this;
161  m_iter += E::walk(1, m_iter);
162 
163  return retval;
164 }
165 
166 template <typename E, typename A>
167 CsStringIterator<E,A> CsStringIterator<E,A>::operator-(size_type n) const
168 {
169  auto iter = m_iter + E::walk(-n, m_iter);
170  return CsStringIterator(iter);
171 }
172 
173 template <typename E, typename A>
174 typename CsStringIterator<E, A>::size_type CsStringIterator <E,A>::operator-(CsStringIterator other) const
175 {
176  CsStringIterator a = *this;
177  CsStringIterator b = other;
178 
179  if (a < b) {
180  return 0 - E::distance(a.m_iter, b.m_iter);
181 
182  } else {
183  return E::distance(b.m_iter, a.m_iter);
184 
185  }
186 }
187 
188 template <typename E, typename A>
189 CsStringIterator<E,A> &CsStringIterator<E,A>::operator--()
190 {
191  m_iter+= E::walk(-1, m_iter);
192  return *this;
193 }
194 
195 template <typename E, typename A>
196 CsStringIterator<E,A> CsStringIterator<E,A>::operator--(int)
197 {
198  CsStringIterator retval = *this;
199  m_iter += E::walk(-1, m_iter);
200 
201  return retval;
202 }
203 
204 // private methods
205 template <typename E, typename A>
206 CsStringIterator<E,A>::CsStringIterator(v_iter data)
207 {
208  m_iter = data;
209 }
210 
211 template <typename E, typename A>
212 auto CsStringIterator<E,A>::codePointRange() const -> typename std::pair<v_iter, v_iter>
213 {
214  return std::make_pair(m_iter, m_iter + E::walk(1, m_iter));
215 }
216 
217 template <typename E, typename A>
218 CsStringIterator<E,A> CsStringIterator<E,A>::advance_storage(size_type n) const
219 {
220  CsStringIterator retval = CsStringIterator(m_iter + n);
221  return retval;
222 }
223 
224 template <typename E, typename A>
225 auto CsStringIterator<E,A>::codePointBegin() const -> v_iter
226 {
227  return m_iter;
228 }
229 
230 template <typename E, typename A>
231 auto CsStringIterator<E,A>::codePointEnd() const -> v_iter
232 {
233  return m_iter + E::walk(1, m_iter);
234 }
235 
236 // reverse iterator dereference needs to return by value
237 template <typename T>
238 class CsStringReverseIterator : public std::reverse_iterator<T>
239 {
240  public:
241  CsStringReverseIterator() = default;
242 
243  CsStringReverseIterator(T iter)
244  : std::reverse_iterator<T>(iter)
245  {
246  }
247 
248  template <typename U>
249  CsStringReverseIterator(CsStringReverseIterator<U> iter)
250  : std::reverse_iterator<T>(iter.base())
251  {
252  }
253 
254  decltype(std::declval<T>().operator*()) operator*() const;
255  decltype(std::declval<T>().operator->()) operator->() const;
256 };
257 
258 template <typename T>
259 decltype(std::declval<T>().operator*()) CsStringReverseIterator<T>::operator*() const
260 {
261  auto tmp = this->base();
262  return (--tmp).operator*();
263 }
264 
265 template <typename T>
266 decltype(std::declval<T>().operator->()) CsStringReverseIterator<T>::operator->() const
267 {
268  auto tmp = this->base();
269  return (--tmp).operator->();
270 }
271 
272 }
273 
274 #endif
#define LIB_CS_STRING_EXPORT
Definition: cs_char.h:35