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 <__type_traits/is_constant_evaluated.h>
22 #include <cstddef>
23 #include <cstdint>
24 #include <cstdio>
25 #include <cstring>
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
assignchar_traits89 assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
eqchar_traits90 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
91 {return __c1 == __c2;}
ltchar_traits92 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
93 {return __c1 < __c2;}
94
95 static _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_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_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_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
164 {return char_type(__c);}
to_int_typechar_traits165 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
166 {return int_type(__c);}
eq_int_typechar_traits167 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
168 {return __c1 == __c2;}
eofchar_traits169 static inline _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 > 17
203 using comparison_category = strong_ordering;
204 #endif
205
206 static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
207 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
208 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
209 {return __c1 == __c2;}
210 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
211 {return (unsigned char)__c1 < (unsigned char)__c2;}
212
213 static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
214 if (__n == 0)
215 return 0;
216 return std::__constexpr_memcmp(__s1, __s2, __n);
217 }
218
219 static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT {
220 return std::__constexpr_strlen(__s);
221 }
222
223 static _LIBCPP_CONSTEXPR_SINCE_CXX17
224 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
225 if (__n == 0)
226 return nullptr;
227 return std::__constexpr_char_memchr(__s, static_cast<int>(__a), __n);
228 }
229
230 static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
231 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
232 return std::__char_traits_move(__s1, __s2, __n);
233 }
234
235 static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
236 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
237 if (!__libcpp_is_constant_evaluated())
238 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
239 std::copy_n(__s2, __n, __s1);
240 return __s1;
241 }
242
243 static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
244 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
245 std::fill_n(__s, __n, __a);
246 return __s;
247 }
248
249 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
250 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
251 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
252 {return char_type(__c);}
253 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
254 {return int_type((unsigned char)__c);}
255 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
256 {return __c1 == __c2;}
257 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
258 {return int_type(EOF);}
259 };
260
261 // char_traits<wchar_t>
262
263 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
264 template <>
265 struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
266 {
267 using char_type = wchar_t;
268 using int_type = wint_t;
269 using off_type = streamoff;
270 using pos_type = streampos;
271 using state_type = mbstate_t;
272 #if _LIBCPP_STD_VER > 17
273 using comparison_category = strong_ordering;
274 #endif
275
276 static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
277 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
278 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
279 {return __c1 == __c2;}
280 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
281 {return __c1 < __c2;}
282
283 static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
284 if (__n == 0)
285 return 0;
286 return std::__constexpr_wmemcmp(__s1, __s2, __n);
287 }
288
289 static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT {
290 return std::__constexpr_wcslen(__s);
291 }
292
293 static _LIBCPP_CONSTEXPR_SINCE_CXX17
294 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
295 if (__n == 0)
296 return nullptr;
297 return std::__constexpr_wmemchr(__s, __a, __n);
298 }
299
300 static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
301 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
302 return std::__char_traits_move(__s1, __s2, __n);
303 }
304
305 static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
306 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
307 if (!__libcpp_is_constant_evaluated())
308 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
309 std::copy_n(__s2, __n, __s1);
310 return __s1;
311 }
312
313 static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
314 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
315 std::fill_n(__s, __n, __a);
316 return __s;
317 }
318
319 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
320 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
321 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
322 {return char_type(__c);}
323 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
324 {return int_type(__c);}
325 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
326 {return __c1 == __c2;}
327 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
328 {return int_type(WEOF);}
329 };
330 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
331
332 #ifndef _LIBCPP_HAS_NO_CHAR8_T
333
334 template <>
335 struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
336 {
337 using char_type = char8_t;
338 using int_type = unsigned int;
339 using off_type = streamoff;
340 using pos_type = u8streampos;
341 using state_type = mbstate_t;
342 #if _LIBCPP_STD_VER > 17
343 using comparison_category = strong_ordering;
344 #endif
345
346 static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
347 {__c1 = __c2;}
348 static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
349 {return __c1 == __c2;}
350 static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
351 {return __c1 < __c2;}
352
353 static _LIBCPP_HIDE_FROM_ABI constexpr int
354 compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
355 return std::__constexpr_memcmp(__s1, __s2, __n);
356 }
357
358 static constexpr
359 size_t length(const char_type* __s) _NOEXCEPT;
360
361 _LIBCPP_INLINE_VISIBILITY static constexpr
362 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
363
364 static _LIBCPP_CONSTEXPR_SINCE_CXX20
365 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
366 return std::__char_traits_move(__s1, __s2, __n);
367 }
368
369 static _LIBCPP_CONSTEXPR_SINCE_CXX20
370 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
371 if (!__libcpp_is_constant_evaluated())
372 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
373 std::copy_n(__s2, __n, __s1);
374 return __s1;
375 }
376
377 static _LIBCPP_CONSTEXPR_SINCE_CXX20
378 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
379 std::fill_n(__s, __n, __a);
380 return __s;
381 }
382
383 static inline constexpr int_type not_eof(int_type __c) noexcept
384 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
385 static inline constexpr char_type to_char_type(int_type __c) noexcept
386 {return char_type(__c);}
387 static inline constexpr int_type to_int_type(char_type __c) noexcept
388 {return int_type(__c);}
389 static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
390 {return __c1 == __c2;}
391 static inline constexpr int_type eof() noexcept
392 {return int_type(EOF);}
393 };
394
395 // TODO use '__builtin_strlen' if it ever supports char8_t ??
396 inline constexpr
397 size_t
398 char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
399 {
400 size_t __len = 0;
401 for (; !eq(*__s, char_type(0)); ++__s)
402 ++__len;
403 return __len;
404 }
405
406 // TODO use '__builtin_char_memchr' if it ever supports char8_t ??
407 inline constexpr
408 const char8_t*
409 char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
410 {
411 for (; __n; --__n)
412 {
413 if (eq(*__s, __a))
414 return __s;
415 ++__s;
416 }
417 return nullptr;
418 }
419
420 #endif // _LIBCPP_HAS_NO_CHAR8_T
421
422 template <>
423 struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
424 {
425 using char_type = char16_t;
426 using int_type = uint_least16_t;
427 using off_type = streamoff;
428 using pos_type = u16streampos;
429 using state_type = mbstate_t;
430 #if _LIBCPP_STD_VER > 17
431 using comparison_category = strong_ordering;
432 #endif
433
434 static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
435 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
436 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
437 {return __c1 == __c2;}
438 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
439 {return __c1 < __c2;}
440
441 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
442 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
443 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
444 size_t length(const char_type* __s) _NOEXCEPT;
445 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
446 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
447
448 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
449 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
450 return std::__char_traits_move(__s1, __s2, __n);
451 }
452
453 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
454 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
455 if (!__libcpp_is_constant_evaluated())
456 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
457 std::copy_n(__s2, __n, __s1);
458 return __s1;
459 }
460
461 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
462 static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
463 std::fill_n(__s, __n, __a);
464 return __s;
465 }
466
467 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
468 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
469 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
470 {return char_type(__c);}
471 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
472 {return int_type(__c);}
473 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
474 {return __c1 == __c2;}
475 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
476 {return int_type(0xFFFF);}
477 };
478
479 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
480 int
481 char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
482 {
483 for (; __n; --__n, ++__s1, ++__s2)
484 {
485 if (lt(*__s1, *__s2))
486 return -1;
487 if (lt(*__s2, *__s1))
488 return 1;
489 }
490 return 0;
491 }
492
493 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
494 size_t
495 char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT
496 {
497 size_t __len = 0;
498 for (; !eq(*__s, char_type(0)); ++__s)
499 ++__len;
500 return __len;
501 }
502
503 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
504 const char16_t*
505 char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
506 {
507 for (; __n; --__n)
508 {
509 if (eq(*__s, __a))
510 return __s;
511 ++__s;
512 }
513 return nullptr;
514 }
515
516 template <>
517 struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
518 {
519 using char_type = char32_t;
520 using int_type = uint_least32_t;
521 using off_type = streamoff;
522 using pos_type = u32streampos;
523 using state_type = mbstate_t;
524 #if _LIBCPP_STD_VER > 17
525 using comparison_category = strong_ordering;
526 #endif
527
528 static inline _LIBCPP_CONSTEXPR_SINCE_CXX17
529 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
530 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
531 {return __c1 == __c2;}
532 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
533 {return __c1 < __c2;}
534
535 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
536 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
537 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
538 size_t length(const char_type* __s) _NOEXCEPT;
539 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
540 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
541
542 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
543 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
544 return std::__char_traits_move(__s1, __s2, __n);
545 }
546
547 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
548 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
549 std::copy_n(__s2, __n, __s1);
550 return __s1;
551 }
552
553 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
554 static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
555 std::fill_n(__s, __n, __a);
556 return __s;
557 }
558
559 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
560 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
561 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
562 {return char_type(__c);}
563 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
564 {return int_type(__c);}
565 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
566 {return __c1 == __c2;}
567 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
568 {return int_type(0xFFFFFFFF);}
569 };
570
571 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
572 int
573 char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
574 {
575 for (; __n; --__n, ++__s1, ++__s2)
576 {
577 if (lt(*__s1, *__s2))
578 return -1;
579 if (lt(*__s2, *__s1))
580 return 1;
581 }
582 return 0;
583 }
584
585 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
586 size_t
587 char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT
588 {
589 size_t __len = 0;
590 for (; !eq(*__s, char_type(0)); ++__s)
591 ++__len;
592 return __len;
593 }
594
595 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
596 const char32_t*
597 char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
598 {
599 for (; __n; --__n)
600 {
601 if (eq(*__s, __a))
602 return __s;
603 ++__s;
604 }
605 return nullptr;
606 }
607
608 // helper fns for basic_string and string_view
609
610 // __str_find
611 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
612 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
613 __str_find(const _CharT *__p, _SizeT __sz,
614 _CharT __c, _SizeT __pos) _NOEXCEPT
615 {
616 if (__pos >= __sz)
617 return __npos;
618 const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
619 if (__r == nullptr)
620 return __npos;
621 return static_cast<_SizeT>(__r - __p);
622 }
623
624 template <class _CharT, class _Traits>
625 _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const _CharT *
626 __search_substring(const _CharT *__first1, const _CharT *__last1,
627 const _CharT *__first2, const _CharT *__last2) _NOEXCEPT {
628 // Take advantage of knowing source and pattern lengths.
629 // Stop short when source is smaller than pattern.
630 const ptrdiff_t __len2 = __last2 - __first2;
631 if (__len2 == 0)
632 return __first1;
633
634 ptrdiff_t __len1 = __last1 - __first1;
635 if (__len1 < __len2)
636 return __last1;
637
638 // First element of __first2 is loop invariant.
639 _CharT __f2 = *__first2;
640 while (true) {
641 __len1 = __last1 - __first1;
642 // Check whether __first1 still has at least __len2 bytes.
643 if (__len1 < __len2)
644 return __last1;
645
646 // Find __f2 the first byte matching in __first1.
647 __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
648 if (__first1 == nullptr)
649 return __last1;
650
651 // It is faster to compare from the first byte of __first1 even if we
652 // already know that it matches the first byte of __first2: this is because
653 // __first2 is most likely aligned, as it is user's "pattern" string, and
654 // __first1 + 1 is most likely not aligned, as the match is in the middle of
655 // the string.
656 if (_Traits::compare(__first1, __first2, __len2) == 0)
657 return __first1;
658
659 ++__first1;
660 }
661 }
662
663 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
664 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
665 __str_find(const _CharT *__p, _SizeT __sz,
666 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
667 {
668 if (__pos > __sz)
669 return __npos;
670
671 if (__n == 0) // There is nothing to search, just return __pos.
672 return __pos;
673
674 const _CharT *__r = std::__search_substring<_CharT, _Traits>(
675 __p + __pos, __p + __sz, __s, __s + __n);
676
677 if (__r == __p + __sz)
678 return __npos;
679 return static_cast<_SizeT>(__r - __p);
680 }
681
682
683 // __str_rfind
684
685 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
686 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
687 __str_rfind(const _CharT *__p, _SizeT __sz,
688 _CharT __c, _SizeT __pos) _NOEXCEPT
689 {
690 if (__sz < 1)
691 return __npos;
692 if (__pos < __sz)
693 ++__pos;
694 else
695 __pos = __sz;
696 for (const _CharT* __ps = __p + __pos; __ps != __p;)
697 {
698 if (_Traits::eq(*--__ps, __c))
699 return static_cast<_SizeT>(__ps - __p);
700 }
701 return __npos;
702 }
703
704 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
705 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
706 __str_rfind(const _CharT *__p, _SizeT __sz,
707 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
708 {
709 __pos = _VSTD::min(__pos, __sz);
710 if (__n < __sz - __pos)
711 __pos += __n;
712 else
713 __pos = __sz;
714 const _CharT* __r = std::__find_end_classic(__p, __p + __pos, __s, __s + __n, _Traits::eq);
715 if (__n > 0 && __r == __p + __pos)
716 return __npos;
717 return static_cast<_SizeT>(__r - __p);
718 }
719
720 // __str_find_first_of
721 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
722 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
723 __str_find_first_of(const _CharT *__p, _SizeT __sz,
724 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
725 {
726 if (__pos >= __sz || __n == 0)
727 return __npos;
728 const _CharT* __r = _VSTD::__find_first_of_ce
729 (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
730 if (__r == __p + __sz)
731 return __npos;
732 return static_cast<_SizeT>(__r - __p);
733 }
734
735
736 // __str_find_last_of
737 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
738 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
739 __str_find_last_of(const _CharT *__p, _SizeT __sz,
740 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
741 {
742 if (__n != 0)
743 {
744 if (__pos < __sz)
745 ++__pos;
746 else
747 __pos = __sz;
748 for (const _CharT* __ps = __p + __pos; __ps != __p;)
749 {
750 const _CharT* __r = _Traits::find(__s, __n, *--__ps);
751 if (__r)
752 return static_cast<_SizeT>(__ps - __p);
753 }
754 }
755 return __npos;
756 }
757
758
759 // __str_find_first_not_of
760 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
761 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
762 __str_find_first_not_of(const _CharT *__p, _SizeT __sz,
763 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
764 {
765 if (__pos < __sz)
766 {
767 const _CharT* __pe = __p + __sz;
768 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
769 if (_Traits::find(__s, __n, *__ps) == nullptr)
770 return static_cast<_SizeT>(__ps - __p);
771 }
772 return __npos;
773 }
774
775
776 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
777 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
778 __str_find_first_not_of(const _CharT *__p, _SizeT __sz,
779 _CharT __c, _SizeT __pos) _NOEXCEPT
780 {
781 if (__pos < __sz)
782 {
783 const _CharT* __pe = __p + __sz;
784 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
785 if (!_Traits::eq(*__ps, __c))
786 return static_cast<_SizeT>(__ps - __p);
787 }
788 return __npos;
789 }
790
791
792 // __str_find_last_not_of
793 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
794 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
795 __str_find_last_not_of(const _CharT *__p, _SizeT __sz,
796 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
797 {
798 if (__pos < __sz)
799 ++__pos;
800 else
801 __pos = __sz;
802 for (const _CharT* __ps = __p + __pos; __ps != __p;)
803 if (_Traits::find(__s, __n, *--__ps) == nullptr)
804 return static_cast<_SizeT>(__ps - __p);
805 return __npos;
806 }
807
808
809 template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
810 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
811 __str_find_last_not_of(const _CharT *__p, _SizeT __sz,
812 _CharT __c, _SizeT __pos) _NOEXCEPT
813 {
814 if (__pos < __sz)
815 ++__pos;
816 else
817 __pos = __sz;
818 for (const _CharT* __ps = __p + __pos; __ps != __p;)
819 if (!_Traits::eq(*--__ps, __c))
820 return static_cast<_SizeT>(__ps - __p);
821 return __npos;
822 }
823
824 template<class _Ptr>
825 inline _LIBCPP_INLINE_VISIBILITY
826 size_t __do_string_hash(_Ptr __p, _Ptr __e)
827 {
828 typedef typename iterator_traits<_Ptr>::value_type value_type;
829 return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
830 }
831
832 _LIBCPP_END_NAMESPACE_STD
833
834 _LIBCPP_POP_MACROS
835
836 #endif // _LIBCPP___STRING_CHAR_TRAITS_H
837