LCOV - code coverage report
Current view: top level - core/core/string - SPStringView.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 403 423 95.3 %
Date: 2024-05-12 00:16:13 Functions: 532 593 89.7 %

          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_ */

Generated by: LCOV version 1.14