xref: /freebsd-src/contrib/llvm-project/libcxx/include/__string/char_traits.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
181ad6265SDimitry Andric //===----------------------------------------------------------------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #ifndef _LIBCPP___STRING_CHAR_TRAITS_H
1081ad6265SDimitry Andric #define _LIBCPP___STRING_CHAR_TRAITS_H
1181ad6265SDimitry Andric 
1281ad6265SDimitry Andric #include <__algorithm/copy_n.h>
1381ad6265SDimitry Andric #include <__algorithm/fill_n.h>
1481ad6265SDimitry Andric #include <__algorithm/find_end.h>
1581ad6265SDimitry Andric #include <__algorithm/find_first_of.h>
1681ad6265SDimitry Andric #include <__algorithm/min.h>
17*bdd1243dSDimitry Andric #include <__compare/ordering.h>
1881ad6265SDimitry Andric #include <__config>
1981ad6265SDimitry Andric #include <__functional/hash.h>
2081ad6265SDimitry Andric #include <__iterator/iterator_traits.h>
21*bdd1243dSDimitry Andric #include <__type_traits/is_constant_evaluated.h>
22*bdd1243dSDimitry Andric #include <cstddef>
2381ad6265SDimitry Andric #include <cstdint>
2481ad6265SDimitry Andric #include <cstdio>
2581ad6265SDimitry Andric #include <cstring>
2681ad6265SDimitry Andric #include <iosfwd>
2781ad6265SDimitry Andric 
2881ad6265SDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2981ad6265SDimitry Andric #   include <cwchar> // for wmemcpy
3081ad6265SDimitry Andric #endif
3181ad6265SDimitry Andric 
3281ad6265SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
3381ad6265SDimitry Andric #  pragma GCC system_header
3481ad6265SDimitry Andric #endif
3581ad6265SDimitry Andric 
3681ad6265SDimitry Andric _LIBCPP_PUSH_MACROS
3781ad6265SDimitry Andric #include <__undef_macros>
3881ad6265SDimitry Andric 
3981ad6265SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
4081ad6265SDimitry Andric 
4181ad6265SDimitry Andric template <class _CharT>
42*bdd1243dSDimitry Andric struct char_traits;
43*bdd1243dSDimitry Andric /*
44*bdd1243dSDimitry Andric The Standard does not define the base template for char_traits because it is impossible to provide
45*bdd1243dSDimitry Andric a correct definition for arbitrary character types. Instead, it requires implementations to provide
46*bdd1243dSDimitry Andric specializations for predefined character types like `char`, `wchar_t` and others. We provide this as
47*bdd1243dSDimitry Andric exposition-only to document what members a char_traits specialization should provide:
4881ad6265SDimitry Andric {
49*bdd1243dSDimitry Andric     using char_type  = _CharT;
50*bdd1243dSDimitry Andric     using int_type   = ...;
51*bdd1243dSDimitry Andric     using off_type   = ...;
52*bdd1243dSDimitry Andric     using pos_type   = ...;
53*bdd1243dSDimitry Andric     using state_type = ...;
5481ad6265SDimitry Andric 
55*bdd1243dSDimitry Andric     static void assign(char_type&, const char_type&);
56*bdd1243dSDimitry Andric     static bool eq(char_type, char_type);
57*bdd1243dSDimitry Andric     static bool lt(char_type, char_type);
58*bdd1243dSDimitry Andric 
59*bdd1243dSDimitry Andric     static int              compare(const char_type*, const char_type*, size_t);
60*bdd1243dSDimitry Andric     static size_t           length(const char_type*);
61*bdd1243dSDimitry Andric     static const char_type* find(const char_type*, size_t, const char_type&);
62*bdd1243dSDimitry Andric     static char_type*       move(char_type*, const char_type*, size_t);
63*bdd1243dSDimitry Andric     static char_type*       copy(char_type*, const char_type*, size_t);
64*bdd1243dSDimitry Andric     static char_type*       assign(char_type*, size_t, char_type);
65*bdd1243dSDimitry Andric 
66*bdd1243dSDimitry Andric     static int_type  not_eof(int_type);
67*bdd1243dSDimitry Andric     static char_type to_char_type(int_type);
68*bdd1243dSDimitry Andric     static int_type  to_int_type(char_type);
69*bdd1243dSDimitry Andric     static bool      eq_int_type(int_type, int_type);
70*bdd1243dSDimitry Andric     static int_type  eof();
71*bdd1243dSDimitry Andric };
72*bdd1243dSDimitry Andric */
73*bdd1243dSDimitry Andric 
74*bdd1243dSDimitry Andric //
75*bdd1243dSDimitry Andric // Temporary extension to provide a base template for std::char_traits.
76*bdd1243dSDimitry Andric // TODO: Remove in LLVM 18.
77*bdd1243dSDimitry Andric //
78*bdd1243dSDimitry Andric template <class _CharT>
79*bdd1243dSDimitry Andric struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, char8_t, char16_t or char32_t is non-standard and is provided for a temporary period. It will be removed in LLVM 18, so please migrate off of it.")
80*bdd1243dSDimitry Andric     char_traits
81*bdd1243dSDimitry Andric {
82*bdd1243dSDimitry Andric     using char_type  = _CharT;
83*bdd1243dSDimitry Andric     using int_type   = int;
84*bdd1243dSDimitry Andric     using off_type   = streamoff;
85*bdd1243dSDimitry Andric     using pos_type   = streampos;
86*bdd1243dSDimitry Andric     using state_type = mbstate_t;
87*bdd1243dSDimitry Andric 
88*bdd1243dSDimitry Andric     static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17
8981ad6265SDimitry Andric         assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
9081ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
9181ad6265SDimitry Andric         {return __c1 == __c2;}
9281ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
9381ad6265SDimitry Andric         {return __c1 < __c2;}
9481ad6265SDimitry Andric 
95*bdd1243dSDimitry Andric     static _LIBCPP_CONSTEXPR_SINCE_CXX17
96*bdd1243dSDimitry Andric     int compare(const char_type* __s1, const char_type* __s2, size_t __n) {
9781ad6265SDimitry Andric         for (; __n; --__n, ++__s1, ++__s2)
9881ad6265SDimitry Andric         {
9981ad6265SDimitry Andric             if (lt(*__s1, *__s2))
10081ad6265SDimitry Andric                 return -1;
10181ad6265SDimitry Andric             if (lt(*__s2, *__s1))
10281ad6265SDimitry Andric                 return 1;
10381ad6265SDimitry Andric         }
10481ad6265SDimitry Andric         return 0;
10581ad6265SDimitry Andric     }
106*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
107*bdd1243dSDimitry Andric     size_t length(const char_type* __s) {
10881ad6265SDimitry Andric         size_t __len = 0;
10981ad6265SDimitry Andric         for (; !eq(*__s, char_type(0)); ++__s)
11081ad6265SDimitry Andric             ++__len;
11181ad6265SDimitry Andric         return __len;
11281ad6265SDimitry Andric     }
113*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
114*bdd1243dSDimitry Andric     const char_type* find(const char_type* __s, size_t __n, const char_type& __a) {
11581ad6265SDimitry Andric         for (; __n; --__n)
11681ad6265SDimitry Andric         {
11781ad6265SDimitry Andric             if (eq(*__s, __a))
11881ad6265SDimitry Andric                 return __s;
11981ad6265SDimitry Andric             ++__s;
12081ad6265SDimitry Andric         }
12181ad6265SDimitry Andric         return nullptr;
12281ad6265SDimitry Andric     }
123*bdd1243dSDimitry Andric     static _LIBCPP_CONSTEXPR_SINCE_CXX20
124*bdd1243dSDimitry Andric     char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) {
12581ad6265SDimitry Andric         if (__n == 0) return __s1;
12681ad6265SDimitry Andric         char_type* __r = __s1;
12781ad6265SDimitry Andric         if (__s1 < __s2)
12881ad6265SDimitry Andric         {
12981ad6265SDimitry Andric             for (; __n; --__n, ++__s1, ++__s2)
13081ad6265SDimitry Andric                 assign(*__s1, *__s2);
13181ad6265SDimitry Andric         }
13281ad6265SDimitry Andric         else if (__s2 < __s1)
13381ad6265SDimitry Andric         {
13481ad6265SDimitry Andric             __s1 += __n;
13581ad6265SDimitry Andric             __s2 += __n;
13681ad6265SDimitry Andric             for (; __n; --__n)
13781ad6265SDimitry Andric                 assign(*--__s1, *--__s2);
13881ad6265SDimitry Andric         }
13981ad6265SDimitry Andric         return __r;
14081ad6265SDimitry Andric     }
141*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY
142*bdd1243dSDimitry Andric     static _LIBCPP_CONSTEXPR_SINCE_CXX20
143*bdd1243dSDimitry Andric     char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) {
14481ad6265SDimitry Andric         if (!__libcpp_is_constant_evaluated()) {
14581ad6265SDimitry Andric             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
14681ad6265SDimitry Andric         }
14781ad6265SDimitry Andric         char_type* __r = __s1;
14881ad6265SDimitry Andric         for (; __n; --__n, ++__s1, ++__s2)
14981ad6265SDimitry Andric             assign(*__s1, *__s2);
15081ad6265SDimitry Andric         return __r;
15181ad6265SDimitry Andric     }
152*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY
153*bdd1243dSDimitry Andric     static _LIBCPP_CONSTEXPR_SINCE_CXX20
154*bdd1243dSDimitry Andric     char_type*       assign(char_type* __s, size_t __n, char_type __a) {
15581ad6265SDimitry Andric         char_type* __r = __s;
15681ad6265SDimitry Andric         for (; __n; --__n, ++__s)
15781ad6265SDimitry Andric             assign(*__s, __a);
15881ad6265SDimitry Andric         return __r;
15981ad6265SDimitry Andric     }
16081ad6265SDimitry Andric 
161*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
162*bdd1243dSDimitry Andric         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
163*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
164*bdd1243dSDimitry Andric         {return char_type(__c);}
165*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type  to_int_type(char_type __c) _NOEXCEPT
166*bdd1243dSDimitry Andric         {return int_type(__c);}
167*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR bool      eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
168*bdd1243dSDimitry Andric         {return __c1 == __c2;}
169*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
170*bdd1243dSDimitry Andric         {return int_type(EOF);}
171*bdd1243dSDimitry Andric };
172*bdd1243dSDimitry Andric 
17381ad6265SDimitry Andric template <class _CharT>
174*bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
17581ad6265SDimitry Andric _CharT* __char_traits_move(_CharT* __dest, const _CharT* __source, size_t __n) _NOEXCEPT
17681ad6265SDimitry Andric {
17781ad6265SDimitry Andric #ifdef _LIBCPP_COMPILER_GCC
17881ad6265SDimitry Andric   if (__libcpp_is_constant_evaluated()) {
17981ad6265SDimitry Andric     if (__n == 0)
18081ad6265SDimitry Andric       return __dest;
18181ad6265SDimitry Andric     _CharT* __allocation = new _CharT[__n];
18281ad6265SDimitry Andric     std::copy_n(__source, __n, __allocation);
18381ad6265SDimitry Andric     std::copy_n(static_cast<const _CharT*>(__allocation), __n, __dest);
18481ad6265SDimitry Andric     delete[] __allocation;
18581ad6265SDimitry Andric     return __dest;
18681ad6265SDimitry Andric   }
18781ad6265SDimitry Andric #endif
18881ad6265SDimitry Andric   ::__builtin_memmove(__dest, __source, __n * sizeof(_CharT));
18981ad6265SDimitry Andric   return __dest;
19081ad6265SDimitry Andric }
19181ad6265SDimitry Andric 
19281ad6265SDimitry Andric // char_traits<char>
19381ad6265SDimitry Andric 
19481ad6265SDimitry Andric template <>
19581ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char>
19681ad6265SDimitry Andric {
197*bdd1243dSDimitry Andric     using char_type           = char;
198*bdd1243dSDimitry Andric     using int_type            = int;
199*bdd1243dSDimitry Andric     using off_type            = streamoff;
200*bdd1243dSDimitry Andric     using pos_type            = streampos;
201*bdd1243dSDimitry Andric     using state_type          = mbstate_t;
202*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17
203*bdd1243dSDimitry Andric     using comparison_category = strong_ordering;
204*bdd1243dSDimitry Andric #endif
20581ad6265SDimitry Andric 
206*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
20781ad6265SDimitry Andric     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
20881ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
20981ad6265SDimitry Andric             {return __c1 == __c2;}
21081ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
21181ad6265SDimitry Andric         {return (unsigned char)__c1 < (unsigned char)__c2;}
21281ad6265SDimitry Andric 
213*bdd1243dSDimitry Andric   static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
214*bdd1243dSDimitry Andric     if (__n == 0)
215*bdd1243dSDimitry Andric       return 0;
216*bdd1243dSDimitry Andric     return std::__constexpr_memcmp(__s1, __s2, __n);
21781ad6265SDimitry Andric   }
21881ad6265SDimitry Andric 
219*bdd1243dSDimitry Andric   static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s)  _NOEXCEPT {
220*bdd1243dSDimitry Andric     return std::__constexpr_strlen(__s);
221*bdd1243dSDimitry Andric   }
22281ad6265SDimitry Andric 
223*bdd1243dSDimitry Andric   static _LIBCPP_CONSTEXPR_SINCE_CXX17
224*bdd1243dSDimitry Andric   const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
225*bdd1243dSDimitry Andric     if (__n == 0)
226*bdd1243dSDimitry Andric         return nullptr;
227*bdd1243dSDimitry Andric     return std::__constexpr_char_memchr(__s, static_cast<int>(__a), __n);
228*bdd1243dSDimitry Andric   }
229*bdd1243dSDimitry Andric 
230*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
23181ad6265SDimitry Andric     char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
23281ad6265SDimitry Andric         return std::__char_traits_move(__s1, __s2, __n);
23381ad6265SDimitry Andric     }
23481ad6265SDimitry Andric 
235*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
23681ad6265SDimitry Andric     char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
23781ad6265SDimitry Andric         if (!__libcpp_is_constant_evaluated())
23881ad6265SDimitry Andric             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
23981ad6265SDimitry Andric         std::copy_n(__s2, __n, __s1);
24081ad6265SDimitry Andric         return __s1;
24181ad6265SDimitry Andric     }
24281ad6265SDimitry Andric 
243*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
24481ad6265SDimitry Andric     char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
24581ad6265SDimitry Andric         std::fill_n(__s, __n, __a);
24681ad6265SDimitry Andric         return __s;
24781ad6265SDimitry Andric     }
24881ad6265SDimitry Andric 
24981ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
25081ad6265SDimitry Andric         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
25181ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
25281ad6265SDimitry Andric         {return char_type(__c);}
25381ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
25481ad6265SDimitry Andric         {return int_type((unsigned char)__c);}
25581ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
25681ad6265SDimitry Andric         {return __c1 == __c2;}
25781ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
25881ad6265SDimitry Andric         {return int_type(EOF);}
25981ad6265SDimitry Andric };
26081ad6265SDimitry Andric 
26181ad6265SDimitry Andric // char_traits<wchar_t>
26281ad6265SDimitry Andric 
26381ad6265SDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
26481ad6265SDimitry Andric template <>
26581ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
26681ad6265SDimitry Andric {
267*bdd1243dSDimitry Andric     using char_type           = wchar_t;
268*bdd1243dSDimitry Andric     using int_type            = wint_t;
269*bdd1243dSDimitry Andric     using off_type            = streamoff;
270*bdd1243dSDimitry Andric     using pos_type            = streampos;
271*bdd1243dSDimitry Andric     using state_type          = mbstate_t;
272*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17
273*bdd1243dSDimitry Andric     using comparison_category = strong_ordering;
274*bdd1243dSDimitry Andric #endif
27581ad6265SDimitry Andric 
276*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
27781ad6265SDimitry Andric     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
27881ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
27981ad6265SDimitry Andric         {return __c1 == __c2;}
28081ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
28181ad6265SDimitry Andric         {return __c1 < __c2;}
28281ad6265SDimitry Andric 
283*bdd1243dSDimitry Andric   static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
284*bdd1243dSDimitry Andric     if (__n == 0)
285*bdd1243dSDimitry Andric         return 0;
286*bdd1243dSDimitry Andric     return std::__constexpr_wmemcmp(__s1, __s2, __n);
287*bdd1243dSDimitry Andric   }
28881ad6265SDimitry Andric 
289*bdd1243dSDimitry Andric   static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT {
290*bdd1243dSDimitry Andric     return std::__constexpr_wcslen(__s);
291*bdd1243dSDimitry Andric   }
292*bdd1243dSDimitry Andric 
293*bdd1243dSDimitry Andric   static _LIBCPP_CONSTEXPR_SINCE_CXX17
294*bdd1243dSDimitry Andric   const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
295*bdd1243dSDimitry Andric     if (__n == 0)
296*bdd1243dSDimitry Andric         return nullptr;
297*bdd1243dSDimitry Andric     return std::__constexpr_wmemchr(__s, __a, __n);
298*bdd1243dSDimitry Andric   }
299*bdd1243dSDimitry Andric 
300*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
30181ad6265SDimitry Andric     char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
30281ad6265SDimitry Andric         return std::__char_traits_move(__s1, __s2, __n);
30381ad6265SDimitry Andric     }
30481ad6265SDimitry Andric 
305*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
30681ad6265SDimitry Andric     char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
30781ad6265SDimitry Andric         if (!__libcpp_is_constant_evaluated())
30881ad6265SDimitry Andric             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
30981ad6265SDimitry Andric         std::copy_n(__s2, __n, __s1);
31081ad6265SDimitry Andric         return __s1;
31181ad6265SDimitry Andric     }
31281ad6265SDimitry Andric 
313*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
31481ad6265SDimitry Andric     char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
31581ad6265SDimitry Andric         std::fill_n(__s, __n, __a);
31681ad6265SDimitry Andric         return __s;
31781ad6265SDimitry Andric     }
31881ad6265SDimitry Andric 
31981ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
32081ad6265SDimitry Andric         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
32181ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
32281ad6265SDimitry Andric         {return char_type(__c);}
32381ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
32481ad6265SDimitry Andric         {return int_type(__c);}
32581ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
32681ad6265SDimitry Andric         {return __c1 == __c2;}
32781ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
32881ad6265SDimitry Andric         {return int_type(WEOF);}
32981ad6265SDimitry Andric };
33081ad6265SDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
33181ad6265SDimitry Andric 
33281ad6265SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T
33381ad6265SDimitry Andric 
33481ad6265SDimitry Andric template <>
33581ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
33681ad6265SDimitry Andric {
337*bdd1243dSDimitry Andric     using char_type           = char8_t;
338*bdd1243dSDimitry Andric     using int_type            = unsigned int;
339*bdd1243dSDimitry Andric     using off_type            = streamoff;
340*bdd1243dSDimitry Andric     using pos_type            = u8streampos;
341*bdd1243dSDimitry Andric     using state_type          = mbstate_t;
342*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17
343*bdd1243dSDimitry Andric     using comparison_category = strong_ordering;
344*bdd1243dSDimitry Andric #endif
34581ad6265SDimitry Andric 
34681ad6265SDimitry Andric     static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
34781ad6265SDimitry Andric         {__c1 = __c2;}
34881ad6265SDimitry Andric     static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
34981ad6265SDimitry Andric         {return __c1 == __c2;}
35081ad6265SDimitry Andric     static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
35181ad6265SDimitry Andric         {return __c1 < __c2;}
35281ad6265SDimitry Andric 
353*bdd1243dSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI constexpr int
354*bdd1243dSDimitry Andric   compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
355*bdd1243dSDimitry Andric       return std::__constexpr_memcmp(__s1, __s2, __n);
356*bdd1243dSDimitry Andric   }
35781ad6265SDimitry Andric 
35881ad6265SDimitry Andric     static constexpr
35981ad6265SDimitry Andric     size_t           length(const char_type* __s) _NOEXCEPT;
36081ad6265SDimitry Andric 
36181ad6265SDimitry Andric     _LIBCPP_INLINE_VISIBILITY static constexpr
36281ad6265SDimitry Andric     const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
36381ad6265SDimitry Andric 
364*bdd1243dSDimitry Andric     static _LIBCPP_CONSTEXPR_SINCE_CXX20
36581ad6265SDimitry Andric     char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
36681ad6265SDimitry Andric         return std::__char_traits_move(__s1, __s2, __n);
36781ad6265SDimitry Andric     }
36881ad6265SDimitry Andric 
369*bdd1243dSDimitry Andric     static _LIBCPP_CONSTEXPR_SINCE_CXX20
37081ad6265SDimitry Andric     char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
37181ad6265SDimitry Andric         if (!__libcpp_is_constant_evaluated())
37281ad6265SDimitry Andric             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
37381ad6265SDimitry Andric         std::copy_n(__s2, __n, __s1);
37481ad6265SDimitry Andric         return __s1;
37581ad6265SDimitry Andric     }
37681ad6265SDimitry Andric 
377*bdd1243dSDimitry Andric     static _LIBCPP_CONSTEXPR_SINCE_CXX20
37881ad6265SDimitry Andric     char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
37981ad6265SDimitry Andric         std::fill_n(__s, __n, __a);
38081ad6265SDimitry Andric         return __s;
38181ad6265SDimitry Andric     }
38281ad6265SDimitry Andric 
38381ad6265SDimitry Andric     static inline constexpr int_type  not_eof(int_type __c) noexcept
38481ad6265SDimitry Andric         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
38581ad6265SDimitry Andric     static inline constexpr char_type to_char_type(int_type __c) noexcept
38681ad6265SDimitry Andric         {return char_type(__c);}
38781ad6265SDimitry Andric     static inline constexpr int_type to_int_type(char_type __c) noexcept
38881ad6265SDimitry Andric         {return int_type(__c);}
38981ad6265SDimitry Andric     static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
39081ad6265SDimitry Andric         {return __c1 == __c2;}
39181ad6265SDimitry Andric     static inline constexpr int_type eof() noexcept
39281ad6265SDimitry Andric         {return int_type(EOF);}
39381ad6265SDimitry Andric };
39481ad6265SDimitry Andric 
39581ad6265SDimitry Andric // TODO use '__builtin_strlen' if it ever supports char8_t ??
39681ad6265SDimitry Andric inline constexpr
39781ad6265SDimitry Andric size_t
39881ad6265SDimitry Andric char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
39981ad6265SDimitry Andric {
40081ad6265SDimitry Andric     size_t __len = 0;
40181ad6265SDimitry Andric     for (; !eq(*__s, char_type(0)); ++__s)
40281ad6265SDimitry Andric         ++__len;
40381ad6265SDimitry Andric     return __len;
40481ad6265SDimitry Andric }
40581ad6265SDimitry Andric 
40681ad6265SDimitry Andric // TODO use '__builtin_char_memchr' if it ever supports char8_t ??
40781ad6265SDimitry Andric inline constexpr
40881ad6265SDimitry Andric const char8_t*
40981ad6265SDimitry Andric char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
41081ad6265SDimitry Andric {
41181ad6265SDimitry Andric     for (; __n; --__n)
41281ad6265SDimitry Andric     {
41381ad6265SDimitry Andric         if (eq(*__s, __a))
41481ad6265SDimitry Andric             return __s;
41581ad6265SDimitry Andric         ++__s;
41681ad6265SDimitry Andric     }
41781ad6265SDimitry Andric     return nullptr;
41881ad6265SDimitry Andric }
41981ad6265SDimitry Andric 
42081ad6265SDimitry Andric #endif // _LIBCPP_HAS_NO_CHAR8_T
42181ad6265SDimitry Andric 
42281ad6265SDimitry Andric template <>
42381ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
42481ad6265SDimitry Andric {
425*bdd1243dSDimitry Andric     using char_type           = char16_t;
426*bdd1243dSDimitry Andric     using int_type            = uint_least16_t;
427*bdd1243dSDimitry Andric     using off_type            = streamoff;
428*bdd1243dSDimitry Andric     using pos_type            = u16streampos;
429*bdd1243dSDimitry Andric     using state_type          = mbstate_t;
430*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17
431*bdd1243dSDimitry Andric     using comparison_category = strong_ordering;
432*bdd1243dSDimitry Andric #endif
43381ad6265SDimitry Andric 
434*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
43581ad6265SDimitry Andric     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
43681ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
43781ad6265SDimitry Andric         {return __c1 == __c2;}
43881ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
43981ad6265SDimitry Andric         {return __c1 < __c2;}
44081ad6265SDimitry Andric 
441*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
44281ad6265SDimitry Andric     int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
443*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
44481ad6265SDimitry Andric     size_t           length(const char_type* __s) _NOEXCEPT;
445*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
44681ad6265SDimitry Andric     const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
44781ad6265SDimitry Andric 
448*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
44981ad6265SDimitry Andric     static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
45081ad6265SDimitry Andric         return std::__char_traits_move(__s1, __s2, __n);
45181ad6265SDimitry Andric     }
45281ad6265SDimitry Andric 
453*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
45481ad6265SDimitry Andric     static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
45581ad6265SDimitry Andric         if (!__libcpp_is_constant_evaluated())
45681ad6265SDimitry Andric             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
45781ad6265SDimitry Andric         std::copy_n(__s2, __n, __s1);
45881ad6265SDimitry Andric         return __s1;
45981ad6265SDimitry Andric     }
46081ad6265SDimitry Andric 
461*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
46281ad6265SDimitry Andric     static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
46381ad6265SDimitry Andric         std::fill_n(__s, __n, __a);
46481ad6265SDimitry Andric         return __s;
46581ad6265SDimitry Andric     }
46681ad6265SDimitry Andric 
46781ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
46881ad6265SDimitry Andric         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
46981ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
47081ad6265SDimitry Andric         {return char_type(__c);}
47181ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
47281ad6265SDimitry Andric         {return int_type(__c);}
47381ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
47481ad6265SDimitry Andric         {return __c1 == __c2;}
47581ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
47681ad6265SDimitry Andric         {return int_type(0xFFFF);}
47781ad6265SDimitry Andric };
47881ad6265SDimitry Andric 
479*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17
48081ad6265SDimitry Andric int
48181ad6265SDimitry Andric char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
48281ad6265SDimitry Andric {
48381ad6265SDimitry Andric     for (; __n; --__n, ++__s1, ++__s2)
48481ad6265SDimitry Andric     {
48581ad6265SDimitry Andric         if (lt(*__s1, *__s2))
48681ad6265SDimitry Andric             return -1;
48781ad6265SDimitry Andric         if (lt(*__s2, *__s1))
48881ad6265SDimitry Andric             return 1;
48981ad6265SDimitry Andric     }
49081ad6265SDimitry Andric     return 0;
49181ad6265SDimitry Andric }
49281ad6265SDimitry Andric 
493*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17
49481ad6265SDimitry Andric size_t
49581ad6265SDimitry Andric char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT
49681ad6265SDimitry Andric {
49781ad6265SDimitry Andric     size_t __len = 0;
49881ad6265SDimitry Andric     for (; !eq(*__s, char_type(0)); ++__s)
49981ad6265SDimitry Andric         ++__len;
50081ad6265SDimitry Andric     return __len;
50181ad6265SDimitry Andric }
50281ad6265SDimitry Andric 
503*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17
50481ad6265SDimitry Andric const char16_t*
50581ad6265SDimitry Andric char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
50681ad6265SDimitry Andric {
50781ad6265SDimitry Andric     for (; __n; --__n)
50881ad6265SDimitry Andric     {
50981ad6265SDimitry Andric         if (eq(*__s, __a))
51081ad6265SDimitry Andric             return __s;
51181ad6265SDimitry Andric         ++__s;
51281ad6265SDimitry Andric     }
51381ad6265SDimitry Andric     return nullptr;
51481ad6265SDimitry Andric }
51581ad6265SDimitry Andric 
51681ad6265SDimitry Andric template <>
51781ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
51881ad6265SDimitry Andric {
519*bdd1243dSDimitry Andric     using char_type           = char32_t;
520*bdd1243dSDimitry Andric     using int_type            = uint_least32_t;
521*bdd1243dSDimitry Andric     using off_type            = streamoff;
522*bdd1243dSDimitry Andric     using pos_type            = u32streampos;
523*bdd1243dSDimitry Andric     using state_type          = mbstate_t;
524*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17
525*bdd1243dSDimitry Andric     using comparison_category = strong_ordering;
526*bdd1243dSDimitry Andric #endif
52781ad6265SDimitry Andric 
528*bdd1243dSDimitry Andric     static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
52981ad6265SDimitry Andric     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
53081ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
53181ad6265SDimitry Andric         {return __c1 == __c2;}
53281ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
53381ad6265SDimitry Andric         {return __c1 < __c2;}
53481ad6265SDimitry Andric 
535*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
53681ad6265SDimitry Andric     int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
537*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
53881ad6265SDimitry Andric     size_t           length(const char_type* __s) _NOEXCEPT;
539*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
54081ad6265SDimitry Andric     const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
54181ad6265SDimitry Andric 
542*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
54381ad6265SDimitry Andric     static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
54481ad6265SDimitry Andric         return std::__char_traits_move(__s1, __s2, __n);
54581ad6265SDimitry Andric     }
54681ad6265SDimitry Andric 
547*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
54881ad6265SDimitry Andric     static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
54981ad6265SDimitry Andric         std::copy_n(__s2, __n, __s1);
55081ad6265SDimitry Andric         return __s1;
55181ad6265SDimitry Andric     }
55281ad6265SDimitry Andric 
553*bdd1243dSDimitry Andric     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
55481ad6265SDimitry Andric     static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
55581ad6265SDimitry Andric         std::fill_n(__s, __n, __a);
55681ad6265SDimitry Andric         return __s;
55781ad6265SDimitry Andric     }
55881ad6265SDimitry Andric 
55981ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
56081ad6265SDimitry Andric         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
56181ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
56281ad6265SDimitry Andric         {return char_type(__c);}
56381ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
56481ad6265SDimitry Andric         {return int_type(__c);}
56581ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
56681ad6265SDimitry Andric         {return __c1 == __c2;}
56781ad6265SDimitry Andric     static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
56881ad6265SDimitry Andric         {return int_type(0xFFFFFFFF);}
56981ad6265SDimitry Andric };
57081ad6265SDimitry Andric 
571*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17
57281ad6265SDimitry Andric int
57381ad6265SDimitry Andric char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
57481ad6265SDimitry Andric {
57581ad6265SDimitry Andric     for (; __n; --__n, ++__s1, ++__s2)
57681ad6265SDimitry Andric     {
57781ad6265SDimitry Andric         if (lt(*__s1, *__s2))
57881ad6265SDimitry Andric             return -1;
57981ad6265SDimitry Andric         if (lt(*__s2, *__s1))
58081ad6265SDimitry Andric             return 1;
58181ad6265SDimitry Andric     }
58281ad6265SDimitry Andric     return 0;
58381ad6265SDimitry Andric }
58481ad6265SDimitry Andric 
585*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17
58681ad6265SDimitry Andric size_t
58781ad6265SDimitry Andric char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT
58881ad6265SDimitry Andric {
58981ad6265SDimitry Andric     size_t __len = 0;
59081ad6265SDimitry Andric     for (; !eq(*__s, char_type(0)); ++__s)
59181ad6265SDimitry Andric         ++__len;
59281ad6265SDimitry Andric     return __len;
59381ad6265SDimitry Andric }
59481ad6265SDimitry Andric 
595*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17
59681ad6265SDimitry Andric const char32_t*
59781ad6265SDimitry Andric char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
59881ad6265SDimitry Andric {
59981ad6265SDimitry Andric     for (; __n; --__n)
60081ad6265SDimitry Andric     {
60181ad6265SDimitry Andric         if (eq(*__s, __a))
60281ad6265SDimitry Andric             return __s;
60381ad6265SDimitry Andric         ++__s;
60481ad6265SDimitry Andric     }
60581ad6265SDimitry Andric     return nullptr;
60681ad6265SDimitry Andric }
60781ad6265SDimitry Andric 
60881ad6265SDimitry Andric // helper fns for basic_string and string_view
60981ad6265SDimitry Andric 
61081ad6265SDimitry Andric // __str_find
61181ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
612*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
61381ad6265SDimitry Andric __str_find(const _CharT *__p, _SizeT __sz,
61481ad6265SDimitry Andric              _CharT __c, _SizeT __pos) _NOEXCEPT
61581ad6265SDimitry Andric {
61681ad6265SDimitry Andric     if (__pos >= __sz)
61781ad6265SDimitry Andric         return __npos;
61881ad6265SDimitry Andric     const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
61981ad6265SDimitry Andric     if (__r == nullptr)
62081ad6265SDimitry Andric         return __npos;
62181ad6265SDimitry Andric     return static_cast<_SizeT>(__r - __p);
62281ad6265SDimitry Andric }
62381ad6265SDimitry Andric 
62481ad6265SDimitry Andric template <class _CharT, class _Traits>
625*bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const _CharT *
62681ad6265SDimitry Andric __search_substring(const _CharT *__first1, const _CharT *__last1,
62781ad6265SDimitry Andric                    const _CharT *__first2, const _CharT *__last2) _NOEXCEPT {
62881ad6265SDimitry Andric   // Take advantage of knowing source and pattern lengths.
62981ad6265SDimitry Andric   // Stop short when source is smaller than pattern.
63081ad6265SDimitry Andric   const ptrdiff_t __len2 = __last2 - __first2;
63181ad6265SDimitry Andric   if (__len2 == 0)
63281ad6265SDimitry Andric     return __first1;
63381ad6265SDimitry Andric 
63481ad6265SDimitry Andric   ptrdiff_t __len1 = __last1 - __first1;
63581ad6265SDimitry Andric   if (__len1 < __len2)
63681ad6265SDimitry Andric     return __last1;
63781ad6265SDimitry Andric 
63881ad6265SDimitry Andric   // First element of __first2 is loop invariant.
63981ad6265SDimitry Andric   _CharT __f2 = *__first2;
64081ad6265SDimitry Andric   while (true) {
64181ad6265SDimitry Andric     __len1 = __last1 - __first1;
64281ad6265SDimitry Andric     // Check whether __first1 still has at least __len2 bytes.
64381ad6265SDimitry Andric     if (__len1 < __len2)
64481ad6265SDimitry Andric       return __last1;
64581ad6265SDimitry Andric 
64681ad6265SDimitry Andric     // Find __f2 the first byte matching in __first1.
64781ad6265SDimitry Andric     __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
64881ad6265SDimitry Andric     if (__first1 == nullptr)
64981ad6265SDimitry Andric       return __last1;
65081ad6265SDimitry Andric 
65181ad6265SDimitry Andric     // It is faster to compare from the first byte of __first1 even if we
65281ad6265SDimitry Andric     // already know that it matches the first byte of __first2: this is because
65381ad6265SDimitry Andric     // __first2 is most likely aligned, as it is user's "pattern" string, and
65481ad6265SDimitry Andric     // __first1 + 1 is most likely not aligned, as the match is in the middle of
65581ad6265SDimitry Andric     // the string.
65681ad6265SDimitry Andric     if (_Traits::compare(__first1, __first2, __len2) == 0)
65781ad6265SDimitry Andric       return __first1;
65881ad6265SDimitry Andric 
65981ad6265SDimitry Andric     ++__first1;
66081ad6265SDimitry Andric   }
66181ad6265SDimitry Andric }
66281ad6265SDimitry Andric 
66381ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
664*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
66581ad6265SDimitry Andric __str_find(const _CharT *__p, _SizeT __sz,
66681ad6265SDimitry Andric        const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
66781ad6265SDimitry Andric {
66881ad6265SDimitry Andric     if (__pos > __sz)
66981ad6265SDimitry Andric         return __npos;
67081ad6265SDimitry Andric 
67181ad6265SDimitry Andric     if (__n == 0) // There is nothing to search, just return __pos.
67281ad6265SDimitry Andric         return __pos;
67381ad6265SDimitry Andric 
674*bdd1243dSDimitry Andric     const _CharT *__r = std::__search_substring<_CharT, _Traits>(
67581ad6265SDimitry Andric         __p + __pos, __p + __sz, __s, __s + __n);
67681ad6265SDimitry Andric 
67781ad6265SDimitry Andric     if (__r == __p + __sz)
67881ad6265SDimitry Andric         return __npos;
67981ad6265SDimitry Andric     return static_cast<_SizeT>(__r - __p);
68081ad6265SDimitry Andric }
68181ad6265SDimitry Andric 
68281ad6265SDimitry Andric 
68381ad6265SDimitry Andric // __str_rfind
68481ad6265SDimitry Andric 
68581ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
686*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
68781ad6265SDimitry Andric __str_rfind(const _CharT *__p, _SizeT __sz,
68881ad6265SDimitry Andric               _CharT __c, _SizeT __pos) _NOEXCEPT
68981ad6265SDimitry Andric {
69081ad6265SDimitry Andric     if (__sz < 1)
69181ad6265SDimitry Andric         return __npos;
69281ad6265SDimitry Andric     if (__pos < __sz)
69381ad6265SDimitry Andric         ++__pos;
69481ad6265SDimitry Andric     else
69581ad6265SDimitry Andric         __pos = __sz;
69681ad6265SDimitry Andric     for (const _CharT* __ps = __p + __pos; __ps != __p;)
69781ad6265SDimitry Andric     {
69881ad6265SDimitry Andric         if (_Traits::eq(*--__ps, __c))
69981ad6265SDimitry Andric             return static_cast<_SizeT>(__ps - __p);
70081ad6265SDimitry Andric     }
70181ad6265SDimitry Andric     return __npos;
70281ad6265SDimitry Andric }
70381ad6265SDimitry Andric 
70481ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
705*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
70681ad6265SDimitry Andric __str_rfind(const _CharT *__p, _SizeT __sz,
70781ad6265SDimitry Andric         const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
70881ad6265SDimitry Andric {
70981ad6265SDimitry Andric     __pos = _VSTD::min(__pos, __sz);
71081ad6265SDimitry Andric     if (__n < __sz - __pos)
71181ad6265SDimitry Andric         __pos += __n;
71281ad6265SDimitry Andric     else
71381ad6265SDimitry Andric         __pos = __sz;
714753f127fSDimitry Andric     const _CharT* __r = std::__find_end_classic(__p, __p + __pos, __s, __s + __n, _Traits::eq);
71581ad6265SDimitry Andric     if (__n > 0 && __r == __p + __pos)
71681ad6265SDimitry Andric         return __npos;
71781ad6265SDimitry Andric     return static_cast<_SizeT>(__r - __p);
71881ad6265SDimitry Andric }
71981ad6265SDimitry Andric 
72081ad6265SDimitry Andric // __str_find_first_of
72181ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
722*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
72381ad6265SDimitry Andric __str_find_first_of(const _CharT *__p, _SizeT __sz,
72481ad6265SDimitry Andric                 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
72581ad6265SDimitry Andric {
72681ad6265SDimitry Andric     if (__pos >= __sz || __n == 0)
72781ad6265SDimitry Andric         return __npos;
72881ad6265SDimitry Andric     const _CharT* __r = _VSTD::__find_first_of_ce
72981ad6265SDimitry Andric         (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
73081ad6265SDimitry Andric     if (__r == __p + __sz)
73181ad6265SDimitry Andric         return __npos;
73281ad6265SDimitry Andric     return static_cast<_SizeT>(__r - __p);
73381ad6265SDimitry Andric }
73481ad6265SDimitry Andric 
73581ad6265SDimitry Andric 
73681ad6265SDimitry Andric // __str_find_last_of
73781ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
738*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
73981ad6265SDimitry Andric __str_find_last_of(const _CharT *__p, _SizeT __sz,
74081ad6265SDimitry Andric                const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
74181ad6265SDimitry Andric     {
74281ad6265SDimitry Andric     if (__n != 0)
74381ad6265SDimitry Andric     {
74481ad6265SDimitry Andric         if (__pos < __sz)
74581ad6265SDimitry Andric             ++__pos;
74681ad6265SDimitry Andric         else
74781ad6265SDimitry Andric             __pos = __sz;
74881ad6265SDimitry Andric         for (const _CharT* __ps = __p + __pos; __ps != __p;)
74981ad6265SDimitry Andric         {
75081ad6265SDimitry Andric             const _CharT* __r = _Traits::find(__s, __n, *--__ps);
75181ad6265SDimitry Andric             if (__r)
75281ad6265SDimitry Andric                 return static_cast<_SizeT>(__ps - __p);
75381ad6265SDimitry Andric         }
75481ad6265SDimitry Andric     }
75581ad6265SDimitry Andric     return __npos;
75681ad6265SDimitry Andric }
75781ad6265SDimitry Andric 
75881ad6265SDimitry Andric 
75981ad6265SDimitry Andric // __str_find_first_not_of
76081ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
761*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
76281ad6265SDimitry Andric __str_find_first_not_of(const _CharT *__p, _SizeT __sz,
76381ad6265SDimitry Andric                     const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
76481ad6265SDimitry Andric {
76581ad6265SDimitry Andric     if (__pos < __sz)
76681ad6265SDimitry Andric     {
76781ad6265SDimitry Andric         const _CharT* __pe = __p + __sz;
76881ad6265SDimitry Andric         for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
76981ad6265SDimitry Andric             if (_Traits::find(__s, __n, *__ps) == nullptr)
77081ad6265SDimitry Andric                 return static_cast<_SizeT>(__ps - __p);
77181ad6265SDimitry Andric     }
77281ad6265SDimitry Andric     return __npos;
77381ad6265SDimitry Andric }
77481ad6265SDimitry Andric 
77581ad6265SDimitry Andric 
77681ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
777*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
77881ad6265SDimitry Andric __str_find_first_not_of(const _CharT *__p, _SizeT __sz,
77981ad6265SDimitry Andric                           _CharT __c, _SizeT __pos) _NOEXCEPT
78081ad6265SDimitry Andric {
78181ad6265SDimitry Andric     if (__pos < __sz)
78281ad6265SDimitry Andric     {
78381ad6265SDimitry Andric         const _CharT* __pe = __p + __sz;
78481ad6265SDimitry Andric         for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
78581ad6265SDimitry Andric             if (!_Traits::eq(*__ps, __c))
78681ad6265SDimitry Andric                 return static_cast<_SizeT>(__ps - __p);
78781ad6265SDimitry Andric     }
78881ad6265SDimitry Andric     return __npos;
78981ad6265SDimitry Andric }
79081ad6265SDimitry Andric 
79181ad6265SDimitry Andric 
79281ad6265SDimitry Andric // __str_find_last_not_of
79381ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
794*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
79581ad6265SDimitry Andric __str_find_last_not_of(const _CharT *__p, _SizeT __sz,
79681ad6265SDimitry Andric                    const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
79781ad6265SDimitry Andric {
79881ad6265SDimitry Andric     if (__pos < __sz)
79981ad6265SDimitry Andric         ++__pos;
80081ad6265SDimitry Andric     else
80181ad6265SDimitry Andric         __pos = __sz;
80281ad6265SDimitry Andric     for (const _CharT* __ps = __p + __pos; __ps != __p;)
80381ad6265SDimitry Andric         if (_Traits::find(__s, __n, *--__ps) == nullptr)
80481ad6265SDimitry Andric             return static_cast<_SizeT>(__ps - __p);
80581ad6265SDimitry Andric     return __npos;
80681ad6265SDimitry Andric }
80781ad6265SDimitry Andric 
80881ad6265SDimitry Andric 
80981ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
810*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
81181ad6265SDimitry Andric __str_find_last_not_of(const _CharT *__p, _SizeT __sz,
81281ad6265SDimitry Andric                          _CharT __c, _SizeT __pos) _NOEXCEPT
81381ad6265SDimitry Andric {
81481ad6265SDimitry Andric     if (__pos < __sz)
81581ad6265SDimitry Andric         ++__pos;
81681ad6265SDimitry Andric     else
81781ad6265SDimitry Andric         __pos = __sz;
81881ad6265SDimitry Andric     for (const _CharT* __ps = __p + __pos; __ps != __p;)
81981ad6265SDimitry Andric         if (!_Traits::eq(*--__ps, __c))
82081ad6265SDimitry Andric             return static_cast<_SizeT>(__ps - __p);
82181ad6265SDimitry Andric     return __npos;
82281ad6265SDimitry Andric }
82381ad6265SDimitry Andric 
82481ad6265SDimitry Andric template<class _Ptr>
82581ad6265SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
82681ad6265SDimitry Andric size_t __do_string_hash(_Ptr __p, _Ptr __e)
82781ad6265SDimitry Andric {
82881ad6265SDimitry Andric     typedef typename iterator_traits<_Ptr>::value_type value_type;
82981ad6265SDimitry Andric     return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
83081ad6265SDimitry Andric }
83181ad6265SDimitry Andric 
83281ad6265SDimitry Andric _LIBCPP_END_NAMESPACE_STD
83381ad6265SDimitry Andric 
83481ad6265SDimitry Andric _LIBCPP_POP_MACROS
83581ad6265SDimitry Andric 
83681ad6265SDimitry Andric #endif // _LIBCPP___STRING_CHAR_TRAITS_H
837