Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
StringIterator.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Foundation/Assert.h" //Assert::unreachable
5#include "../Foundation/Span.h"
6#include "../Foundation/StringSpan.h"
7
8namespace SC
9{
12
15
20constexpr bool StringEncodingAreBinaryCompatible(StringEncoding encoding1, StringEncoding encoding2)
21{
22 return (encoding1 == encoding2) or (encoding2 == StringEncoding::Ascii and encoding1 == StringEncoding::Utf8) or
23 (encoding2 == StringEncoding::Utf8 and encoding1 == StringEncoding::Ascii);
24}
25
34template <typename CharIterator>
35struct SC_COMPILER_EXPORT StringIterator
36{
37 static constexpr StringEncoding getEncoding() { return CharIterator::getEncoding(); }
38
39 using CodeUnit = char;
40 using CodePoint = StringCodePoint;
41
43 constexpr void setToStart() { it = start; }
44
46 constexpr void setToEnd() { it = end; }
47
50 [[nodiscard]] constexpr bool isAtEnd() const { return it >= end; }
51
54 [[nodiscard]] constexpr bool isAtStart() const { return it <= start; }
55
59 [[nodiscard]] constexpr bool advanceUntilMatches(CodePoint c);
60
64 [[nodiscard]] bool reverseAdvanceUntilMatches(CodePoint c);
65
70 template <typename OtherIterator>
72 {
73 return advanceBeforeOrAfterFinding<OtherIterator, true>(other);
74 }
75
76 [[nodiscard]] bool advanceAfterFinding(StringIterator other) { return advanceAfterFindingSameIterator(other); }
77
82 template <typename OtherIterator>
84 {
85 return advanceBeforeOrAfterFinding<OtherIterator, false>(other);
86 }
87
88 [[nodiscard]] bool advanceBeforeFinding(StringIterator other) { return advanceBeforeFindingSameIterator(other); }
89
93 [[nodiscard]] bool advanceByLengthOf(StringIterator other) { return advanceOfBytes(other.end - other.it); }
94
99 [[nodiscard]] bool advanceUntilMatchesAny(Span<const CodePoint> items, CodePoint& matched);
100
105 [[nodiscard]] bool reverseAdvanceUntilMatchesAny(Span<const CodePoint> items, CodePoint& matched);
106
111 [[nodiscard]] bool advanceUntilDifferentFrom(CodePoint c, CodePoint* optionalReadChar = nullptr);
112
116 [[nodiscard]] constexpr bool advanceIfMatches(CodePoint c);
117
121 [[nodiscard]] bool advanceBackwardIfMatches(CodePoint c);
122
127
132 [[nodiscard]] bool advanceIfMatchesRange(CodePoint first, CodePoint last);
133
138 [[nodiscard]] bool match(CodePoint c) { return it < end and CharIterator::decode(it, end) == c; }
139
143 [[nodiscard]] constexpr bool advanceRead(CodePoint& c);
144
148 [[nodiscard]] bool read(CodePoint& c);
149
153 [[nodiscard]] bool advanceBackwardRead(CodePoint& c);
154
157 [[nodiscard]] constexpr bool stepForward();
158
161 [[nodiscard]] constexpr bool stepBackward();
162
166 [[nodiscard]] constexpr bool advanceCodePoints(size_t numCodePoints);
167
171 [[nodiscard]] bool reverseAdvanceCodePoints(size_t numCodePoints);
172
176 [[nodiscard]] constexpr bool isFollowedBy(CodePoint c);
177
181 [[nodiscard]] constexpr bool isPrecededBy(CodePoint c);
182
186 [[nodiscard]] constexpr StringIterator sliceFromStartUntil(StringIterator otherPoint) const;
187
191 [[nodiscard]] constexpr ssize_t bytesDistanceFrom(StringIterator other) const;
192
196 [[nodiscard]] bool endsWithAnyOf(Span<const CodePoint> codePoints) const;
197
201 [[nodiscard]] bool startsWithAnyOf(Span<const CodePoint> codePoints) const;
202
206 template <typename IteratorType>
207 [[nodiscard]] bool endsWith(IteratorType other) const;
208
212 template <typename IteratorType>
213 [[nodiscard]] bool startsWith(IteratorType other) const;
214
215 protected:
216 template <typename OtherIterator, bool after>
217 [[nodiscard]] bool advanceBeforeOrAfterFinding(StringIterator<OtherIterator> other);
218 [[nodiscard]] bool advanceAfterFindingSameIterator(StringIterator other);
219 [[nodiscard]] bool advanceBeforeFindingSameIterator(StringIterator other);
220 [[nodiscard]] bool advanceOfBytes(ssize_t bytesLength);
221
222 friend struct StringView;
223 static constexpr const CodeUnit* getNextOf(const CodeUnit* src, const char* end)
224 {
225 return CharIterator::getNextOf(src, end);
226 }
227 static constexpr const CodeUnit* getPreviousOf(const CodeUnit* src, const char* start)
228 {
229 return CharIterator::getPreviousOf(src, start);
230 }
231 constexpr StringIterator(const CodeUnit* it, const CodeUnit* end) : it(it), start(it), end(end) {}
232 const CodeUnit* it;
233 const CodeUnit* start;
234 const CodeUnit* end;
235};
236
238struct SC_COMPILER_EXPORT StringIteratorASCII : public StringIterator<StringIteratorASCII>
239{
240 [[nodiscard]] constexpr bool advanceUntilMatches(CodePoint c);
241
242 private:
243 [[nodiscard]] bool advanceUntilMatchesNonConstexpr(CodePoint c);
244 using StringIterator::StringIterator;
245 constexpr StringIteratorASCII(const CodeUnit* it, const CodeUnit* end) : StringIterator(it, end) {}
247 friend Parent;
248 friend struct StringView;
249
250 [[nodiscard]] static constexpr StringEncoding getEncoding() { return StringEncoding::Ascii; }
251
252 [[nodiscard]] static constexpr const char* getNextOf(const char* src, const char*) { return src + 1; }
253 [[nodiscard]] static constexpr const char* getPreviousOf(const char* src, const char*) { return src - 1; }
254 [[nodiscard]] static constexpr CodePoint decode(const char* src, const char*)
255 {
256 return static_cast<CodePoint>(*src);
257 }
258};
259
261struct SC_COMPILER_EXPORT StringIteratorUTF16 : public StringIterator<StringIteratorUTF16>
262{
263 private:
264 using StringIterator::StringIterator;
265 constexpr StringIteratorUTF16(const CodeUnit* it, const CodeUnit* end) : StringIterator(it, end) {}
267 friend Parent;
268 friend struct StringView;
269
270 [[nodiscard]] static StringEncoding getEncoding() { return StringEncoding::Utf16; }
271
272 [[nodiscard]] static const char* getNextOf(const char* bytes, const char* end);
273 [[nodiscard]] static const char* getPreviousOf(const char* bytes, const char* start);
274
275 [[nodiscard]] static uint32_t decode(const char* bytes, const char* end);
276};
277
279struct SC_COMPILER_EXPORT StringIteratorUTF8 : public StringIterator<StringIteratorUTF8>
280{
281 private:
283 friend Parent;
284 friend struct StringView;
285 using StringIterator::StringIterator;
286 constexpr StringIteratorUTF8(const CodeUnit* it, const CodeUnit* end) : StringIterator(it, end) {}
287
288 [[nodiscard]] static StringEncoding getEncoding() { return StringEncoding::Utf8; }
289
290 [[nodiscard]] static const char* getNextOf(const char* src, const char* end);
291 [[nodiscard]] static const char* getPreviousOf(const char* src, const char* start);
292
293 [[nodiscard]] static uint32_t decode(const char* src, const char* end);
294};
295
298{
299 bool matches[256] = {false};
301 {
302 for (auto c : chars)
303 {
304 matches[static_cast<int>(c)] = true;
305 }
306 }
307};
309
310//-----------------------------------------------------------------------------------------------------------------------
311// Implementations Details
312//-----------------------------------------------------------------------------------------------------------------------
313template <typename CharIterator>
315{
316 while (it < end)
317 {
318 if (CharIterator::decode(it, end) == c)
319 return true;
320 it = getNextOf(it, end);
321 }
322 return false;
323}
324
325template <typename CharIterator>
327{
328 if (it < end and CharIterator::decode(it, end) == c)
329 {
330 it = getNextOf(it, end);
331 return true;
332 }
333 return false;
334}
335
336template <typename CharIterator>
338{
339 if (it < end)
340 {
341 c = CharIterator::decode(it, end);
342 it = getNextOf(it, end);
343 return true;
344 }
345 return false;
346}
347
348template <typename CharIterator>
350{
351 if (it < end)
352 {
353 it = getNextOf(it, end);
354 return true;
355 }
356 return false;
357}
358
359template <typename CharIterator>
361{
362 if (it > start)
363 {
364 it = getPreviousOf(it, start);
365 return true;
366 }
367 return false;
368}
369
370template <typename CharIterator>
371constexpr bool StringIterator<CharIterator>::advanceCodePoints(size_t numCodePoints)
372{
373 while (numCodePoints > 0)
374 {
375 numCodePoints -= 1;
376 if (it >= end)
377 {
378 return false;
379 }
380 it = getNextOf(it, end);
381 }
382 return true;
383}
384
385template <typename CharIterator>
387{
388 return it < end ? CharIterator::decode(getNextOf(it, end), end) == c : false;
389}
390
391template <typename CharIterator>
393{
394 return it > start ? CharIterator::decode(getPreviousOf(it, start), it) == c : false;
395}
396
397template <typename CharIterator>
399 StringIterator otherPoint) const
400{
401 SC_ASSERT_RELEASE(it <= otherPoint.it);
402 return StringIterator(it, otherPoint.it);
403}
404
405template <typename CharIterator>
407{
408 return (it - other.it) * static_cast<ssize_t>(sizeof(CodeUnit));
409}
410
411// StringIteratorASCII
412[[nodiscard]] constexpr bool StringIteratorASCII::advanceUntilMatches(CodePoint c)
413{
414#if defined(__clang__)
415#pragma clang diagnostic push
416#pragma clang diagnostic ignored "-Wunreachable-code"
417#endif
418 return __builtin_is_constant_evaluated() ? StringIterator::advanceUntilMatches(c)
419 : advanceUntilMatchesNonConstexpr(c);
420#if defined(__clang__)
421#pragma clang diagnostic pop
422#endif
423}
424
425} // namespace SC
#define SC_ASSERT_RELEASE(e)
Assert expression e to be true.
Definition Assert.h:42
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:38
signed long ssize_t
Platform independent signed size type.
Definition PrimitiveTypes.h:57
constexpr bool StringEncodingAreBinaryCompatible(StringEncoding encoding1, StringEncoding encoding2)
Checks if two encodings have the same utf unit size.
Definition StringIterator.h:20
uint32_t StringCodePoint
UTF code point (32 bit)
Definition StringIterator.h:14
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
A string iterator for ASCII strings.
Definition StringIterator.h:239
Builds a constexpr bool skip table of 256 entries used in some parsers.
Definition StringIterator.h:298
A string iterator for UTF16 strings.
Definition StringIterator.h:262
A string iterator for UTF8 strings.
Definition StringIterator.h:280
A position inside a fixed range [start, end) of UTF code points.
Definition StringIterator.h:36
constexpr void setToStart()
Rewind current position to start of iterator range.
Definition StringIterator.h:43
constexpr ssize_t bytesDistanceFrom(StringIterator other) const
Get distance in bytes from current position to another StringIterator current position.
Definition StringIterator.h:406
constexpr void setToEnd()
Set current position to end of iterator range.
Definition StringIterator.h:46
bool advanceUntilMatchesAny(Span< const CodePoint > items, CodePoint &matched)
Advances position until any CodePoint in the given Span is found.
bool advanceBackwardIfMatches(CodePoint c)
Move position by one code point towards start if previous code point matches c
constexpr bool advanceIfMatches(CodePoint c)
Advance position only if next code point matches c.
Definition StringIterator.h:326
bool advanceBeforeFinding(StringIterator< OtherIterator > other)
Advances position towards end until a matching range of character equal to other[it,...
Definition StringIterator.h:83
constexpr bool isAtStart() const
Check if current position is at start of iterator range.
Definition StringIterator.h:54
bool reverseAdvanceUntilMatches(CodePoint c)
Moves position towards start until CodePoint c is found or position == end
bool advanceAfterFinding(StringIterator< OtherIterator > other)
Advances position towards end until a matching range of character equal to other[it,...
Definition StringIterator.h:71
bool advanceUntilDifferentFrom(CodePoint c, CodePoint *optionalReadChar=nullptr)
Advances position until a code point different from c is found or end is reached.
bool startsWith(IteratorType other) const
Check if this Iterator at its start matches entirely another Iterator's range.
bool reverseAdvanceCodePoints(size_t numCodePoints)
Move position backwards (towards start) by variable number of code pints.
constexpr bool stepBackward()
Move position to previous code point.
Definition StringIterator.h:360
constexpr bool advanceCodePoints(size_t numCodePoints)
Move position forward (towards end) by variable number of code points.
Definition StringIterator.h:371
bool reverseAdvanceUntilMatchesAny(Span< const CodePoint > items, CodePoint &matched)
Moves position towards start until any CodePoint in the given Span is found.
constexpr bool stepForward()
Move position to next code point.
Definition StringIterator.h:349
bool endsWithAnyOf(Span< const CodePoint > codePoints) const
Check if this Iterator ends with any code point in the given span.
bool advanceIfMatchesAny(Span< const CodePoint > items)
Advance position only if any of the code points in given Span is matched.
constexpr bool isFollowedBy(CodePoint c)
Check if next code point is c
Definition StringIterator.h:386
bool advanceBackwardRead(CodePoint &c)
Move to previous position and read code unit.
bool startsWithAnyOf(Span< const CodePoint > codePoints) const
Check if this Iterator starts with any code point in the given span.
constexpr StringIterator sliceFromStartUntil(StringIterator otherPoint) const
Returns another StringIterator range, starting from start to otherPoint position.
Definition StringIterator.h:398
constexpr bool isPrecededBy(CodePoint c)
Check if previous code point is c
Definition StringIterator.h:392
constexpr bool advanceUntilMatches(CodePoint c)
Advances position towards end until it matches CodePoint c or position == end
Definition StringIterator.h:314
bool read(CodePoint &c)
Read code unit at current position.
constexpr bool advanceRead(CodePoint &c)
Decode code unit at current position and advance.
Definition StringIterator.h:337
bool match(CodePoint c)
Check if code unit at current position matches CodePoint c
Definition StringIterator.h:138
constexpr bool isAtEnd() const
Check if current position is at end of iterator range.
Definition StringIterator.h:50
bool advanceIfMatchesRange(CodePoint first, CodePoint last)
Advance position if any code point in the range [first, last] is matched.
bool endsWith(IteratorType other) const
Check if this Iterator at its end matches entirely another Iterator's range.
bool advanceByLengthOf(StringIterator other)
Advances position by the same number of code points as other.
Definition StringIterator.h:93
Non-owning view over a range of characters with UTF Encoding.
Definition StringView.h:46