xref: /openbsd-src/gnu/llvm/libcxx/include/__string.d/__string/char_traits.h (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
1*4bdff4beSrobert //===----------------------------------------------------------------------===//
2*4bdff4beSrobert //
3*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information.
5*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4bdff4beSrobert //
7*4bdff4beSrobert //===----------------------------------------------------------------------===//
8*4bdff4beSrobert 
9*4bdff4beSrobert #ifndef _LIBCPP___STRING_CHAR_TRAITS_H
10*4bdff4beSrobert #define _LIBCPP___STRING_CHAR_TRAITS_H
11*4bdff4beSrobert 
12*4bdff4beSrobert #include <__algorithm/copy_n.h>
13*4bdff4beSrobert #include <__algorithm/fill_n.h>
14*4bdff4beSrobert #include <__algorithm/find_end.h>
15*4bdff4beSrobert #include <__algorithm/find_first_of.h>
16*4bdff4beSrobert #include <__algorithm/min.h>
17*4bdff4beSrobert #include <__compare/ordering.h>
18*4bdff4beSrobert #include <__config>
19*4bdff4beSrobert #include <__functional/hash.h>
20*4bdff4beSrobert #include <__iterator/iterator_traits.h>
21*4bdff4beSrobert #include <__type_traits/is_constant_evaluated.h>
22*4bdff4beSrobert #include <cstddef>
23*4bdff4beSrobert #include <cstdint>
24*4bdff4beSrobert #include <cstdio>
25*4bdff4beSrobert #include <cstring>
26*4bdff4beSrobert #include <iosfwd>
27*4bdff4beSrobert 
28*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
29*4bdff4beSrobert #   include <cwchar> // for wmemcpy
30*4bdff4beSrobert #endif
31*4bdff4beSrobert 
32*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
33*4bdff4beSrobert #  pragma GCC system_header
34*4bdff4beSrobert #endif
35*4bdff4beSrobert 
36*4bdff4beSrobert _LIBCPP_PUSH_MACROS
37*4bdff4beSrobert #include <__undef_macros>
38*4bdff4beSrobert 
39*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
40*4bdff4beSrobert 
41*4bdff4beSrobert template <class _CharT>
42*4bdff4beSrobert struct char_traits;
43*4bdff4beSrobert /*
44*4bdff4beSrobert The Standard does not define the base template for char_traits because it is impossible to provide
45*4bdff4beSrobert a correct definition for arbitrary character types. Instead, it requires implementations to provide
46*4bdff4beSrobert specializations for predefined character types like `char`, `wchar_t` and others. We provide this as
47*4bdff4beSrobert exposition-only to document what members a char_traits specialization should provide:
48*4bdff4beSrobert {
49*4bdff4beSrobert     using char_type  = _CharT;
50*4bdff4beSrobert     using int_type   = ...;
51*4bdff4beSrobert     using off_type   = ...;
52*4bdff4beSrobert     using pos_type   = ...;
53*4bdff4beSrobert     using state_type = ...;
54*4bdff4beSrobert 
55*4bdff4beSrobert     static void assign(char_type&, const char_type&);
56*4bdff4beSrobert     static bool eq(char_type, char_type);
57*4bdff4beSrobert     static bool lt(char_type, char_type);
58*4bdff4beSrobert 
59*4bdff4beSrobert     static int              compare(const char_type*, const char_type*, size_t);
60*4bdff4beSrobert     static size_t           length(const char_type*);
61*4bdff4beSrobert     static const char_type* find(const char_type*, size_t, const char_type&);
62*4bdff4beSrobert     static char_type*       move(char_type*, const char_type*, size_t);
63*4bdff4beSrobert     static char_type*       copy(char_type*, const char_type*, size_t);
64*4bdff4beSrobert     static char_type*       assign(char_type*, size_t, char_type);
65*4bdff4beSrobert 
66*4bdff4beSrobert     static int_type  not_eof(int_type);
67*4bdff4beSrobert     static char_type to_char_type(int_type);
68*4bdff4beSrobert     static int_type  to_int_type(char_type);
69*4bdff4beSrobert     static bool      eq_int_type(int_type, int_type);
70*4bdff4beSrobert     static int_type  eof();
71*4bdff4beSrobert };
72*4bdff4beSrobert */
73*4bdff4beSrobert 
74*4bdff4beSrobert //
75*4bdff4beSrobert // Temporary extension to provide a base template for std::char_traits.
76*4bdff4beSrobert // TODO: Remove in LLVM 18.
77*4bdff4beSrobert //
78*4bdff4beSrobert template <class _CharT>
79*4bdff4beSrobert 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*4bdff4beSrobert     char_traits
81*4bdff4beSrobert {
82*4bdff4beSrobert     using char_type  = _CharT;
83*4bdff4beSrobert     using int_type   = int;
84*4bdff4beSrobert     using off_type   = streamoff;
85*4bdff4beSrobert     using pos_type   = streampos;
86*4bdff4beSrobert     using state_type = mbstate_t;
87*4bdff4beSrobert 
88*4bdff4beSrobert     static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17
assignchar_traits89*4bdff4beSrobert         assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
eqchar_traits90*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
91*4bdff4beSrobert         {return __c1 == __c2;}
ltchar_traits92*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
93*4bdff4beSrobert         {return __c1 < __c2;}
94*4bdff4beSrobert 
95*4bdff4beSrobert     static _LIBCPP_CONSTEXPR_SINCE_CXX17
comparechar_traits96*4bdff4beSrobert     int compare(const char_type* __s1, const char_type* __s2, size_t __n) {
97*4bdff4beSrobert         for (; __n; --__n, ++__s1, ++__s2)
98*4bdff4beSrobert         {
99*4bdff4beSrobert             if (lt(*__s1, *__s2))
100*4bdff4beSrobert                 return -1;
101*4bdff4beSrobert             if (lt(*__s2, *__s1))
102*4bdff4beSrobert                 return 1;
103*4bdff4beSrobert         }
104*4bdff4beSrobert         return 0;
105*4bdff4beSrobert     }
106*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
lengthchar_traits107*4bdff4beSrobert     size_t length(const char_type* __s) {
108*4bdff4beSrobert         size_t __len = 0;
109*4bdff4beSrobert         for (; !eq(*__s, char_type(0)); ++__s)
110*4bdff4beSrobert             ++__len;
111*4bdff4beSrobert         return __len;
112*4bdff4beSrobert     }
113*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
findchar_traits114*4bdff4beSrobert     const char_type* find(const char_type* __s, size_t __n, const char_type& __a) {
115*4bdff4beSrobert         for (; __n; --__n)
116*4bdff4beSrobert         {
117*4bdff4beSrobert             if (eq(*__s, __a))
118*4bdff4beSrobert                 return __s;
119*4bdff4beSrobert             ++__s;
120*4bdff4beSrobert         }
121*4bdff4beSrobert         return nullptr;
122*4bdff4beSrobert     }
123*4bdff4beSrobert     static _LIBCPP_CONSTEXPR_SINCE_CXX20
movechar_traits124*4bdff4beSrobert     char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) {
125*4bdff4beSrobert         if (__n == 0) return __s1;
126*4bdff4beSrobert         char_type* __r = __s1;
127*4bdff4beSrobert         if (__s1 < __s2)
128*4bdff4beSrobert         {
129*4bdff4beSrobert             for (; __n; --__n, ++__s1, ++__s2)
130*4bdff4beSrobert                 assign(*__s1, *__s2);
131*4bdff4beSrobert         }
132*4bdff4beSrobert         else if (__s2 < __s1)
133*4bdff4beSrobert         {
134*4bdff4beSrobert             __s1 += __n;
135*4bdff4beSrobert             __s2 += __n;
136*4bdff4beSrobert             for (; __n; --__n)
137*4bdff4beSrobert                 assign(*--__s1, *--__s2);
138*4bdff4beSrobert         }
139*4bdff4beSrobert         return __r;
140*4bdff4beSrobert     }
141*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY
142*4bdff4beSrobert     static _LIBCPP_CONSTEXPR_SINCE_CXX20
copychar_traits143*4bdff4beSrobert     char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) {
144*4bdff4beSrobert         if (!__libcpp_is_constant_evaluated()) {
145*4bdff4beSrobert             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
146*4bdff4beSrobert         }
147*4bdff4beSrobert         char_type* __r = __s1;
148*4bdff4beSrobert         for (; __n; --__n, ++__s1, ++__s2)
149*4bdff4beSrobert             assign(*__s1, *__s2);
150*4bdff4beSrobert         return __r;
151*4bdff4beSrobert     }
152*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY
153*4bdff4beSrobert     static _LIBCPP_CONSTEXPR_SINCE_CXX20
assignchar_traits154*4bdff4beSrobert     char_type*       assign(char_type* __s, size_t __n, char_type __a) {
155*4bdff4beSrobert         char_type* __r = __s;
156*4bdff4beSrobert         for (; __n; --__n, ++__s)
157*4bdff4beSrobert             assign(*__s, __a);
158*4bdff4beSrobert         return __r;
159*4bdff4beSrobert     }
160*4bdff4beSrobert 
not_eofchar_traits161*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
162*4bdff4beSrobert         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
to_char_typechar_traits163*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
164*4bdff4beSrobert         {return char_type(__c);}
to_int_typechar_traits165*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type  to_int_type(char_type __c) _NOEXCEPT
166*4bdff4beSrobert         {return int_type(__c);}
eq_int_typechar_traits167*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool      eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
168*4bdff4beSrobert         {return __c1 == __c2;}
eofchar_traits169*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
170*4bdff4beSrobert         {return int_type(EOF);}
171*4bdff4beSrobert };
172*4bdff4beSrobert 
173*4bdff4beSrobert template <class _CharT>
174*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
__char_traits_move(_CharT * __dest,const _CharT * __source,size_t __n)175*4bdff4beSrobert _CharT* __char_traits_move(_CharT* __dest, const _CharT* __source, size_t __n) _NOEXCEPT
176*4bdff4beSrobert {
177*4bdff4beSrobert #ifdef _LIBCPP_COMPILER_GCC
178*4bdff4beSrobert   if (__libcpp_is_constant_evaluated()) {
179*4bdff4beSrobert     if (__n == 0)
180*4bdff4beSrobert       return __dest;
181*4bdff4beSrobert     _CharT* __allocation = new _CharT[__n];
182*4bdff4beSrobert     std::copy_n(__source, __n, __allocation);
183*4bdff4beSrobert     std::copy_n(static_cast<const _CharT*>(__allocation), __n, __dest);
184*4bdff4beSrobert     delete[] __allocation;
185*4bdff4beSrobert     return __dest;
186*4bdff4beSrobert   }
187*4bdff4beSrobert #endif
188*4bdff4beSrobert   ::__builtin_memmove(__dest, __source, __n * sizeof(_CharT));
189*4bdff4beSrobert   return __dest;
190*4bdff4beSrobert }
191*4bdff4beSrobert 
192*4bdff4beSrobert // char_traits<char>
193*4bdff4beSrobert 
194*4bdff4beSrobert template <>
195*4bdff4beSrobert struct _LIBCPP_TEMPLATE_VIS char_traits<char>
196*4bdff4beSrobert {
197*4bdff4beSrobert     using char_type           = char;
198*4bdff4beSrobert     using int_type            = int;
199*4bdff4beSrobert     using off_type            = streamoff;
200*4bdff4beSrobert     using pos_type            = streampos;
201*4bdff4beSrobert     using state_type          = mbstate_t;
202*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
203*4bdff4beSrobert     using comparison_category = strong_ordering;
204*4bdff4beSrobert #endif
205*4bdff4beSrobert 
206*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
207*4bdff4beSrobert     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
208*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
209*4bdff4beSrobert             {return __c1 == __c2;}
210*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
211*4bdff4beSrobert         {return (unsigned char)__c1 < (unsigned char)__c2;}
212*4bdff4beSrobert 
213*4bdff4beSrobert   static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
214*4bdff4beSrobert     if (__n == 0)
215*4bdff4beSrobert       return 0;
216*4bdff4beSrobert     return std::__constexpr_memcmp(__s1, __s2, __n);
217*4bdff4beSrobert   }
218*4bdff4beSrobert 
219*4bdff4beSrobert   static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s)  _NOEXCEPT {
220*4bdff4beSrobert     return std::__constexpr_strlen(__s);
221*4bdff4beSrobert   }
222*4bdff4beSrobert 
223*4bdff4beSrobert   static _LIBCPP_CONSTEXPR_SINCE_CXX17
224*4bdff4beSrobert   const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
225*4bdff4beSrobert     if (__n == 0)
226*4bdff4beSrobert         return nullptr;
227*4bdff4beSrobert     return std::__constexpr_char_memchr(__s, static_cast<int>(__a), __n);
228*4bdff4beSrobert   }
229*4bdff4beSrobert 
230*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
231*4bdff4beSrobert     char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
232*4bdff4beSrobert         return std::__char_traits_move(__s1, __s2, __n);
233*4bdff4beSrobert     }
234*4bdff4beSrobert 
235*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
236*4bdff4beSrobert     char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
237*4bdff4beSrobert         if (!__libcpp_is_constant_evaluated())
238*4bdff4beSrobert             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
239*4bdff4beSrobert         std::copy_n(__s2, __n, __s1);
240*4bdff4beSrobert         return __s1;
241*4bdff4beSrobert     }
242*4bdff4beSrobert 
243*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
244*4bdff4beSrobert     char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
245*4bdff4beSrobert         std::fill_n(__s, __n, __a);
246*4bdff4beSrobert         return __s;
247*4bdff4beSrobert     }
248*4bdff4beSrobert 
249*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
250*4bdff4beSrobert         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
251*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
252*4bdff4beSrobert         {return char_type(__c);}
253*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
254*4bdff4beSrobert         {return int_type((unsigned char)__c);}
255*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
256*4bdff4beSrobert         {return __c1 == __c2;}
257*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
258*4bdff4beSrobert         {return int_type(EOF);}
259*4bdff4beSrobert };
260*4bdff4beSrobert 
261*4bdff4beSrobert // char_traits<wchar_t>
262*4bdff4beSrobert 
263*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
264*4bdff4beSrobert template <>
265*4bdff4beSrobert struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
266*4bdff4beSrobert {
267*4bdff4beSrobert     using char_type           = wchar_t;
268*4bdff4beSrobert     using int_type            = wint_t;
269*4bdff4beSrobert     using off_type            = streamoff;
270*4bdff4beSrobert     using pos_type            = streampos;
271*4bdff4beSrobert     using state_type          = mbstate_t;
272*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
273*4bdff4beSrobert     using comparison_category = strong_ordering;
274*4bdff4beSrobert #endif
275*4bdff4beSrobert 
276*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
277*4bdff4beSrobert     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
278*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
279*4bdff4beSrobert         {return __c1 == __c2;}
280*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
281*4bdff4beSrobert         {return __c1 < __c2;}
282*4bdff4beSrobert 
283*4bdff4beSrobert   static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
284*4bdff4beSrobert     if (__n == 0)
285*4bdff4beSrobert         return 0;
286*4bdff4beSrobert     return std::__constexpr_wmemcmp(__s1, __s2, __n);
287*4bdff4beSrobert   }
288*4bdff4beSrobert 
289*4bdff4beSrobert   static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT {
290*4bdff4beSrobert     return std::__constexpr_wcslen(__s);
291*4bdff4beSrobert   }
292*4bdff4beSrobert 
293*4bdff4beSrobert   static _LIBCPP_CONSTEXPR_SINCE_CXX17
294*4bdff4beSrobert   const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
295*4bdff4beSrobert     if (__n == 0)
296*4bdff4beSrobert         return nullptr;
297*4bdff4beSrobert     return std::__constexpr_wmemchr(__s, __a, __n);
298*4bdff4beSrobert   }
299*4bdff4beSrobert 
300*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
301*4bdff4beSrobert     char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
302*4bdff4beSrobert         return std::__char_traits_move(__s1, __s2, __n);
303*4bdff4beSrobert     }
304*4bdff4beSrobert 
305*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
306*4bdff4beSrobert     char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
307*4bdff4beSrobert         if (!__libcpp_is_constant_evaluated())
308*4bdff4beSrobert             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
309*4bdff4beSrobert         std::copy_n(__s2, __n, __s1);
310*4bdff4beSrobert         return __s1;
311*4bdff4beSrobert     }
312*4bdff4beSrobert 
313*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
314*4bdff4beSrobert     char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
315*4bdff4beSrobert         std::fill_n(__s, __n, __a);
316*4bdff4beSrobert         return __s;
317*4bdff4beSrobert     }
318*4bdff4beSrobert 
319*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
320*4bdff4beSrobert         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
321*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
322*4bdff4beSrobert         {return char_type(__c);}
323*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
324*4bdff4beSrobert         {return int_type(__c);}
325*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
326*4bdff4beSrobert         {return __c1 == __c2;}
327*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
328*4bdff4beSrobert         {return int_type(WEOF);}
329*4bdff4beSrobert };
330*4bdff4beSrobert #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
331*4bdff4beSrobert 
332*4bdff4beSrobert #ifndef _LIBCPP_HAS_NO_CHAR8_T
333*4bdff4beSrobert 
334*4bdff4beSrobert template <>
335*4bdff4beSrobert struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
336*4bdff4beSrobert {
337*4bdff4beSrobert     using char_type           = char8_t;
338*4bdff4beSrobert     using int_type            = unsigned int;
339*4bdff4beSrobert     using off_type            = streamoff;
340*4bdff4beSrobert     using pos_type            = u8streampos;
341*4bdff4beSrobert     using state_type          = mbstate_t;
342*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
343*4bdff4beSrobert     using comparison_category = strong_ordering;
344*4bdff4beSrobert #endif
345*4bdff4beSrobert 
346*4bdff4beSrobert     static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
347*4bdff4beSrobert         {__c1 = __c2;}
348*4bdff4beSrobert     static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
349*4bdff4beSrobert         {return __c1 == __c2;}
350*4bdff4beSrobert     static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
351*4bdff4beSrobert         {return __c1 < __c2;}
352*4bdff4beSrobert 
353*4bdff4beSrobert   static _LIBCPP_HIDE_FROM_ABI constexpr int
354*4bdff4beSrobert   compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
355*4bdff4beSrobert       return std::__constexpr_memcmp(__s1, __s2, __n);
356*4bdff4beSrobert   }
357*4bdff4beSrobert 
358*4bdff4beSrobert     static constexpr
359*4bdff4beSrobert     size_t           length(const char_type* __s) _NOEXCEPT;
360*4bdff4beSrobert 
361*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY static constexpr
362*4bdff4beSrobert     const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
363*4bdff4beSrobert 
364*4bdff4beSrobert     static _LIBCPP_CONSTEXPR_SINCE_CXX20
365*4bdff4beSrobert     char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
366*4bdff4beSrobert         return std::__char_traits_move(__s1, __s2, __n);
367*4bdff4beSrobert     }
368*4bdff4beSrobert 
369*4bdff4beSrobert     static _LIBCPP_CONSTEXPR_SINCE_CXX20
370*4bdff4beSrobert     char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
371*4bdff4beSrobert         if (!__libcpp_is_constant_evaluated())
372*4bdff4beSrobert             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
373*4bdff4beSrobert         std::copy_n(__s2, __n, __s1);
374*4bdff4beSrobert         return __s1;
375*4bdff4beSrobert     }
376*4bdff4beSrobert 
377*4bdff4beSrobert     static _LIBCPP_CONSTEXPR_SINCE_CXX20
378*4bdff4beSrobert     char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
379*4bdff4beSrobert         std::fill_n(__s, __n, __a);
380*4bdff4beSrobert         return __s;
381*4bdff4beSrobert     }
382*4bdff4beSrobert 
383*4bdff4beSrobert     static inline constexpr int_type  not_eof(int_type __c) noexcept
384*4bdff4beSrobert         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
385*4bdff4beSrobert     static inline constexpr char_type to_char_type(int_type __c) noexcept
386*4bdff4beSrobert         {return char_type(__c);}
387*4bdff4beSrobert     static inline constexpr int_type to_int_type(char_type __c) noexcept
388*4bdff4beSrobert         {return int_type(__c);}
389*4bdff4beSrobert     static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
390*4bdff4beSrobert         {return __c1 == __c2;}
391*4bdff4beSrobert     static inline constexpr int_type eof() noexcept
392*4bdff4beSrobert         {return int_type(EOF);}
393*4bdff4beSrobert };
394*4bdff4beSrobert 
395*4bdff4beSrobert // TODO use '__builtin_strlen' if it ever supports char8_t ??
396*4bdff4beSrobert inline constexpr
397*4bdff4beSrobert size_t
398*4bdff4beSrobert char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
399*4bdff4beSrobert {
400*4bdff4beSrobert     size_t __len = 0;
401*4bdff4beSrobert     for (; !eq(*__s, char_type(0)); ++__s)
402*4bdff4beSrobert         ++__len;
403*4bdff4beSrobert     return __len;
404*4bdff4beSrobert }
405*4bdff4beSrobert 
406*4bdff4beSrobert // TODO use '__builtin_char_memchr' if it ever supports char8_t ??
407*4bdff4beSrobert inline constexpr
408*4bdff4beSrobert const char8_t*
409*4bdff4beSrobert char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
410*4bdff4beSrobert {
411*4bdff4beSrobert     for (; __n; --__n)
412*4bdff4beSrobert     {
413*4bdff4beSrobert         if (eq(*__s, __a))
414*4bdff4beSrobert             return __s;
415*4bdff4beSrobert         ++__s;
416*4bdff4beSrobert     }
417*4bdff4beSrobert     return nullptr;
418*4bdff4beSrobert }
419*4bdff4beSrobert 
420*4bdff4beSrobert #endif // _LIBCPP_HAS_NO_CHAR8_T
421*4bdff4beSrobert 
422*4bdff4beSrobert template <>
423*4bdff4beSrobert struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
424*4bdff4beSrobert {
425*4bdff4beSrobert     using char_type           = char16_t;
426*4bdff4beSrobert     using int_type            = uint_least16_t;
427*4bdff4beSrobert     using off_type            = streamoff;
428*4bdff4beSrobert     using pos_type            = u16streampos;
429*4bdff4beSrobert     using state_type          = mbstate_t;
430*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
431*4bdff4beSrobert     using comparison_category = strong_ordering;
432*4bdff4beSrobert #endif
433*4bdff4beSrobert 
434*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
435*4bdff4beSrobert     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
436*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
437*4bdff4beSrobert         {return __c1 == __c2;}
438*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
439*4bdff4beSrobert         {return __c1 < __c2;}
440*4bdff4beSrobert 
441*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
442*4bdff4beSrobert     int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
443*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
444*4bdff4beSrobert     size_t           length(const char_type* __s) _NOEXCEPT;
445*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
446*4bdff4beSrobert     const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
447*4bdff4beSrobert 
448*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
449*4bdff4beSrobert     static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
450*4bdff4beSrobert         return std::__char_traits_move(__s1, __s2, __n);
451*4bdff4beSrobert     }
452*4bdff4beSrobert 
453*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
454*4bdff4beSrobert     static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
455*4bdff4beSrobert         if (!__libcpp_is_constant_evaluated())
456*4bdff4beSrobert             _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
457*4bdff4beSrobert         std::copy_n(__s2, __n, __s1);
458*4bdff4beSrobert         return __s1;
459*4bdff4beSrobert     }
460*4bdff4beSrobert 
461*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
462*4bdff4beSrobert     static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
463*4bdff4beSrobert         std::fill_n(__s, __n, __a);
464*4bdff4beSrobert         return __s;
465*4bdff4beSrobert     }
466*4bdff4beSrobert 
467*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
468*4bdff4beSrobert         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
469*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
470*4bdff4beSrobert         {return char_type(__c);}
471*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
472*4bdff4beSrobert         {return int_type(__c);}
473*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
474*4bdff4beSrobert         {return __c1 == __c2;}
475*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
476*4bdff4beSrobert         {return int_type(0xFFFF);}
477*4bdff4beSrobert };
478*4bdff4beSrobert 
479*4bdff4beSrobert inline _LIBCPP_CONSTEXPR_SINCE_CXX17
480*4bdff4beSrobert int
481*4bdff4beSrobert char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
482*4bdff4beSrobert {
483*4bdff4beSrobert     for (; __n; --__n, ++__s1, ++__s2)
484*4bdff4beSrobert     {
485*4bdff4beSrobert         if (lt(*__s1, *__s2))
486*4bdff4beSrobert             return -1;
487*4bdff4beSrobert         if (lt(*__s2, *__s1))
488*4bdff4beSrobert             return 1;
489*4bdff4beSrobert     }
490*4bdff4beSrobert     return 0;
491*4bdff4beSrobert }
492*4bdff4beSrobert 
493*4bdff4beSrobert inline _LIBCPP_CONSTEXPR_SINCE_CXX17
494*4bdff4beSrobert size_t
495*4bdff4beSrobert char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT
496*4bdff4beSrobert {
497*4bdff4beSrobert     size_t __len = 0;
498*4bdff4beSrobert     for (; !eq(*__s, char_type(0)); ++__s)
499*4bdff4beSrobert         ++__len;
500*4bdff4beSrobert     return __len;
501*4bdff4beSrobert }
502*4bdff4beSrobert 
503*4bdff4beSrobert inline _LIBCPP_CONSTEXPR_SINCE_CXX17
504*4bdff4beSrobert const char16_t*
505*4bdff4beSrobert char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
506*4bdff4beSrobert {
507*4bdff4beSrobert     for (; __n; --__n)
508*4bdff4beSrobert     {
509*4bdff4beSrobert         if (eq(*__s, __a))
510*4bdff4beSrobert             return __s;
511*4bdff4beSrobert         ++__s;
512*4bdff4beSrobert     }
513*4bdff4beSrobert     return nullptr;
514*4bdff4beSrobert }
515*4bdff4beSrobert 
516*4bdff4beSrobert template <>
517*4bdff4beSrobert struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
518*4bdff4beSrobert {
519*4bdff4beSrobert     using char_type           = char32_t;
520*4bdff4beSrobert     using int_type            = uint_least32_t;
521*4bdff4beSrobert     using off_type            = streamoff;
522*4bdff4beSrobert     using pos_type            = u32streampos;
523*4bdff4beSrobert     using state_type          = mbstate_t;
524*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
525*4bdff4beSrobert     using comparison_category = strong_ordering;
526*4bdff4beSrobert #endif
527*4bdff4beSrobert 
528*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
529*4bdff4beSrobert     void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
530*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
531*4bdff4beSrobert         {return __c1 == __c2;}
532*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
533*4bdff4beSrobert         {return __c1 < __c2;}
534*4bdff4beSrobert 
535*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
536*4bdff4beSrobert     int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
537*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
538*4bdff4beSrobert     size_t           length(const char_type* __s) _NOEXCEPT;
539*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
540*4bdff4beSrobert     const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
541*4bdff4beSrobert 
542*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
543*4bdff4beSrobert     static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
544*4bdff4beSrobert         return std::__char_traits_move(__s1, __s2, __n);
545*4bdff4beSrobert     }
546*4bdff4beSrobert 
547*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
548*4bdff4beSrobert     static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
549*4bdff4beSrobert         std::copy_n(__s2, __n, __s1);
550*4bdff4beSrobert         return __s1;
551*4bdff4beSrobert     }
552*4bdff4beSrobert 
553*4bdff4beSrobert     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
554*4bdff4beSrobert     static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
555*4bdff4beSrobert         std::fill_n(__s, __n, __a);
556*4bdff4beSrobert         return __s;
557*4bdff4beSrobert     }
558*4bdff4beSrobert 
559*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
560*4bdff4beSrobert         {return eq_int_type(__c, eof()) ? ~eof() : __c;}
561*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
562*4bdff4beSrobert         {return char_type(__c);}
563*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
564*4bdff4beSrobert         {return int_type(__c);}
565*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
566*4bdff4beSrobert         {return __c1 == __c2;}
567*4bdff4beSrobert     static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
568*4bdff4beSrobert         {return int_type(0xFFFFFFFF);}
569*4bdff4beSrobert };
570*4bdff4beSrobert 
571*4bdff4beSrobert inline _LIBCPP_CONSTEXPR_SINCE_CXX17
572*4bdff4beSrobert int
573*4bdff4beSrobert char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
574*4bdff4beSrobert {
575*4bdff4beSrobert     for (; __n; --__n, ++__s1, ++__s2)
576*4bdff4beSrobert     {
577*4bdff4beSrobert         if (lt(*__s1, *__s2))
578*4bdff4beSrobert             return -1;
579*4bdff4beSrobert         if (lt(*__s2, *__s1))
580*4bdff4beSrobert             return 1;
581*4bdff4beSrobert     }
582*4bdff4beSrobert     return 0;
583*4bdff4beSrobert }
584*4bdff4beSrobert 
585*4bdff4beSrobert inline _LIBCPP_CONSTEXPR_SINCE_CXX17
586*4bdff4beSrobert size_t
587*4bdff4beSrobert char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT
588*4bdff4beSrobert {
589*4bdff4beSrobert     size_t __len = 0;
590*4bdff4beSrobert     for (; !eq(*__s, char_type(0)); ++__s)
591*4bdff4beSrobert         ++__len;
592*4bdff4beSrobert     return __len;
593*4bdff4beSrobert }
594*4bdff4beSrobert 
595*4bdff4beSrobert inline _LIBCPP_CONSTEXPR_SINCE_CXX17
596*4bdff4beSrobert const char32_t*
597*4bdff4beSrobert char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
598*4bdff4beSrobert {
599*4bdff4beSrobert     for (; __n; --__n)
600*4bdff4beSrobert     {
601*4bdff4beSrobert         if (eq(*__s, __a))
602*4bdff4beSrobert             return __s;
603*4bdff4beSrobert         ++__s;
604*4bdff4beSrobert     }
605*4bdff4beSrobert     return nullptr;
606*4bdff4beSrobert }
607*4bdff4beSrobert 
608*4bdff4beSrobert // helper fns for basic_string and string_view
609*4bdff4beSrobert 
610*4bdff4beSrobert // __str_find
611*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
612*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
613*4bdff4beSrobert __str_find(const _CharT *__p, _SizeT __sz,
614*4bdff4beSrobert              _CharT __c, _SizeT __pos) _NOEXCEPT
615*4bdff4beSrobert {
616*4bdff4beSrobert     if (__pos >= __sz)
617*4bdff4beSrobert         return __npos;
618*4bdff4beSrobert     const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
619*4bdff4beSrobert     if (__r == nullptr)
620*4bdff4beSrobert         return __npos;
621*4bdff4beSrobert     return static_cast<_SizeT>(__r - __p);
622*4bdff4beSrobert }
623*4bdff4beSrobert 
624*4bdff4beSrobert template <class _CharT, class _Traits>
625*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const _CharT *
626*4bdff4beSrobert __search_substring(const _CharT *__first1, const _CharT *__last1,
627*4bdff4beSrobert                    const _CharT *__first2, const _CharT *__last2) _NOEXCEPT {
628*4bdff4beSrobert   // Take advantage of knowing source and pattern lengths.
629*4bdff4beSrobert   // Stop short when source is smaller than pattern.
630*4bdff4beSrobert   const ptrdiff_t __len2 = __last2 - __first2;
631*4bdff4beSrobert   if (__len2 == 0)
632*4bdff4beSrobert     return __first1;
633*4bdff4beSrobert 
634*4bdff4beSrobert   ptrdiff_t __len1 = __last1 - __first1;
635*4bdff4beSrobert   if (__len1 < __len2)
636*4bdff4beSrobert     return __last1;
637*4bdff4beSrobert 
638*4bdff4beSrobert   // First element of __first2 is loop invariant.
639*4bdff4beSrobert   _CharT __f2 = *__first2;
640*4bdff4beSrobert   while (true) {
641*4bdff4beSrobert     __len1 = __last1 - __first1;
642*4bdff4beSrobert     // Check whether __first1 still has at least __len2 bytes.
643*4bdff4beSrobert     if (__len1 < __len2)
644*4bdff4beSrobert       return __last1;
645*4bdff4beSrobert 
646*4bdff4beSrobert     // Find __f2 the first byte matching in __first1.
647*4bdff4beSrobert     __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
648*4bdff4beSrobert     if (__first1 == nullptr)
649*4bdff4beSrobert       return __last1;
650*4bdff4beSrobert 
651*4bdff4beSrobert     // It is faster to compare from the first byte of __first1 even if we
652*4bdff4beSrobert     // already know that it matches the first byte of __first2: this is because
653*4bdff4beSrobert     // __first2 is most likely aligned, as it is user's "pattern" string, and
654*4bdff4beSrobert     // __first1 + 1 is most likely not aligned, as the match is in the middle of
655*4bdff4beSrobert     // the string.
656*4bdff4beSrobert     if (_Traits::compare(__first1, __first2, __len2) == 0)
657*4bdff4beSrobert       return __first1;
658*4bdff4beSrobert 
659*4bdff4beSrobert     ++__first1;
660*4bdff4beSrobert   }
661*4bdff4beSrobert }
662*4bdff4beSrobert 
663*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
664*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
665*4bdff4beSrobert __str_find(const _CharT *__p, _SizeT __sz,
666*4bdff4beSrobert        const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
667*4bdff4beSrobert {
668*4bdff4beSrobert     if (__pos > __sz)
669*4bdff4beSrobert         return __npos;
670*4bdff4beSrobert 
671*4bdff4beSrobert     if (__n == 0) // There is nothing to search, just return __pos.
672*4bdff4beSrobert         return __pos;
673*4bdff4beSrobert 
674*4bdff4beSrobert     const _CharT *__r = std::__search_substring<_CharT, _Traits>(
675*4bdff4beSrobert         __p + __pos, __p + __sz, __s, __s + __n);
676*4bdff4beSrobert 
677*4bdff4beSrobert     if (__r == __p + __sz)
678*4bdff4beSrobert         return __npos;
679*4bdff4beSrobert     return static_cast<_SizeT>(__r - __p);
680*4bdff4beSrobert }
681*4bdff4beSrobert 
682*4bdff4beSrobert 
683*4bdff4beSrobert // __str_rfind
684*4bdff4beSrobert 
685*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
686*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
687*4bdff4beSrobert __str_rfind(const _CharT *__p, _SizeT __sz,
688*4bdff4beSrobert               _CharT __c, _SizeT __pos) _NOEXCEPT
689*4bdff4beSrobert {
690*4bdff4beSrobert     if (__sz < 1)
691*4bdff4beSrobert         return __npos;
692*4bdff4beSrobert     if (__pos < __sz)
693*4bdff4beSrobert         ++__pos;
694*4bdff4beSrobert     else
695*4bdff4beSrobert         __pos = __sz;
696*4bdff4beSrobert     for (const _CharT* __ps = __p + __pos; __ps != __p;)
697*4bdff4beSrobert     {
698*4bdff4beSrobert         if (_Traits::eq(*--__ps, __c))
699*4bdff4beSrobert             return static_cast<_SizeT>(__ps - __p);
700*4bdff4beSrobert     }
701*4bdff4beSrobert     return __npos;
702*4bdff4beSrobert }
703*4bdff4beSrobert 
704*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
705*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
706*4bdff4beSrobert __str_rfind(const _CharT *__p, _SizeT __sz,
707*4bdff4beSrobert         const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
708*4bdff4beSrobert {
709*4bdff4beSrobert     __pos = _VSTD::min(__pos, __sz);
710*4bdff4beSrobert     if (__n < __sz - __pos)
711*4bdff4beSrobert         __pos += __n;
712*4bdff4beSrobert     else
713*4bdff4beSrobert         __pos = __sz;
714*4bdff4beSrobert     const _CharT* __r = std::__find_end_classic(__p, __p + __pos, __s, __s + __n, _Traits::eq);
715*4bdff4beSrobert     if (__n > 0 && __r == __p + __pos)
716*4bdff4beSrobert         return __npos;
717*4bdff4beSrobert     return static_cast<_SizeT>(__r - __p);
718*4bdff4beSrobert }
719*4bdff4beSrobert 
720*4bdff4beSrobert // __str_find_first_of
721*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
722*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
723*4bdff4beSrobert __str_find_first_of(const _CharT *__p, _SizeT __sz,
724*4bdff4beSrobert                 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
725*4bdff4beSrobert {
726*4bdff4beSrobert     if (__pos >= __sz || __n == 0)
727*4bdff4beSrobert         return __npos;
728*4bdff4beSrobert     const _CharT* __r = _VSTD::__find_first_of_ce
729*4bdff4beSrobert         (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
730*4bdff4beSrobert     if (__r == __p + __sz)
731*4bdff4beSrobert         return __npos;
732*4bdff4beSrobert     return static_cast<_SizeT>(__r - __p);
733*4bdff4beSrobert }
734*4bdff4beSrobert 
735*4bdff4beSrobert 
736*4bdff4beSrobert // __str_find_last_of
737*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
738*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
739*4bdff4beSrobert __str_find_last_of(const _CharT *__p, _SizeT __sz,
740*4bdff4beSrobert                const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
741*4bdff4beSrobert     {
742*4bdff4beSrobert     if (__n != 0)
743*4bdff4beSrobert     {
744*4bdff4beSrobert         if (__pos < __sz)
745*4bdff4beSrobert             ++__pos;
746*4bdff4beSrobert         else
747*4bdff4beSrobert             __pos = __sz;
748*4bdff4beSrobert         for (const _CharT* __ps = __p + __pos; __ps != __p;)
749*4bdff4beSrobert         {
750*4bdff4beSrobert             const _CharT* __r = _Traits::find(__s, __n, *--__ps);
751*4bdff4beSrobert             if (__r)
752*4bdff4beSrobert                 return static_cast<_SizeT>(__ps - __p);
753*4bdff4beSrobert         }
754*4bdff4beSrobert     }
755*4bdff4beSrobert     return __npos;
756*4bdff4beSrobert }
757*4bdff4beSrobert 
758*4bdff4beSrobert 
759*4bdff4beSrobert // __str_find_first_not_of
760*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
761*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
762*4bdff4beSrobert __str_find_first_not_of(const _CharT *__p, _SizeT __sz,
763*4bdff4beSrobert                     const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
764*4bdff4beSrobert {
765*4bdff4beSrobert     if (__pos < __sz)
766*4bdff4beSrobert     {
767*4bdff4beSrobert         const _CharT* __pe = __p + __sz;
768*4bdff4beSrobert         for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
769*4bdff4beSrobert             if (_Traits::find(__s, __n, *__ps) == nullptr)
770*4bdff4beSrobert                 return static_cast<_SizeT>(__ps - __p);
771*4bdff4beSrobert     }
772*4bdff4beSrobert     return __npos;
773*4bdff4beSrobert }
774*4bdff4beSrobert 
775*4bdff4beSrobert 
776*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
777*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
778*4bdff4beSrobert __str_find_first_not_of(const _CharT *__p, _SizeT __sz,
779*4bdff4beSrobert                           _CharT __c, _SizeT __pos) _NOEXCEPT
780*4bdff4beSrobert {
781*4bdff4beSrobert     if (__pos < __sz)
782*4bdff4beSrobert     {
783*4bdff4beSrobert         const _CharT* __pe = __p + __sz;
784*4bdff4beSrobert         for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
785*4bdff4beSrobert             if (!_Traits::eq(*__ps, __c))
786*4bdff4beSrobert                 return static_cast<_SizeT>(__ps - __p);
787*4bdff4beSrobert     }
788*4bdff4beSrobert     return __npos;
789*4bdff4beSrobert }
790*4bdff4beSrobert 
791*4bdff4beSrobert 
792*4bdff4beSrobert // __str_find_last_not_of
793*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
794*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
795*4bdff4beSrobert __str_find_last_not_of(const _CharT *__p, _SizeT __sz,
796*4bdff4beSrobert                    const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
797*4bdff4beSrobert {
798*4bdff4beSrobert     if (__pos < __sz)
799*4bdff4beSrobert         ++__pos;
800*4bdff4beSrobert     else
801*4bdff4beSrobert         __pos = __sz;
802*4bdff4beSrobert     for (const _CharT* __ps = __p + __pos; __ps != __p;)
803*4bdff4beSrobert         if (_Traits::find(__s, __n, *--__ps) == nullptr)
804*4bdff4beSrobert             return static_cast<_SizeT>(__ps - __p);
805*4bdff4beSrobert     return __npos;
806*4bdff4beSrobert }
807*4bdff4beSrobert 
808*4bdff4beSrobert 
809*4bdff4beSrobert template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
810*4bdff4beSrobert inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
811*4bdff4beSrobert __str_find_last_not_of(const _CharT *__p, _SizeT __sz,
812*4bdff4beSrobert                          _CharT __c, _SizeT __pos) _NOEXCEPT
813*4bdff4beSrobert {
814*4bdff4beSrobert     if (__pos < __sz)
815*4bdff4beSrobert         ++__pos;
816*4bdff4beSrobert     else
817*4bdff4beSrobert         __pos = __sz;
818*4bdff4beSrobert     for (const _CharT* __ps = __p + __pos; __ps != __p;)
819*4bdff4beSrobert         if (!_Traits::eq(*--__ps, __c))
820*4bdff4beSrobert             return static_cast<_SizeT>(__ps - __p);
821*4bdff4beSrobert     return __npos;
822*4bdff4beSrobert }
823*4bdff4beSrobert 
824*4bdff4beSrobert template<class _Ptr>
825*4bdff4beSrobert inline _LIBCPP_INLINE_VISIBILITY
826*4bdff4beSrobert size_t __do_string_hash(_Ptr __p, _Ptr __e)
827*4bdff4beSrobert {
828*4bdff4beSrobert     typedef typename iterator_traits<_Ptr>::value_type value_type;
829*4bdff4beSrobert     return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
830*4bdff4beSrobert }
831*4bdff4beSrobert 
832*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
833*4bdff4beSrobert 
834*4bdff4beSrobert _LIBCPP_POP_MACROS
835*4bdff4beSrobert 
836*4bdff4beSrobert #endif // _LIBCPP___STRING_CHAR_TRAITS_H
837