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