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