Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CORE_STRING_SPSTRINGVIEW_H_
25 : #define STAPPLER_CORE_STRING_SPSTRINGVIEW_H_
26 :
27 : #include "SPMemInterface.h"
28 : #include "SPBytesReader.h"
29 : #include "SPUnicode.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler {
32 :
33 : // Fast reader for char string
34 : // Matching function based on templates
35 : //
36 : // Usage:
37 : // using StringView::Chars;
38 : // using StringView::Range;
39 : //
40 : // reader.readUntil<Chars<' ', '\n', '\r', '\t'>>();
41 : // reader.readChars<Chars<'-', '+', '.', 'e'>, Range<'0', '9'>>();
42 : //
43 :
44 : template <typename _CharType>
45 : class StringViewBase : public BytesReader<_CharType> {
46 : public:
47 : using Self = StringViewBase;
48 : using MatchCharType = _CharType;
49 : using CharType = _CharType;
50 : using value_type = _CharType;
51 : using TraitsType = typename std::char_traits<CharType>;
52 :
53 : using PoolString = typename memory::PoolInterface::template BasicStringType<CharType>;
54 : using StdString = typename memory::StandartInterface::template BasicStringType<CharType>;
55 :
56 : template <CharType ... Args>
57 : using MatchChars = chars::Chars<CharType, Args...>;
58 :
59 : template <char First, char Last>
60 : using MatchRange = chars::Range<CharType, First, Last>;
61 :
62 : template <CharGroupId Group>
63 : using MatchCharGroup = chars::CharGroup<CharType, Group>;
64 :
65 : // CharGroup shortcuts
66 : using Numbers = MatchCharGroup<CharGroupId::Numbers>;
67 : using Latin = MatchCharGroup<CharGroupId::Latin>;
68 : using WhiteSpace = MatchCharGroup<CharGroupId::WhiteSpace>;
69 : using LatinLowercase = MatchCharGroup<CharGroupId::LatinLowercase>;
70 : using LatinUppercase = MatchCharGroup<CharGroupId::LatinUppercase>;
71 : using Alphanumeric = MatchCharGroup<CharGroupId::Alphanumeric>;
72 : using Hexadecimial = MatchCharGroup<CharGroupId::Hexadecimial>;
73 : using Base64 = MatchCharGroup<CharGroupId::Base64>;
74 :
75 : template <typename Interface, typename ... Args>
76 : static auto merge(Args && ... args) -> typename Interface::template BasicStringType<CharType>;
77 :
78 : template <typename Interface, _CharType c, typename ... Args>
79 : static auto merge(Args && ... args) -> typename Interface::template BasicStringType<CharType>;
80 :
81 : constexpr StringViewBase();
82 : constexpr StringViewBase(const CharType *ptr, size_t len = maxOf<size_t>());
83 : constexpr StringViewBase(const CharType *ptr, size_t pos, size_t len);
84 : constexpr StringViewBase(const Self &, size_t pos, size_t len);
85 : constexpr StringViewBase(const Self &, size_t len);
86 : StringViewBase(const PoolString &str);
87 : StringViewBase(const StdString &str);
88 :
89 : Self & operator =(const PoolString &str);
90 : Self & operator =(const StdString &str);
91 : Self & operator =(const Self &str);
92 :
93 : Self & set(const PoolString &str);
94 : Self & set(const StdString &str);
95 : Self & set(const Self &str);
96 :
97 : // unsafe set, without length-check
98 : Self & set(const CharType *p, size_t l);
99 :
100 : bool is(const CharType &c) const;
101 : bool is(const CharType *c) const;
102 : bool is(const Self &c) const;
103 :
104 : template <_CharType C> bool is() const;
105 : template <CharGroupId G> bool is() const;
106 : template <typename M> bool is() const;
107 :
108 106971 : Self sub(size_t pos = 0, size_t len = maxOf<size_t>()) const { return StringViewBase(*this, pos, len); }
109 :
110 : Self pdup(memory::pool_t * = nullptr) const;
111 :
112 : Self ptolower_c(memory::pool_t * = nullptr) const;
113 : Self ptoupper_c(memory::pool_t * = nullptr) const;
114 :
115 : template <typename Interface>
116 : auto str() const -> typename Interface::template BasicStringType<CharType>;
117 :
118 : Self & operator ++ ();
119 : Self operator ++ (int);
120 : Self & operator += (size_t l);
121 :
122 : Self begin() const;
123 : Self end() const;
124 :
125 : Self operator - (const Self &) const;
126 : Self& operator -= (const Self &) const;
127 :
128 : uint64_t hash() const {
129 : return hash::hash64((const char *)this->data(), this->size() * sizeof(CharType));
130 : }
131 :
132 : uint32_t hash32() const {
133 : return hash::hash32((const char *)this->data(), uint32_t(this->size() * sizeof(CharType)));
134 : }
135 :
136 : public:
137 : Result<float> readFloat();
138 : Result<double> readDouble();
139 : Result<int64_t> readInteger(int base = 0);
140 :
141 : public:
142 : template<typename ... Args> void skipChars();
143 : template<typename ... Args> void skipUntil();
144 :
145 : template<typename ... Args> void backwardSkipChars();
146 : template<typename ... Args> void backwardSkipUntil();
147 :
148 : bool skipString(const Self &str);
149 : bool skipUntilString(const Self &str, bool stopBeforeString = true);
150 :
151 : template<typename ... Args> Self readChars();
152 : template<typename ... Args> Self readUntil();
153 :
154 : template<typename ... Args> Self backwardReadChars();
155 : template<typename ... Args> Self backwardReadUntil();
156 :
157 : Self readUntilString(const Self &str);
158 :
159 : template<typename Separator, typename Callback> void split(const Callback &cb) const;
160 :
161 : template <typename ... Args> void trimChars();
162 : template <typename ... Args> void trimUntil();
163 :
164 : protected:
165 : template <typename T>
166 : static size_t __size(const T &);
167 :
168 : static size_t __size(const CharType *);
169 :
170 : template <typename T, typename ... Args>
171 : static size_t _size(T &&);
172 :
173 : template <typename T, typename ... Args>
174 : static size_t _size(T &&, Args && ... args);
175 :
176 : template <typename Buf, typename T>
177 : static void __merge(Buf &, T &&t);
178 :
179 : template <typename Buf>
180 : static void __merge(Buf &, const CharType *);
181 :
182 : template <typename Buf, typename T, typename ... Args>
183 : static void _merge(Buf &, T &&, Args && ... args);
184 :
185 : template <typename Buf, typename T>
186 : static void _merge(Buf &, T &&);
187 :
188 : template <typename Buf, _CharType C, bool Front, typename T>
189 : static void __mergeWithSep(Buf &, T &&t);
190 :
191 : template <typename Buf, _CharType C, bool Front, typename T, typename ... Args>
192 : static void _mergeWithSep(Buf &, T &&, Args && ... args);
193 :
194 : template <typename Buf, _CharType C, bool Front, typename T>
195 : static void _mergeWithSep(Buf &, T &&);
196 :
197 : template <typename ... Args> bool match (CharType c);
198 : };
199 :
200 : class StringViewUtf8 : public BytesReader<char> {
201 : public:
202 : using Self = StringViewUtf8;
203 : using MatchCharType = char32_t;
204 : using CharType = char;
205 : using value_type = char;
206 : using TraitsType = typename std::char_traits<char>;
207 :
208 : using PoolString = typename memory::PoolInterface::StringType;
209 : using StdString = typename memory::StandartInterface::StringType;
210 :
211 : template <MatchCharType ... Args>
212 : using MatchChars = chars::Chars<MatchCharType, Args...>;
213 :
214 : template <char First, char Last>
215 : using MatchRange = chars::Range<MatchCharType, First, Last>;
216 :
217 : template <CharGroupId Group>
218 : using MatchCharGroup = chars::CharGroup<MatchCharType, Group>;
219 :
220 : template <typename ... Args>
221 : using MatchCompose = chars::Compose<MatchCharType, Args ...>;
222 :
223 : template <MatchCharType ... Args>
224 : using Chars = chars::Chars<MatchCharType, Args...>;
225 :
226 : template <char First, char Last>
227 : using Range = chars::Range<MatchCharType, First, Last>;
228 :
229 : template <CharGroupId Group>
230 : using CharGroup = chars::CharGroup<MatchCharType, Group>;
231 :
232 : template <typename ... Args>
233 : using Compose = chars::Compose<MatchCharType, Args ...>;
234 :
235 : // CharGroup shortcuts
236 : using Numbers = MatchCharGroup<CharGroupId::Numbers>;
237 : using Latin = MatchCharGroup<CharGroupId::Latin>;
238 : using WhiteSpace = MatchCharGroup<CharGroupId::WhiteSpace>;
239 : using LatinLowercase = MatchCharGroup<CharGroupId::LatinLowercase>;
240 : using LatinUppercase = MatchCharGroup<CharGroupId::LatinUppercase>;
241 : using Alphanumeric = MatchCharGroup<CharGroupId::Alphanumeric>;
242 : using Hexadecimial = MatchCharGroup<CharGroupId::Hexadecimial>;
243 : using Base64 = MatchCharGroup<CharGroupId::Base64>;
244 :
245 : StringViewUtf8();
246 : StringViewUtf8(const char *ptr, size_t len = maxOf<size_t>());
247 : StringViewUtf8(const char *ptr, size_t pos, size_t len);
248 : StringViewUtf8(const StringViewUtf8 &, size_t len);
249 : StringViewUtf8(const StringViewUtf8 &, size_t pos, size_t len);
250 : StringViewUtf8(const PoolString &str);
251 : StringViewUtf8(const StdString &str);
252 : StringViewUtf8(const StringViewBase<char> &str);
253 :
254 : Self & operator =(const PoolString &str);
255 : Self & operator =(const StdString &str);
256 : Self & operator =(const Self &str);
257 :
258 : Self & set(const PoolString &str);
259 : Self & set(const StdString &str);
260 : Self & set(const Self &str);
261 : Self & set(const char *p, size_t l);
262 :
263 : bool is(const char &c) const;
264 : bool is(const char16_t &c) const;
265 : bool is(const char32_t &c) const;
266 : bool is(const char *c) const;
267 : bool is(const Self &c) const;
268 :
269 : template <char32_t C> bool is() const;
270 : template <CharGroupId G> bool is() const;
271 : template <typename M> bool is() const;
272 :
273 9950 : Self sub(size_t pos = 0, size_t len = maxOf<size_t>()) const { return StringViewUtf8(*this, pos, len); }
274 :
275 : Self letter() const;
276 :
277 : template <typename Interface>
278 : auto str() const -> typename Interface::StringType;
279 :
280 : void offset(size_t l);
281 : Self & operator ++ ();
282 : Self operator ++ (int);
283 : Self & operator += (size_t l);
284 :
285 : bool isSpace() const;
286 :
287 : Self begin() const;
288 : Self end() const;
289 :
290 : Self operator - (const Self &) const;
291 : Self& operator -= (const Self &);
292 :
293 : MatchCharType operator * () const;
294 :
295 : template <typename Callback>
296 : void foreach(const Callback &cb) const;
297 :
298 : size_t code_size() const;
299 :
300 : operator StringViewBase<char> () const;
301 :
302 : uint64_t hash() const {
303 : return hash::hash64(data(), size() * sizeof(CharType));
304 : }
305 :
306 : uint64_t hash32() const {
307 : return hash::hash32(data(), uint32_t(size() * sizeof(CharType)));
308 : }
309 :
310 : public:
311 : Result<float> readFloat();
312 : Result<double> readDouble();
313 : Result<int64_t> readInteger(int base = 0);
314 :
315 : public:
316 : template<typename ... Args> void skipChars();
317 : template<typename ... Args> void skipUntil();
318 :
319 : template<typename ... Args> void backwardSkipChars();
320 : template<typename ... Args> void backwardSkipUntil();
321 :
322 : bool skipString(const Self &str);
323 : bool skipUntilString(const Self &str, bool stopBeforeString = true);
324 :
325 : template<typename ... Args> Self readChars();
326 : template<typename ... Args> Self readUntil();
327 :
328 : template<typename ... Args> Self backwardReadChars();
329 : template<typename ... Args> Self backwardReadUntil();
330 :
331 : Self readUntilString(const Self &str);
332 : template<typename Separator, typename Callback> void split(const Callback &cb) const;
333 :
334 : template <typename ... Args> void trimChars();
335 : template <typename ... Args> void trimUntil();
336 :
337 : protected: // char-matching inline functions
338 : template <typename ...Args> bool rv_match_utf8 (const CharType *ptr, size_t len, uint8_t &offset);
339 : template <typename ...Args> bool match (MatchCharType c);
340 : };
341 :
342 : using StringView = StringViewBase<char>;
343 : using WideStringView = StringViewBase<char16_t>;
344 :
345 : }
346 :
347 : namespace STAPPLER_VERSIONIZED stappler::platform {
348 :
349 : template <typename Interface>
350 : auto tolower(StringView) -> typename Interface::StringType;
351 :
352 : template <typename Interface>
353 : auto toupper(StringView) -> typename Interface::StringType;
354 :
355 : template <typename Interface>
356 : auto totitle(StringView) -> typename Interface::StringType;
357 :
358 : template <typename Interface>
359 : auto tolower(WideStringView) -> typename Interface::WideStringType;
360 :
361 : template <typename Interface>
362 : auto toupper(WideStringView) -> typename Interface::WideStringType;
363 :
364 : template <typename Interface>
365 : auto totitle(WideStringView) -> typename Interface::WideStringType;
366 :
367 : int compare_u(StringView l, StringView r);
368 : int compare_u(WideStringView l, WideStringView r);
369 :
370 : int caseCompare_u(StringView l, StringView r);
371 : int caseCompare_u(WideStringView l, WideStringView r);
372 :
373 : }
374 :
375 : namespace STAPPLER_VERSIONIZED stappler::string {
376 :
377 : template <typename L, typename R, typename CharType
378 : = typename std::enable_if<
379 : std::is_same< typename L::value_type, typename R::value_type >::value,
380 : typename L::value_type>::type>
381 : inline int compare_c(const L &l, const R &r);
382 :
383 : template <typename L, typename R, typename CharType
384 : = typename std::enable_if<
385 : std::is_same< typename L::value_type, typename R::value_type >::value,
386 : typename L::value_type>::type>
387 : inline int compare_u(const L &l, const R &r);
388 :
389 : template <typename L, typename R, typename CharType
390 : = typename std::enable_if<
391 : std::is_same< typename L::value_type, typename R::value_type >::value,
392 : typename L::value_type>::type>
393 : inline int caseCompare_c(const L &l, const R &r);
394 :
395 : template <typename L, typename R, typename CharType
396 : = typename std::enable_if<
397 : std::is_same< typename L::value_type, typename R::value_type >::value,
398 : typename L::value_type>::type>
399 : inline int caseCompare_u(const L &l, const R &r);
400 :
401 : template<typename _CharT>
402 : constexpr size_t length(const _CharT *__p) {
403 : if (!__p) {
404 : return 0;
405 : }
406 :
407 : return std::char_traits<_CharT>::length(__p);
408 : }
409 :
410 : template<typename _CharT>
411 1064195538 : constexpr size_t length(const _CharT *__p, size_t max) {
412 1064195538 : if (!__p) {
413 188024 : return 0;
414 : }
415 :
416 1064007514 : if (max == maxOf<size_t>()) {
417 27964921 : return std::char_traits<_CharT>::length(__p);
418 : } else {
419 1036042295 : size_t __i = 0;
420 7547030465 : while (__i < max && __p[__i] != _CharT()) {
421 6510988170 : ++__i;
422 : }
423 1036042295 : return __i;
424 : }
425 : }
426 :
427 : }
428 :
429 :
430 : namespace STAPPLER_VERSIONIZED stappler {
431 :
432 : template <typename C> inline std::basic_ostream<C> &
433 24389250 : operator << (std::basic_ostream<C> & os, const StringViewBase<C> & str) {
434 24389250 : return os.write(str.data(), str.size());
435 : }
436 :
437 : inline std::basic_ostream<char> &
438 2150 : operator << (std::basic_ostream<char> & os, const StringViewUtf8 & str) {
439 2150 : return os.write(str.data(), str.size());
440 : }
441 :
442 : #define SP_STRINGVIEW_COMPARE_OP(Type1, Type2) \
443 : template <typename C> inline bool operator == (const Type1 &l, const Type2 &r) { return string::compare_c(l, r) == 0; } \
444 : template <typename C> inline bool operator != (const Type1 &l, const Type2 &r) { return string::compare_c(l, r) != 0; } \
445 : template <typename C> inline bool operator > (const Type1 &l, const Type2 &r) { return string::compare_c(l, r) > 0; } \
446 : template <typename C> inline bool operator >= (const Type1 &l, const Type2 &r) { return string::compare_c(l, r) >= 0; } \
447 : template <typename C> inline bool operator < (const Type1 &l, const Type2 &r) { return string::compare_c(l, r) < 0; } \
448 : template <typename C> inline bool operator <= (const Type1 &l, const Type2 &r) { return string::compare_c(l, r) <= 0; }
449 :
450 : #define SP_STRINGVIEW_COMPARE_OP_UTF8(Type1, Type2) \
451 : inline bool operator == (const Type1 &l, const Type2 &r) { return string::compare_c /* not an error! It's faster */ (l, r) == 0; } \
452 : inline bool operator != (const Type1 &l, const Type2 &r) { return string::compare_c /* not an error! It's faster */ (l, r) != 0; } \
453 : inline bool operator > (const Type1 &l, const Type2 &r) { return string::compare_u(l, r) > 0; } \
454 : inline bool operator >= (const Type1 &l, const Type2 &r) { return string::compare_u(l, r) >= 0; } \
455 : inline bool operator < (const Type1 &l, const Type2 &r) { return string::compare_u(l, r) < 0; } \
456 : inline bool operator <= (const Type1 &l, const Type2 &r) { return string::compare_u(l, r) <= 0; }
457 :
458 11851626 : SP_STRINGVIEW_COMPARE_OP(StringViewBase<C>, StringViewBase<C>)
459 :
460 76729 : SP_STRINGVIEW_COMPARE_OP(memory::StandartInterface::BasicStringType<C>, StringViewBase<C>)
461 290746 : SP_STRINGVIEW_COMPARE_OP(StringViewBase<C>, memory::StandartInterface::BasicStringType<C>)
462 :
463 754000 : SP_STRINGVIEW_COMPARE_OP(memory::PoolInterface::BasicStringType<C>, StringViewBase<C>)
464 688007 : SP_STRINGVIEW_COMPARE_OP(StringViewBase<C>, memory::PoolInterface::BasicStringType<C>)
465 :
466 : SP_STRINGVIEW_COMPARE_OP_UTF8(StringViewUtf8, StringViewUtf8)
467 :
468 50 : SP_STRINGVIEW_COMPARE_OP_UTF8(memory::StandartInterface::BasicStringType<char>, StringViewUtf8)
469 : SP_STRINGVIEW_COMPARE_OP_UTF8(StringViewUtf8, memory::StandartInterface::BasicStringType<char>)
470 :
471 : SP_STRINGVIEW_COMPARE_OP_UTF8(memory::PoolInterface::BasicStringType<char>, StringViewUtf8)
472 : SP_STRINGVIEW_COMPARE_OP_UTF8(StringViewUtf8, memory::PoolInterface::BasicStringType<char>)
473 :
474 2064873 : template <typename C> inline bool operator == (const StringViewBase<C> &l, const C *r) { return string::compare_c(l, StringViewBase<C>(r)) == 0; }
475 6858 : template <typename C> inline bool operator != (const StringViewBase<C> &l, const C *r) { return string::compare_c(l, StringViewBase<C>(r)) != 0; }
476 :
477 : template <typename C> inline bool operator == (const C *l, const StringViewBase<C> &r) { return string::compare_c(StringViewBase<C>(l), r) == 0; }
478 : template <typename C> inline bool operator != (const C *l, const StringViewBase<C> &r) { return string::compare_c(StringViewBase<C>(l), r) != 0; }
479 :
480 150 : inline bool operator == (const StringViewUtf8 &l, const char *r) { return string::compare_c(l, StringViewUtf8(r)) == 0; }
481 : inline bool operator != (const StringViewUtf8 &l, const char *r) { return string::compare_c(l, StringViewUtf8(r)) != 0; }
482 :
483 : inline bool operator == (const char *l, const StringViewUtf8 &r) { return string::compare_c(StringViewUtf8(l), r) == 0; }
484 : inline bool operator != (const char *l, const StringViewUtf8 &r) { return string::compare_c(StringViewUtf8(l), r) != 0; }
485 :
486 : #undef SP_STRINGVIEW_COMPARE_OP
487 : #undef SP_STRINGVIEW_COMPARE_OP_UTF8
488 :
489 : template <typename _CharType>
490 : template <typename Interface, typename ... Args>
491 25 : auto StringViewBase<_CharType>::merge(Args && ... args) -> typename Interface::template BasicStringType<CharType> {
492 : using StringType = typename Interface::template BasicStringType<CharType>;
493 :
494 25 : StringType ret; ret.reserve(_size(forward<Args>(args)...));
495 25 : _merge(ret, forward<Args>(args)...);
496 25 : return ret;
497 0 : }
498 :
499 : template <typename _CharType>
500 : template <typename Interface, _CharType C, typename ... Args>
501 23184 : auto StringViewBase<_CharType>::merge(Args && ... args) -> typename Interface::template BasicStringType<CharType> {
502 : using StringType = typename Interface::template BasicStringType<CharType>;
503 :
504 23184 : StringType ret; ret.reserve(_size(forward<Args>(args)...) + sizeof...(Args));
505 23184 : _mergeWithSep<StringType, C, true>(ret, forward<Args>(args)...);
506 23184 : return ret;
507 0 : }
508 :
509 :
510 : template <typename _CharType>
511 : template <typename T>
512 46368 : inline size_t StringViewBase<_CharType>::__size(const T &t) {
513 46368 : return t.size();
514 : }
515 :
516 : template <typename _CharType>
517 75 : inline size_t StringViewBase<_CharType>::__size(const CharType *c) {
518 75 : return std::char_traits<_CharType>::length(c);
519 : }
520 :
521 : template <typename _CharType>
522 : template <typename T, typename ... Args>
523 23209 : inline size_t StringViewBase<_CharType>::_size(T &&t) {
524 23209 : return __size(t);
525 : }
526 :
527 : template <typename _CharType>
528 : template <typename T, typename ... Args>
529 23234 : inline size_t StringViewBase<_CharType>::_size(T &&t, Args && ... args) {
530 23234 : return __size(t) + _size(forward<Args>(args)...);
531 : }
532 :
533 : template <typename _CharType>
534 : template <typename Buf, typename T>
535 0 : inline void StringViewBase<_CharType>::__merge(Buf &buf, T &&t) {
536 0 : if (!t.empty()) {
537 0 : buf.append(t.data(), t.size());
538 : }
539 0 : }
540 :
541 : template <typename _CharType>
542 : template <typename Buf>
543 75 : inline void StringViewBase<_CharType>::__merge(Buf &buf, const CharType *c) {
544 75 : if (c) {
545 75 : buf.append(c);
546 : }
547 75 : }
548 :
549 : template <typename _CharType>
550 : template <typename Buf, typename T, typename ... Args>
551 50 : inline void StringViewBase<_CharType>::_merge(Buf &buf, T &&t, Args && ... args) {
552 50 : __merge(buf, std::forward<T>(t));
553 50 : _merge(buf, forward<Args>(args)...);
554 50 : }
555 :
556 : template <typename _CharType>
557 : template <typename Buf, typename T>
558 25 : inline void StringViewBase<_CharType>::_merge(Buf &buf, T &&t) {
559 25 : __merge(buf, std::forward<T>(t));
560 25 : }
561 :
562 : template <typename _CharType>
563 : template <typename Buf, _CharType C, bool Front, typename T>
564 46368 : inline void StringViewBase<_CharType>::__mergeWithSep(Buf &buf, T &&t) {
565 46368 : Self tmp(t);
566 46368 : tmp.trimChars<typename Self::template Chars<C>>();
567 46368 : if (!tmp.empty()) {
568 : if constexpr (Front) {
569 23184 : tmp = Self(t);
570 23184 : tmp.backwardSkipChars<typename Self::template Chars<C>>();
571 :
572 23184 : buf.append(tmp.data(), tmp.size());
573 : } else {
574 23159 : tmp = Self(t);
575 23159 : tmp.trimChars<typename Self::template Chars<C>>();
576 :
577 23159 : if (!buf.empty()) {
578 23159 : buf.push_back(C);
579 : }
580 :
581 23159 : buf.append(tmp.data(), tmp.size());
582 : }
583 : }
584 46368 : }
585 :
586 : template <typename _CharType>
587 : template <typename Buf, _CharType C, bool Front, typename T, typename ... Args>
588 23184 : inline void StringViewBase<_CharType>::_mergeWithSep(Buf &buf, T &&t, Args && ... args) {
589 23184 : __mergeWithSep<Buf, C, Front>(buf, std::forward<T>(t));
590 23184 : _mergeWithSep<Buf, C, false>(buf, std::forward<Args>(args)...);
591 23184 : }
592 :
593 : template <typename _CharType>
594 : template <typename Buf, _CharType C, bool Front, typename T>
595 23184 : inline void StringViewBase<_CharType>::_mergeWithSep(Buf &buf, T &&t) {
596 23184 : __mergeWithSep<Buf, C, Front>(buf, std::forward<T>(t));
597 23184 : }
598 :
599 :
600 : template <typename _CharType>
601 6897949 : inline constexpr StringViewBase<_CharType>::StringViewBase() : BytesReader<_CharType>(nullptr, 0) { }
602 :
603 : template <typename _CharType>
604 1064002204 : inline constexpr StringViewBase<_CharType>::StringViewBase(const CharType *ptr, size_t len)
605 1064002204 : : BytesReader<_CharType>(ptr, string::length(ptr, len)) { }
606 :
607 : template <typename _CharType>
608 : inline constexpr StringViewBase<_CharType>::StringViewBase(const CharType *ptr, size_t pos, size_t len)
609 : : BytesReader<_CharType>(ptr + pos, string::length(ptr + pos, len)) { }
610 :
611 : template <typename _CharType>
612 108310 : inline constexpr StringViewBase<_CharType>::StringViewBase(const Self &ptr, size_t pos, size_t len)
613 108310 : : BytesReader<_CharType>(ptr.data() + pos, min(len, ptr.size() - pos)) { }
614 :
615 : template <typename _CharType>
616 106550 : inline constexpr StringViewBase<_CharType>::StringViewBase(const Self &ptr, size_t len)
617 106550 : : BytesReader<_CharType>(ptr.data(), min(len, ptr.size())) { }
618 :
619 : template <typename _CharType>
620 8209348 : StringViewBase<_CharType>::StringViewBase(const PoolString &str)
621 8209348 : : StringViewBase(str.data(), str.size()) { }
622 :
623 : template <typename _CharType>
624 8342448 : StringViewBase<_CharType>::StringViewBase(const StdString &str)
625 8342448 : : StringViewBase(str.data(), str.size()) { }
626 :
627 : template <typename _CharType>
628 561675 : auto StringViewBase<_CharType>::operator =(const PoolString &str) -> Self & {
629 561675 : this->set(str);
630 561675 : return *this;
631 : }
632 :
633 : template <typename _CharType>
634 1114997 : auto StringViewBase<_CharType>::operator =(const StdString &str)-> Self & {
635 1114997 : this->set(str);
636 1114997 : return *this;
637 : }
638 :
639 : template <typename _CharType>
640 7685414 : auto StringViewBase<_CharType>::operator =(const Self &str)-> Self & {
641 7685414 : this->set(str);
642 7685413 : return *this;
643 : }
644 :
645 : template <typename _CharType>
646 561675 : auto StringViewBase<_CharType>::set(const PoolString &str)-> Self & {
647 561675 : this->set(str.data(),str.size());
648 561675 : return *this;
649 : }
650 :
651 : template <typename _CharType>
652 1114997 : auto StringViewBase<_CharType>::set(const StdString &str)-> Self & {
653 1114997 : this->set(str.data(), str.size());
654 1114997 : return *this;
655 : }
656 :
657 : template <typename _CharType>
658 7685417 : auto StringViewBase<_CharType>::set(const Self &str)-> Self & {
659 7685417 : this->set(str.data(), str.size());
660 7685413 : return *this;
661 : }
662 :
663 : template <typename _CharType>
664 9362672 : auto StringViewBase<_CharType>::set(const CharType *p, size_t l)-> Self & {
665 9362672 : this->ptr = p;
666 9362672 : this->len = l;
667 9362672 : return *this;
668 : }
669 :
670 : template <typename _CharType>
671 129960 : auto StringViewBase<_CharType>::pdup(memory::pool_t *p) const -> Self {
672 129960 : if (!p) {
673 3923 : p = memory::pool::acquire();
674 : }
675 129961 : auto buf = (_CharType *)memory::pool::palloc(p, (this->size() + 1) * sizeof(_CharType));
676 129961 : memcpy(buf, this->data(), this->size() * sizeof(_CharType));
677 129961 : buf[this->size()] = 0;
678 129961 : return Self(buf, this->size());
679 : }
680 :
681 : template <typename _CharType>
682 6200 : auto StringViewBase<_CharType>::ptolower_c(memory::pool_t *p) const -> Self {
683 6200 : if (!p) {
684 0 : p = memory::pool::acquire();
685 : }
686 6200 : auto buf = (_CharType *)memory::pool::palloc(p, (this->size() + 1) * sizeof(_CharType));
687 6200 : memcpy(buf, this->data(), this->size() * sizeof(_CharType));
688 6200 : for (size_t i = 0; i < this->size(); ++ i) {
689 0 : buf[i] = std::tolower(buf[i], std::locale());
690 : }
691 6200 : buf[this->size()] = 0;
692 6200 : return Self(buf, this->size());
693 : }
694 :
695 : template <typename _CharType>
696 : auto StringViewBase<_CharType>::ptoupper_c(memory::pool_t *p) const -> Self {
697 : if (!p) {
698 : p = memory::pool::acquire();
699 : }
700 : auto buf = (_CharType *)memory::pool::palloc(p, (this->size() + 1) * sizeof(_CharType));
701 : memcpy(buf, this->data(), this->size() * sizeof(_CharType));
702 : for (size_t i = 0; i < this->size(); ++ i) {
703 : buf[i] = std::toupper(buf[i], std::locale());
704 : }
705 : buf[this->size()] = 0;
706 : return Self(buf, this->size());
707 : }
708 :
709 : template <typename _CharType>
710 : template <typename Interface>
711 7740372 : auto StringViewBase<_CharType>::str() const -> typename Interface::template BasicStringType<CharType> {
712 7740372 : if (this->ptr && this->len > 0) {
713 7616835 : return typename Interface::template BasicStringType<CharType>(this->ptr, this->len);
714 : } else {
715 123537 : return typename Interface::template BasicStringType<CharType>();
716 : }
717 : }
718 :
719 : template <typename _CharType>
720 127274426 : auto StringViewBase<_CharType>::operator ++ () -> Self & {
721 127274426 : if (!this->empty()) {
722 127257351 : this->ptr ++; this->len --;
723 : }
724 127274426 : return *this;
725 : }
726 :
727 : template <typename _CharType>
728 123814575 : auto StringViewBase<_CharType>::operator ++ (int) -> Self {
729 123814575 : auto tmp = *this;
730 123814575 : if (!this->empty()) {
731 123814575 : this->ptr ++; this->len --;
732 : }
733 123814575 : return tmp;
734 : }
735 :
736 : template <typename _CharType>
737 8874370 : auto StringViewBase<_CharType>::operator += (size_t l) -> Self & {
738 8874370 : this->offset(l);
739 8874370 : return *this;
740 : }
741 :
742 : template <typename _CharType>
743 438700260 : auto StringViewBase<_CharType>::is(const CharType &c) const -> bool {
744 438700260 : return this->len > 0 && *this->ptr == c;
745 : }
746 :
747 : template <typename _CharType>
748 811327 : auto StringViewBase<_CharType>::is(const CharType *c) const -> bool {
749 811327 : return this->prefix(c, TraitsType::length(c));
750 : }
751 :
752 : template <typename _CharType>
753 6475 : auto StringViewBase<_CharType>::is(const Self &c) const -> bool {
754 6475 : return this->prefix(c.data(), c.size());
755 : }
756 :
757 : template <typename _CharType>
758 : template <_CharType C>
759 675 : auto StringViewBase<_CharType>::is() const -> bool {
760 675 : return this->len > 0 && *this->ptr ==C;
761 : }
762 :
763 : template <typename _CharType>
764 : template <CharGroupId G>
765 50 : auto StringViewBase<_CharType>::is() const -> bool {
766 50 : return this->len > 0 && MatchCharGroup<G>::match(*this->ptr);
767 : }
768 :
769 : template <typename _CharType>
770 : template <typename M>
771 196531 : auto StringViewBase<_CharType>::is() const -> bool {
772 288212 : return this->len > 0 && M::match(*this->ptr);
773 : }
774 :
775 : template <typename _CharType>
776 355 : auto StringViewBase<_CharType>::begin() const -> Self {
777 355 : return Self(this->ptr, this->len);
778 : }
779 :
780 : template <typename _CharType>
781 355 : auto StringViewBase<_CharType>::end() const -> Self {
782 355 : return Self(this->ptr + this->len, 0);
783 : }
784 :
785 : template <typename _CharType>
786 : auto StringViewBase<_CharType>::operator - (const Self &other) const -> Self {
787 : if (this->ptr > other.ptr && size_t(this->ptr - other.ptr) < this->len) {
788 : return Self(this->ptr, this->ptr - other.ptr);
789 : }
790 : return Self();
791 : }
792 :
793 : template <typename _CharType>
794 : auto StringViewBase<_CharType>::operator -= (const Self &other) const -> Self & {
795 : if (this->ptr > other.ptr && size_t(this->ptr - other.ptr) < this->len) {
796 : this->len = this->ptr - other.ptr;
797 : return *this;
798 : }
799 : return *this;
800 : }
801 :
802 : template <typename _CharType>
803 5125 : auto StringViewBase<_CharType>::readFloat() -> Result<float> {
804 5125 : Self tmp = *this;
805 5125 : tmp.skipChars<typename Self::template CharGroup<CharGroupId::WhiteSpace>>();
806 5125 : uint8_t offset = 0;
807 5125 : auto ret = string::readNumber<float>(tmp.ptr, tmp.len, 0, offset);
808 5125 : this->ptr += offset; this->len -= offset;
809 5125 : return ret;
810 : }
811 :
812 : template <typename _CharType>
813 51375 : auto StringViewBase<_CharType>::readDouble() -> Result<double> {
814 51375 : Self tmp = *this;
815 51375 : tmp.skipChars<typename Self::template CharGroup<CharGroupId::WhiteSpace>>();
816 51375 : uint8_t offset = 0;
817 51375 : auto ret = string::readNumber<double>(tmp.ptr, tmp.len, 0, offset);
818 51375 : this->ptr += offset; this->len -= offset;
819 51375 : return ret;
820 : }
821 :
822 : template <typename _CharType>
823 5080917 : auto StringViewBase<_CharType>::readInteger(int base) -> Result<int64_t> {
824 5080917 : Self tmp = *this;
825 5080917 : tmp.skipChars<typename Self::template CharGroup<CharGroupId::WhiteSpace>>();
826 5080917 : uint8_t offset = 0;
827 5080917 : auto ret = string::readNumber<int64_t>(tmp.ptr, tmp.len, 0, offset);
828 5080917 : this->ptr += offset; this->len -= offset;
829 5080917 : return ret;
830 : }
831 :
832 : template <typename _CharType>
833 : template<typename ... Args>
834 86743162 : auto StringViewBase<_CharType>::skipChars() -> void {
835 86743162 : size_t offset = 0;
836 276598345 : while (this->len > offset && match<Args...>(this->ptr[offset])) {
837 189855183 : ++offset;
838 : }
839 86743161 : auto off = std::min(offset, this->len);
840 86743167 : this->len -= off;
841 86743167 : this->ptr += off;
842 86743167 : }
843 :
844 : template <typename _CharType>
845 : template<typename ... Args>
846 187742922 : auto StringViewBase<_CharType>::skipUntil() -> void {
847 187742922 : size_t offset = 0;
848 2701107240 : while (this->len > offset && !match<Args...>(this->ptr[offset])) {
849 2513364318 : ++offset;
850 : }
851 187742927 : auto off = std::min(offset, this->len);
852 187742925 : this->len -= off;
853 187742925 : this->ptr += off;
854 187742925 : }
855 :
856 : template <typename _CharType>
857 : template<typename ... Args>
858 184257 : auto StringViewBase<_CharType>::backwardSkipChars() -> void {
859 239578 : while (this->len > 0 && match<Args...>(this->ptr[this->len - 1])) {
860 55321 : -- this->len;
861 : }
862 184257 : }
863 :
864 : template <typename _CharType>
865 : template<typename ... Args>
866 750 : auto StringViewBase<_CharType>::backwardSkipUntil() -> void {
867 1375 : while (this->len > 0 && !match<Args...>(this->ptr[this->len - 1])) {
868 625 : -- this->len;
869 : }
870 750 : }
871 :
872 : template <typename _CharType>
873 300 : auto StringViewBase<_CharType>::skipString(const Self &str) -> bool {
874 300 : if (!this->ptr) {
875 0 : return false;
876 : }
877 300 : if (this->prefix(str.data(), str.size())) {
878 300 : auto s = std::min(str.size(), this->len);
879 300 : this->ptr += s;
880 300 : this->len -= s;
881 300 : return true;
882 : }
883 0 : return false;
884 : }
885 :
886 : template <typename _CharType>
887 10171 : auto StringViewBase<_CharType>::skipUntilString(const Self &str, bool stopBeforeString) -> bool {
888 10171 : if (!this->ptr) {
889 0 : return false;
890 : }
891 :
892 125841 : while (this->len > 0 && !this->prefix(str.data(), str.size())) {
893 115670 : this->ptr += 1;
894 115670 : this->len -= 1;
895 : }
896 10173 : if (this->len > 0 && *this->ptr != 0 && !stopBeforeString) {
897 0 : skipString(str);
898 : }
899 :
900 10174 : return this->len > 0 && *this->ptr != 0;
901 : }
902 :
903 : template <typename _CharType>
904 : template <typename ... Args>
905 293040 : auto StringViewBase<_CharType>::readChars() -> Self {
906 293040 : auto tmp = *this;
907 293040 : skipChars<Args ...>();
908 293040 : return Self(tmp.data(), tmp.size() - this->size());
909 : }
910 :
911 : template <typename _CharType>
912 : template <typename ... Args>
913 110264777 : auto StringViewBase<_CharType>::readUntil() -> Self {
914 110264777 : auto tmp = *this;
915 110264777 : skipUntil<Args ...>();
916 110264779 : return Self(tmp.data(), tmp.size() - this->size());
917 : }
918 :
919 : template <typename _CharType>
920 : template<typename ... Args>
921 : auto StringViewBase<_CharType>::backwardReadChars() -> Self {
922 : auto tmp = *this;
923 : backwardSkipChars<Args ...>();
924 : return Self(this->data() + this->size(), tmp.size() - this->size());
925 : }
926 :
927 : template <typename _CharType>
928 : template<typename ... Args>
929 50 : auto StringViewBase<_CharType>::backwardReadUntil() -> Self {
930 50 : auto tmp = *this;
931 50 : backwardSkipUntil<Args ...>();
932 50 : return Self(this->data() + this->size(), tmp.size() - this->size());
933 : }
934 :
935 : template <typename _CharType>
936 4723 : auto StringViewBase<_CharType>::readUntilString(const Self &str) -> Self {
937 4723 : auto tmp = *this;
938 4723 : skipUntilString(str);
939 4724 : return Self(tmp.data(), tmp.size() - this->size());
940 : }
941 :
942 : template <typename _CharType>
943 : template<typename Separator, typename Callback>
944 4281 : auto StringViewBase<_CharType>::split(const Callback &cb) const -> void {
945 4281 : Self str(*this);
946 17206 : while (!str.empty()) {
947 12925 : str.skipChars<Separator>();
948 12925 : auto tmp = str.readUntil<Separator>();
949 12925 : if (!tmp.empty()) {
950 12925 : cb(tmp);
951 : }
952 : }
953 4281 : }
954 :
955 : template <typename _CharType>
956 : template<typename ... Args>
957 162848 : auto StringViewBase<_CharType>::trimChars() -> void {
958 162848 : this->skipChars<Args...>();
959 162848 : if (!this->empty()) {
960 161073 : this->backwardSkipChars<Args...>();
961 : }
962 162848 : }
963 :
964 : template <typename _CharType>
965 : template <typename... Args>
966 700 : auto StringViewBase<_CharType>::trimUntil() -> void {
967 700 : this->skipUntil<Args...>();
968 700 : if (!this->empty()) {
969 700 : this->backwardSkipUntil<Args...>();
970 : }
971 700 : }
972 :
973 : template <typename _CharType>
974 : template <typename ...Args>
975 2977661272 : auto StringViewBase<_CharType>::match (CharType c) -> bool {
976 5955322544 : return chars::Compose<CharType, Args...>::match(c);
977 : }
978 :
979 :
980 50 : inline StringViewUtf8::StringViewUtf8() : BytesReader(nullptr, 0) { }
981 :
982 193484 : inline StringViewUtf8::StringViewUtf8(const char *ptr, size_t len)
983 193484 : : BytesReader(ptr, string::length(ptr, len)) { }
984 :
985 : inline StringViewUtf8::StringViewUtf8(const char *ptr, size_t pos, size_t len)
986 : : BytesReader(ptr + pos, string::length(ptr + pos, len)) { }
987 :
988 50 : inline StringViewUtf8::StringViewUtf8(const StringViewUtf8 &ptr, size_t len)
989 50 : : StringViewUtf8(ptr, 0, len) { }
990 :
991 10000 : inline StringViewUtf8::StringViewUtf8(const StringViewUtf8 &ptr, size_t pos, size_t len)
992 10000 : : BytesReader(ptr.data() + pos, min(len, ptr.size() - pos)) { }
993 :
994 100 : inline StringViewUtf8::StringViewUtf8(const PoolString &str)
995 100 : : StringViewUtf8(str.data(), str.size()) { }
996 :
997 : inline StringViewUtf8::StringViewUtf8(const StdString &str)
998 : : StringViewUtf8(str.data(), str.size()) { }
999 :
1000 39850 : inline StringViewUtf8::StringViewUtf8(const StringViewBase<char> &str)
1001 39850 : : StringViewUtf8(str.data(), str.size()) { }
1002 :
1003 : inline auto StringViewUtf8::operator =(const PoolString &str) -> Self & {
1004 : this->set(str);
1005 : return *this;
1006 : }
1007 : inline auto StringViewUtf8::operator =(const StdString &str) -> Self & {
1008 : this->set(str);
1009 : return *this;
1010 : }
1011 250075 : inline auto StringViewUtf8::operator =(const Self &str) -> Self & {
1012 250075 : this->set(str);
1013 250075 : return *this;
1014 : }
1015 :
1016 : inline auto StringViewUtf8::set(const PoolString &str) -> Self & {
1017 : this->set(str.data(), str.size());
1018 : return *this;
1019 : }
1020 : inline auto StringViewUtf8::set(const StdString &str) -> Self & {
1021 : this->set(str.data(), str.size());
1022 : return *this;
1023 : }
1024 250075 : inline auto StringViewUtf8::set(const Self &str) -> Self & {
1025 250075 : this->set(str.data(), str.size());
1026 250075 : return *this;
1027 : }
1028 250100 : inline auto StringViewUtf8::set(const char *p, size_t l) -> Self & {
1029 250100 : ptr = p; len = l;
1030 250100 : return *this;
1031 : }
1032 :
1033 1492736 : inline bool StringViewUtf8::is(const char &c) const {
1034 1492736 : return len > 0 && *ptr == c;
1035 : }
1036 10059 : inline bool StringViewUtf8::is(const char16_t &c) const {
1037 10059 : return len > 0 && len >= unicode::utf8_length_data[uint8_t(*ptr)] && unicode::utf8Decode32(ptr) == c;
1038 : }
1039 : inline bool StringViewUtf8::is(const char32_t &c) const {
1040 : return len > 0 && len >= unicode::utf8_length_data[uint8_t(*ptr)] && unicode::utf8Decode32(ptr) == c;
1041 : }
1042 125 : inline bool StringViewUtf8::is(const char *c) const {
1043 125 : return prefix(c, std::char_traits<char>::length(c));
1044 : }
1045 : inline bool StringViewUtf8::is(const Self &c) const {
1046 : return prefix(c.data(), c.size());
1047 : }
1048 :
1049 : template <char32_t C>
1050 : inline bool StringViewUtf8::is() const {
1051 : return len > 0 && len >= unicode::utf8_length_data[uint8_t(*ptr)] && unicode::utf8Decode32(ptr) == C;
1052 : }
1053 :
1054 : template <CharGroupId G>
1055 : inline bool StringViewUtf8::is() const {
1056 : return len > 0 && len >= unicode::utf8_length_data[uint8_t(*ptr)] && chars::CharGroup<MatchCharType, G>::match(unicode::utf8Decode32(ptr));
1057 : }
1058 :
1059 : template <typename M>
1060 275984 : inline bool StringViewUtf8::is() const {
1061 550893 : return len > 0 && len >= unicode::utf8_length_data[uint8_t(*ptr)] && M::match(unicode::utf8Decode32(ptr));
1062 : }
1063 :
1064 : inline auto StringViewUtf8::letter() const -> Self {
1065 : if (this->len > 0) {
1066 : return Self(this->ptr, std::min(this->len, size_t( unicode::utf8_length_data[uint8_t(*ptr)] )));
1067 : }
1068 : return Self();
1069 : }
1070 : template <typename Interface>
1071 : inline auto StringViewUtf8::str() const -> typename Interface::StringType {
1072 : if (this->ptr && this->len > 0) {
1073 : return typename Interface::StringType(this->ptr, this->len);
1074 : }
1075 : return typename Interface::StringType();
1076 : }
1077 :
1078 : // extend offset functions with unicode support
1079 200 : inline void StringViewUtf8::offset(size_t l) {
1080 650 : while (l > 0 && len > 0) {
1081 450 : ++ (*this); -- l;
1082 : }
1083 200 : }
1084 28475 : inline auto StringViewUtf8::operator ++ () -> Self & {
1085 28475 : if (len > 0) {
1086 28450 : auto l = std::min(size_t( unicode::utf8_length_data[uint8_t(*ptr)] ), len);
1087 28450 : ptr += l; len -= l;
1088 : }
1089 28475 : return *this;
1090 : }
1091 350 : inline auto StringViewUtf8::operator ++ (int) -> Self {
1092 350 : auto tmp = *this;
1093 350 : ++ (*this);
1094 350 : return tmp;
1095 : }
1096 175 : inline auto StringViewUtf8::operator += (size_t l) -> Self & {
1097 175 : offset(l);
1098 175 : return *this;
1099 : }
1100 :
1101 : inline bool StringViewUtf8::isSpace() const {
1102 : auto tmp = *this;
1103 : tmp.skipChars<WhiteSpace>();
1104 : return tmp.empty();
1105 : }
1106 :
1107 : inline auto StringViewUtf8::begin() const -> Self {
1108 : return Self(this->ptr, this->len);
1109 : }
1110 : inline auto StringViewUtf8::end() const -> Self {
1111 : return Self(this->ptr + this->len, 0);
1112 : }
1113 : inline auto StringViewUtf8::operator - (const Self &other) const -> Self {
1114 : if (this->ptr > other.ptr && size_t(this->ptr - other.ptr) < this->len) {
1115 : return Self(this->ptr, this->ptr - other.ptr);
1116 : }
1117 : return Self();
1118 : }
1119 : inline auto StringViewUtf8::operator -= (const Self &other) -> Self & {
1120 : if (this->ptr > other.ptr && size_t(this->ptr - other.ptr) < this->len) {
1121 : this->len = this->ptr - other.ptr;
1122 : return *this;
1123 : }
1124 : return *this;
1125 : }
1126 : inline auto StringViewUtf8::operator * () const -> MatchCharType {
1127 : return unicode::utf8Decode32(ptr);
1128 : }
1129 :
1130 : template <typename Callback>
1131 25 : inline void StringViewUtf8::foreach(const Callback &cb) const {
1132 25 : auto p = ptr;
1133 25 : const auto e = ptr + len;
1134 125 : while (p < e) {
1135 100 : const uint8_t mask = unicode::utf8_length_mask[uint8_t(*p)];
1136 100 : const uint8_t len = unicode::utf8_length_data[uint8_t(*p)];
1137 100 : uint32_t ret = *p++ & mask;
1138 200 : for (uint8_t c = 1; c < len; ++c) {
1139 100 : const auto ch = *p++;
1140 100 : if ((ch & 0xc0) != 0x80) {
1141 0 : ret = 0;
1142 0 : break;
1143 : }
1144 100 : ret <<= 6;
1145 100 : ret |= (ch & 0x3f);
1146 : }
1147 100 : cb(MatchCharType(ret));
1148 : }
1149 25 : }
1150 :
1151 : inline size_t StringViewUtf8::code_size() const {
1152 : size_t ret = 0;
1153 : auto p = ptr;
1154 : const auto e = ptr + len;
1155 : while (p < e) {
1156 : ++ ret;
1157 : p += unicode::utf8_length_data[uint8_t(*p)];
1158 : }
1159 : return ret;
1160 : }
1161 :
1162 37025 : inline StringViewUtf8::operator StringViewBase<char> () const {
1163 37025 : return StringViewBase<char>(ptr, len);
1164 : }
1165 :
1166 : inline Result<float> StringViewUtf8::readFloat() {
1167 : Self tmp = *this;
1168 : tmp.skipChars<CharGroup<CharGroupId::WhiteSpace>>();
1169 : uint8_t offset = 0;
1170 : auto ret = string::readNumber<float>(tmp.ptr, tmp.len, 0, offset);
1171 : this->ptr += offset; this->len -= offset;
1172 : return ret;
1173 : }
1174 : inline Result<double> StringViewUtf8::readDouble() {
1175 : Self tmp = *this;
1176 : tmp.skipChars<CharGroup<CharGroupId::WhiteSpace>>();
1177 : uint8_t offset = 0;
1178 : auto ret = string::readNumber<double>(tmp.ptr, tmp.len, 0, offset);
1179 : this->ptr += offset; this->len -= offset;
1180 : return ret;
1181 : }
1182 : inline Result<int64_t> StringViewUtf8::readInteger(int base) {
1183 : Self tmp = *this;
1184 : tmp.skipChars<CharGroup<CharGroupId::WhiteSpace>>();
1185 : uint8_t offset = 0;
1186 : auto ret = string::readNumber<int64_t>(tmp.ptr, tmp.len, 0, offset);
1187 : this->ptr += offset; this->len -= offset;
1188 : return ret;
1189 : }
1190 :
1191 : template<typename ... Args>
1192 148434 : inline void StringViewUtf8::skipChars() {
1193 148434 : uint8_t clen = 0;
1194 148434 : size_t offset = 0;
1195 858452 : while (len > offset && match<Args...>(unicode::utf8Decode32(ptr + offset, clen)) && clen > 0) {
1196 710018 : offset += clen;
1197 : }
1198 148434 : auto off = std::min(offset, len);
1199 148434 : len -= off;
1200 148434 : ptr += off;
1201 148434 : }
1202 :
1203 : template<typename ... Args>
1204 132825 : inline void StringViewUtf8::skipUntil() {
1205 132825 : uint8_t clen = 0;
1206 132825 : size_t offset = 0;
1207 281525 : while (len > offset && !match<Args...>(unicode::utf8Decode32(ptr + offset, clen)) && clen > 0) {
1208 148700 : offset += clen;
1209 : }
1210 132825 : auto off = std::min(offset, len);
1211 132825 : len -= off;
1212 132825 : ptr += off;
1213 132825 : }
1214 :
1215 : template<typename ... Args>
1216 2475 : inline void StringViewUtf8::backwardSkipChars() {
1217 2475 : uint8_t clen = 0;
1218 3600 : while (this->len > 0 && rv_match_utf8<Args...>(this->ptr, this->len, clen)) {
1219 1125 : if (clen > 0) {
1220 1125 : this->len -= std::min(size_t(clen), this->len);
1221 : } else {
1222 0 : return;
1223 : }
1224 : }
1225 : }
1226 :
1227 : template<typename ... Args>
1228 725 : inline void StringViewUtf8::backwardSkipUntil() {
1229 725 : uint8_t clen = 0;
1230 5200 : while (this->len > 0 && !rv_match_utf8<Args...>(this->ptr, this->len, clen)) {
1231 4475 : if (clen > 0) {
1232 4475 : this->len -= std::min(size_t(clen), this->len);;
1233 : } else {
1234 0 : return;
1235 : }
1236 : }
1237 : }
1238 :
1239 : inline bool StringViewUtf8::skipString(const Self &str) {
1240 : if (!ptr) {
1241 : return false;
1242 : }
1243 : if (this->prefix(str.data(), str.size())) {
1244 : auto s = std::min(len, str.size());
1245 : ptr += s;
1246 : len -= s;
1247 : return true;
1248 : }
1249 : return false;
1250 : }
1251 : inline bool StringViewUtf8::skipUntilString(const Self &str, bool stopBeforeString) {
1252 : if (!ptr) {
1253 : return false;
1254 : }
1255 :
1256 : while (this->len > 0 && !this->prefix(str.data(), str.size())) {
1257 : this->ptr += 1;
1258 : this->len -= 1;
1259 : }
1260 : if (this->len > 0 && *this->ptr != 0 && !stopBeforeString) {
1261 : skipString(str);
1262 : }
1263 :
1264 : return this->len > 0 && *this->ptr != 0;
1265 : }
1266 :
1267 : template<typename ... Args>
1268 18934 : inline auto StringViewUtf8::readChars() -> Self {
1269 18934 : auto tmp = *this;
1270 18934 : skipChars<Args ...>();
1271 18934 : return Self(tmp.data(), tmp.size() - this->size());
1272 : }
1273 :
1274 : template<typename ... Args>
1275 132125 : inline auto StringViewUtf8::readUntil() -> Self {
1276 132125 : auto tmp = *this;
1277 132125 : skipUntil<Args ...>();
1278 132125 : return Self(tmp.data(), tmp.size() - this->size());
1279 : }
1280 :
1281 : template<typename ... Args>
1282 25 : inline auto StringViewUtf8::backwardReadChars() -> Self {
1283 25 : auto tmp = *this;
1284 25 : backwardSkipChars<Args ...>();
1285 25 : return Self(this->data() + this->size(), tmp.size() - this->size());
1286 : }
1287 :
1288 : template<typename ... Args>
1289 700 : inline auto StringViewUtf8::backwardReadUntil() -> Self {
1290 700 : auto tmp = *this;
1291 700 : backwardSkipUntil<Args ...>();
1292 700 : return Self(this->data() + this->size(), tmp.size() - this->size());
1293 : }
1294 :
1295 : inline auto StringViewUtf8::readUntilString(const Self &str) -> Self {
1296 : auto tmp = *this;
1297 : skipUntilString(str);
1298 : return Self(tmp.data(), tmp.size() - this->size());
1299 : }
1300 :
1301 : template<typename Separator, typename Callback>
1302 : inline void StringViewUtf8::split(const Callback &cb) const {
1303 : Self str(*this);
1304 : while (!str.empty()) {
1305 : str.skipChars<Separator>();
1306 : auto tmp = str.readUntil<Separator>();
1307 : if (!tmp.empty()) {
1308 : cb(tmp);
1309 : }
1310 : }
1311 : }
1312 :
1313 : template<typename ... Args>
1314 1775 : inline void StringViewUtf8::trimChars() {
1315 1775 : this->skipChars<Args...>();
1316 1775 : if (!this->empty()) {
1317 1775 : this->backwardSkipChars<Args...>();
1318 : }
1319 1775 : }
1320 :
1321 : template <typename... Args>
1322 25 : inline void StringViewUtf8::trimUntil() {
1323 25 : this->skipUntil<Args...>();
1324 25 : if (!this->empty()) {
1325 25 : this->backwardSkipUntil<Args...>();
1326 : }
1327 25 : }
1328 :
1329 : template <typename ...Args>
1330 8800 : inline bool StringViewUtf8::rv_match_utf8 (const CharType *ptr, size_t len, uint8_t &offset) {
1331 15900 : while (len > 0) {
1332 31800 : if (!unicode::isUtf8Surrogate(ptr[len - 1])) {
1333 8800 : return match<Args...>(unicode::utf8Decode32(ptr + len - 1, offset));
1334 : } else {
1335 7100 : -- len;
1336 : }
1337 : }
1338 0 : offset = 0;
1339 0 : return false;
1340 : }
1341 :
1342 : template <typename ...Args>
1343 1134827 : inline bool StringViewUtf8::match (MatchCharType c) {
1344 1134827 : return chars::Compose<MatchCharType, Args...>::match(c);
1345 : }
1346 :
1347 : }
1348 :
1349 :
1350 : namespace STAPPLER_VERSIONIZED stappler::string {
1351 :
1352 : template <typename L, typename R, typename CharType>
1353 15859895 : inline int compare_c(const L &l, const R &r) {
1354 15859895 : auto __lsize = l.size();
1355 15859899 : auto __rsize = r.size();
1356 15859898 : auto __len = std::min(__lsize, __rsize);
1357 15859890 : auto ret = std::char_traits<CharType>::compare(l.data(), r.data(), __len);
1358 15859886 : if (!ret) {
1359 1419978 : if (__lsize < __rsize) {
1360 103386 : return -1;
1361 1316592 : } else if (__lsize == __rsize) {
1362 1251632 : return 0;
1363 : } else {
1364 64960 : return 1;
1365 : }
1366 : }
1367 14439908 : return ret;
1368 : }
1369 :
1370 : template <typename L, typename R, typename CharType>
1371 : inline int compare_u(const L &l, const R &r) {
1372 : return platform::compare_u(l, r);
1373 : }
1374 :
1375 15675 : inline int _strncasecmp(const char *l, const char *r, size_t len) {
1376 15675 : return ::strncasecmp(l, r, len);
1377 : }
1378 :
1379 25 : inline int _strncasecmp(const char16_t *l, const char16_t *r, size_t len) {
1380 125 : while (len > 0) {
1381 100 : auto lc = std::tolower(*l ++);
1382 100 : auto rc = std::tolower(*r ++);
1383 100 : if (lc != rc) {
1384 0 : return (lc < rc)?-1:1;
1385 : }
1386 100 : -- len;
1387 : }
1388 25 : return 0;
1389 : }
1390 :
1391 : template <typename L, typename R, typename CharType>
1392 15675 : inline int caseCompare_c(const L &l, const R &r) {
1393 15675 : auto __lsize = l.size();
1394 15675 : auto __rsize = r.size();
1395 15675 : auto __len = std::min(__lsize, __rsize);
1396 15675 : auto ret = _strncasecmp(l.data(), r.data(), __len);
1397 15675 : if (!ret) {
1398 525 : if (__lsize < __rsize) {
1399 0 : return -1;
1400 525 : } else if (__lsize == __rsize) {
1401 500 : return 0;
1402 : } else {
1403 25 : return 1;
1404 : }
1405 : }
1406 15150 : return ret;
1407 : }
1408 :
1409 : template <typename L, typename R, typename CharType>
1410 15925 : inline int caseCompare_u(const L &l, const R &r) {
1411 15925 : return platform::caseCompare_u(l, r);
1412 : }
1413 :
1414 : }
1415 :
1416 :
1417 : namespace std {
1418 :
1419 : template <>
1420 : struct hash<STAPPLER_VERSIONIZED_NAMESPACE::StringView> {
1421 48 : hash() { }
1422 :
1423 91129 : size_t operator() (const STAPPLER_VERSIONIZED_NAMESPACE::StringView &value) const noexcept {
1424 91129 : return hash<string_view>()(string_view(value.data(), value.size()));
1425 : }
1426 : };
1427 :
1428 : template <>
1429 : struct hash<STAPPLER_VERSIONIZED_NAMESPACE::StringViewUtf8> {
1430 : hash() { }
1431 :
1432 : size_t operator() (const STAPPLER_VERSIONIZED_NAMESPACE::StringViewUtf8 &value) const noexcept {
1433 : return hash<string_view>()(string_view(value.data(), value.size()));
1434 : }
1435 : };
1436 :
1437 : template <>
1438 : struct hash<STAPPLER_VERSIONIZED_NAMESPACE::WideStringView> {
1439 : hash() { }
1440 :
1441 : size_t operator() (const STAPPLER_VERSIONIZED_NAMESPACE::WideStringView &value) const noexcept {
1442 : return hash<u16string_view>()(u16string_view(value.data(), value.size()));
1443 : }
1444 : };
1445 :
1446 : }
1447 :
1448 : #endif /* STAPPLER_CORE_STRING_SPSTRINGVIEW_H_ */
|