8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
32 template<
typename CharType,
int N>
33 constexpr FAsciiSet(
const CharType(&Chars)[N])
34 : FAsciiSet(StringToBitset(Chars))
38 template<
typename CharType>
41 return !!TestImpl(TChar<CharType>::ToUnsigned(Char));
45 template<
typename CharType>
48 return TestImpl(TChar<CharType>::ToUnsigned(Char));
54 InitData Bitset = { LoMask, HiMask };
55 SetImpl(Bitset, TChar<
char>::ToUnsigned(Char));
56 return FAsciiSet(Bitset);
62 return FAsciiSet(~LoMask, ~HiMask);
68 template<
class CharType>
69 static constexpr const CharType* FindFirstOrEnd(
const CharType* Str, FAsciiSet Set)
71 for (FAsciiSet SetOrNil(Set.LoMask | NilMask, Set.HiMask); !SetOrNil.Test(*Str); ++Str);
77 template<
class CharType>
78 static constexpr const CharType* FindLastOrEnd(
const CharType* Str, FAsciiSet Set)
80 const CharType* Last = FindFirstOrEnd(Str, Set);
82 for (
const CharType* It = Last; *It; It = FindFirstOrEnd(It + 1, Set))
91 template<
typename CharType>
92 static constexpr const CharType* Skip(
const CharType* Str, FAsciiSet Set)
94 while (Set.Contains(*Str))
103 template<
typename CharType>
104 static constexpr bool HasAny(
const CharType* Str, FAsciiSet Set)
106 return *FindFirstOrEnd(Str, Set) !=
'\0';
110 template<
typename CharType>
111 static constexpr bool HasNone(
const CharType* Str, FAsciiSet Set)
113 return *FindFirstOrEnd(Str, Set) ==
'\0';
117 template<
typename CharType>
118 static constexpr bool HasOnly(
const CharType* Str, FAsciiSet Set)
120 return *Skip(Str, Set) ==
'\0';
126 template<
class StringType>
127 static constexpr StringType FindPrefixWith(
const StringType& Str, FAsciiSet Set)
129 return Scan<EDir::Forward, EInclude::Members, EKeep::Head>(Str, Set);
133 template<
class StringType>
134 static constexpr StringType FindPrefixWithout(
const StringType& Str, FAsciiSet Set)
136 return Scan<EDir::Forward, EInclude::NonMembers, EKeep::Head>(Str, Set);
140 template<
class StringType>
141 static constexpr StringType TrimPrefixWith(
const StringType& Str, FAsciiSet Set)
143 return Scan<EDir::Forward, EInclude::Members, EKeep::Tail>(Str, Set);
147 template<
class StringType>
148 static constexpr StringType TrimPrefixWithout(
const StringType& Str, FAsciiSet Set)
150 return Scan<EDir::Forward, EInclude::NonMembers, EKeep::Tail>(Str, Set);
154 template<
class StringType>
155 static constexpr StringType FindSuffixWith(
const StringType& Str, FAsciiSet Set)
157 return Scan<EDir::Reverse, EInclude::Members, EKeep::Tail>(Str, Set);
161 template<
class StringType>
162 static constexpr StringType FindSuffixWithout(
const StringType& Str, FAsciiSet Set)
164 return Scan<EDir::Reverse, EInclude::NonMembers, EKeep::Tail>(Str, Set);
168 template<
class StringType>
169 static constexpr StringType TrimSuffixWith(
const StringType& Str, FAsciiSet Set)
171 return Scan<EDir::Reverse, EInclude::Members, EKeep::Head>(Str, Set);
175 template<
class StringType>
176 static constexpr StringType TrimSuffixWithout(
const StringType& Str, FAsciiSet Set)
178 return Scan<EDir::Reverse, EInclude::NonMembers, EKeep::Head>(Str, Set);
182 template<
class StringType>
183 static constexpr bool HasAny(
const StringType& Str, FAsciiSet Set)
185 return !HasNone(Str, Set);
189 template<
class StringType>
190 static constexpr bool HasNone(
const StringType& Str, FAsciiSet Set)
193 for (
auto Char : Str)
195 Match |= Set.Test(Char);
201 template<
class StringType>
202 static constexpr bool HasOnly(
const StringType& Str, FAsciiSet Set)
204 auto End = GetData(Str) + GetNum(Str);
205 return FindFirst<EInclude::Members>(Set, GetData(Str), End) == End;
209 enum class EDir {Forward, Reverse};
210 enum class EInclude {Members, NonMembers};
211 enum class EKeep {Head, Tail};
213 template<EInclude Include,
typename CharType>
214 static constexpr const CharType* FindFirst(FAsciiSet Set,
const CharType* It,
const CharType* End)
216 for (; It != End && (Include == EInclude::Members) == !!Set.Test(*It); ++It);
220 template<EInclude Include,
typename CharType>
221 static constexpr const CharType* FindLast(FAsciiSet Set,
const CharType* It,
const CharType* End)
223 for (; It != End && (Include == EInclude::Members) == !!Set.Test(*It); --It);
227 template<EDir Dir, EInclude Include, EKeep Keep,
class StringType>
228 static constexpr StringType Scan(
const StringType& Str, FAsciiSet Set)
230 auto Begin = GetData(Str);
231 auto End = Begin + GetNum(Str);
232 auto It = Dir == EDir::Forward ? FindFirst<Include>(Set, Begin, End)
233 : FindLast<Include>(Set, End - 1, Begin - 1) + 1;
235 return Keep == EKeep::Head ? StringType(Begin,
static_cast<int32>(It - Begin))
236 : StringType(It,
static_cast<int32>(End - It));
240 struct InitData { uint64 Lo, Hi; };
241 static constexpr uint64 NilMask = uint64(1) <<
'\0';
243 static constexpr FORCEINLINE void SetImpl(InitData& Bitset, uint32 Char)
245 uint64 IsLo = uint64(0) - (Char >> 6 == 0);
246 uint64 IsHi = uint64(0) - (Char >> 6 == 1);
247 uint64 Bit = uint64(1) << uint8(Char & 0x3f);
249 Bitset.Lo |= Bit & IsLo;
250 Bitset.Hi |= Bit & IsHi;
255 uint64 IsLo = uint64(0) - (Char >> 6 == 0);
256 uint64 IsHi = uint64(0) - (Char >> 6 == 1);
257 uint64 Bit = uint64(1) << (Char & 0x3f);
259 return (Bit & IsLo & LoMask) | (Bit & IsHi & HiMask);
262 template<
typename CharType,
int N>
263 static constexpr InitData StringToBitset(
const CharType(&Chars)[N])
265 InitData Bitset = { 0, 0 };
266 for (
int I = 0; I < N - 1; ++I)
268 SetImpl(Bitset, TChar<CharType>::ToUnsigned(Chars[I]));
274 constexpr FAsciiSet(InitData Bitset)
275 : LoMask(Bitset.Lo), HiMask(Bitset.Hi)
278 constexpr FAsciiSet(uint64 Lo, uint64 Hi)
279 : LoMask(Lo), HiMask(Hi)
282 uint64 LoMask, HiMask;