1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___STRING_CHAR_TRAITS_H
10 #define _LIBCPP___STRING_CHAR_TRAITS_H
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>
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>
28 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
29 # include <cwchar> // for wmemcpy
32 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
33 # pragma GCC system_header
37 #include <__undef_macros>
39 _LIBCPP_BEGIN_NAMESPACE_STD
41 template <class _CharT
>
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:
49 using char_type = _CharT;
53 using state_type = ...;
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);
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);
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();
75 // Temporary extension to provide a base template for std::char_traits.
76 // TODO(LLVM-19): Remove this class.
78 #if !defined(_LIBCPP_CHAR_TRAITS_REMOVE_BASE_SPECIALIZATION)
79 template <class _CharT
>
80 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.")
83 using char_type
= _CharT
;
85 using off_type
= streamoff
;
86 using pos_type
= streampos
;
87 using state_type
= mbstate_t;
89 static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_HIDE_FROM_ABI
90 assign(char_type
& __c1
, const char_type
& __c2
) _NOEXCEPT
{__c1
= __c2
;}
91 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool eq(char_type __c1
, char_type __c2
) _NOEXCEPT
92 {return __c1
== __c2
;}
93 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool lt(char_type __c1
, char_type __c2
) _NOEXCEPT
96 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
97 int compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
) {
98 for (; __n
; --__n
, ++__s1
, ++__s2
)
100 if (lt(*__s1
, *__s2
))
102 if (lt(*__s2
, *__s1
))
107 _LIBCPP_INLINE_VISIBILITY
static _LIBCPP_CONSTEXPR_SINCE_CXX17
108 size_t length(const char_type
* __s
) {
110 for (; !eq(*__s
, char_type(0)); ++__s
)
114 _LIBCPP_INLINE_VISIBILITY
static _LIBCPP_CONSTEXPR_SINCE_CXX17
115 const char_type
* find(const char_type
* __s
, size_t __n
, const char_type
& __a
) {
124 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
125 char_type
* move(char_type
* __s1
, const char_type
* __s2
, size_t __n
) {
126 if (__n
== 0) return __s1
;
127 char_type
* __r
= __s1
;
130 for (; __n
; --__n
, ++__s1
, ++__s2
)
131 assign(*__s1
, *__s2
);
133 else if (__s2
< __s1
)
138 assign(*--__s1
, *--__s2
);
142 _LIBCPP_INLINE_VISIBILITY
143 static _LIBCPP_CONSTEXPR_SINCE_CXX20
144 char_type
* copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
) {
145 if (!__libcpp_is_constant_evaluated()) {
146 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
147 __s2
< __s1
|| __s2
>= __s1
+ __n
, "char_traits::copy overlapped range");
149 char_type
* __r
= __s1
;
150 for (; __n
; --__n
, ++__s1
, ++__s2
)
151 assign(*__s1
, *__s2
);
154 _LIBCPP_INLINE_VISIBILITY
155 static _LIBCPP_CONSTEXPR_SINCE_CXX20
156 char_type
* assign(char_type
* __s
, size_t __n
, char_type __a
) {
157 char_type
* __r
= __s
;
158 for (; __n
; --__n
, ++__s
)
163 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
not_eof(int_type __c
) _NOEXCEPT
164 {return eq_int_type(__c
, eof()) ? ~eof() : __c
;}
165 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type
to_char_type(int_type __c
) _NOEXCEPT
166 {return char_type(__c
);}
167 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
to_int_type(char_type __c
) _NOEXCEPT
168 {return int_type(__c
);}
169 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool eq_int_type(int_type __c1
, int_type __c2
) _NOEXCEPT
170 {return __c1
== __c2
;}
171 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
eof() _NOEXCEPT
172 {return int_type(EOF
);}
174 #endif // !defined(_LIBCPP_CHAR_TRAITS_REMOVE_BASE_SPECIALIZATION)
179 struct _LIBCPP_TEMPLATE_VIS char_traits
<char>
181 using char_type
= char;
182 using int_type
= int;
183 using off_type
= streamoff
;
184 using pos_type
= streampos
;
185 using state_type
= mbstate_t;
186 #if _LIBCPP_STD_VER >= 20
187 using comparison_category
= strong_ordering
;
190 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
191 void assign(char_type
& __c1
, const char_type
& __c2
) _NOEXCEPT
{__c1
= __c2
;}
193 // TODO: Make this _LIBCPP_HIDE_FROM_ABI
194 static inline _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR
bool eq(char_type __c1
, char_type __c2
) _NOEXCEPT
195 {return __c1
== __c2
;}
196 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool lt(char_type __c1
, char_type __c2
) _NOEXCEPT
197 {return (unsigned char)__c1
< (unsigned char)__c2
;}
199 // __constexpr_memcmp requires a trivially lexicographically comparable type, but char is not when char is a signed type
200 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
int
201 compare(const char_type
* __lhs
, const char_type
* __rhs
, size_t __count
) _NOEXCEPT
{
202 if (__libcpp_is_constant_evaluated()) {
203 #ifdef _LIBCPP_COMPILER_CLANG_BASED
204 return __builtin_memcmp(__lhs
, __rhs
, __count
);
206 while (__count
!= 0) {
207 if (lt(*__lhs
, *__rhs
))
209 if (lt(*__rhs
, *__lhs
))
212 __count
-= sizeof(char_type
);
217 #endif // _LIBCPP_COMPILER_CLANG_BASED
219 return __builtin_memcmp(__lhs
, __rhs
, __count
);
223 static inline _LIBCPP_HIDE_FROM_ABI
size_t _LIBCPP_CONSTEXPR_SINCE_CXX17
length(const char_type
* __s
) _NOEXCEPT
{
224 return std::__constexpr_strlen(__s
);
227 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
228 const char_type
* find(const char_type
* __s
, size_t __n
, const char_type
& __a
) _NOEXCEPT
{
231 return std::__constexpr_memchr(__s
, __a
, __n
);
234 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
235 char_type
* move(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
236 return std::__constexpr_memmove(__s1
, __s2
, __element_count(__n
));
239 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
240 char_type
* copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
241 if (!__libcpp_is_constant_evaluated())
242 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
243 __s2
< __s1
|| __s2
>= __s1
+ __n
, "char_traits::copy overlapped range");
244 std::copy_n(__s2
, __n
, __s1
);
248 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
249 char_type
* assign(char_type
* __s
, size_t __n
, char_type __a
) _NOEXCEPT
{
250 std::fill_n(__s
, __n
, __a
);
254 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
not_eof(int_type __c
) _NOEXCEPT
255 {return eq_int_type(__c
, eof()) ? ~eof() : __c
;}
256 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type
to_char_type(int_type __c
) _NOEXCEPT
257 {return char_type(__c
);}
258 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
to_int_type(char_type __c
) _NOEXCEPT
259 {return int_type((unsigned char)__c
);}
260 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool eq_int_type(int_type __c1
, int_type __c2
) _NOEXCEPT
261 {return __c1
== __c2
;}
262 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
eof() _NOEXCEPT
263 {return int_type(EOF
);}
266 // char_traits<wchar_t>
268 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
270 struct _LIBCPP_TEMPLATE_VIS char_traits
<wchar_t>
272 using char_type
= wchar_t;
273 using int_type
= wint_t;
274 using off_type
= streamoff
;
275 using pos_type
= streampos
;
276 using state_type
= mbstate_t;
277 #if _LIBCPP_STD_VER >= 20
278 using comparison_category
= strong_ordering
;
281 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
282 void assign(char_type
& __c1
, const char_type
& __c2
) _NOEXCEPT
{__c1
= __c2
;}
283 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool eq(char_type __c1
, char_type __c2
) _NOEXCEPT
284 {return __c1
== __c2
;}
285 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool lt(char_type __c1
, char_type __c2
) _NOEXCEPT
286 {return __c1
< __c2
;}
288 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
int
289 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
292 return std::__constexpr_wmemcmp(__s1
, __s2
, __n
);
295 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
size_t length(const char_type
* __s
) _NOEXCEPT
{
296 return std::__constexpr_wcslen(__s
);
299 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
300 const char_type
* find(const char_type
* __s
, size_t __n
, const char_type
& __a
) _NOEXCEPT
{
303 return std::__constexpr_wmemchr(__s
, __a
, __n
);
306 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
307 char_type
* move(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
308 return std::__constexpr_memmove(__s1
, __s2
, __element_count(__n
));
311 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
312 char_type
* copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
313 if (!__libcpp_is_constant_evaluated())
314 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
315 __s2
< __s1
|| __s2
>= __s1
+ __n
, "char_traits::copy overlapped range");
316 std::copy_n(__s2
, __n
, __s1
);
320 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
321 char_type
* assign(char_type
* __s
, size_t __n
, char_type __a
) _NOEXCEPT
{
322 std::fill_n(__s
, __n
, __a
);
326 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
not_eof(int_type __c
) _NOEXCEPT
327 {return eq_int_type(__c
, eof()) ? ~eof() : __c
;}
328 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type
to_char_type(int_type __c
) _NOEXCEPT
329 {return char_type(__c
);}
330 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
to_int_type(char_type __c
) _NOEXCEPT
331 {return int_type(__c
);}
332 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool eq_int_type(int_type __c1
, int_type __c2
) _NOEXCEPT
333 {return __c1
== __c2
;}
334 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
eof() _NOEXCEPT
335 {return int_type(WEOF
);}
337 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
339 #ifndef _LIBCPP_HAS_NO_CHAR8_T
342 struct _LIBCPP_TEMPLATE_VIS char_traits
<char8_t
>
344 using char_type
= char8_t
;
345 using int_type
= unsigned int;
346 using off_type
= streamoff
;
347 using pos_type
= u8streampos
;
348 using state_type
= mbstate_t;
349 #if _LIBCPP_STD_VER >= 20
350 using comparison_category
= strong_ordering
;
353 static inline _LIBCPP_HIDE_FROM_ABI
constexpr void assign(char_type
& __c1
, const char_type
& __c2
) noexcept
355 static inline _LIBCPP_HIDE_FROM_ABI
constexpr bool eq(char_type __c1
, char_type __c2
) noexcept
356 {return __c1
== __c2
;}
357 static inline _LIBCPP_HIDE_FROM_ABI
constexpr bool lt(char_type __c1
, char_type __c2
) noexcept
358 {return __c1
< __c2
;}
360 static _LIBCPP_HIDE_FROM_ABI
constexpr int
361 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
362 return std::__constexpr_memcmp(__s1
, __s2
, __element_count(__n
));
365 static _LIBCPP_HIDE_FROM_ABI
constexpr
366 size_t length(const char_type
* __s
) _NOEXCEPT
;
368 _LIBCPP_INLINE_VISIBILITY
static constexpr
369 const char_type
* find(const char_type
* __s
, size_t __n
, const char_type
& __a
) _NOEXCEPT
;
371 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
372 char_type
* move(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
373 return std::__constexpr_memmove(__s1
, __s2
, __element_count(__n
));
376 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
377 char_type
* copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
378 if (!__libcpp_is_constant_evaluated())
379 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
380 __s2
< __s1
|| __s2
>= __s1
+__n
, "char_traits::copy overlapped range");
381 std::copy_n(__s2
, __n
, __s1
);
385 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
386 char_type
* assign(char_type
* __s
, size_t __n
, char_type __a
) _NOEXCEPT
{
387 std::fill_n(__s
, __n
, __a
);
391 static inline _LIBCPP_HIDE_FROM_ABI
constexpr int_type
not_eof(int_type __c
) noexcept
392 {return eq_int_type(__c
, eof()) ? ~eof() : __c
;}
393 static inline _LIBCPP_HIDE_FROM_ABI
constexpr char_type
to_char_type(int_type __c
) noexcept
394 {return char_type(__c
);}
395 static inline _LIBCPP_HIDE_FROM_ABI
constexpr int_type
to_int_type(char_type __c
) noexcept
396 {return int_type(__c
);}
397 static inline _LIBCPP_HIDE_FROM_ABI
constexpr bool eq_int_type(int_type __c1
, int_type __c2
) noexcept
398 {return __c1
== __c2
;}
399 static inline _LIBCPP_HIDE_FROM_ABI
constexpr int_type
eof() noexcept
400 {return int_type(EOF
);}
403 // TODO use '__builtin_strlen' if it ever supports char8_t ??
406 char_traits
<char8_t
>::length(const char_type
* __s
) _NOEXCEPT
409 for (; !eq(*__s
, char_type(0)); ++__s
)
414 // TODO use '__builtin_char_memchr' if it ever supports char8_t ??
417 char_traits
<char8_t
>::find(const char_type
* __s
, size_t __n
, const char_type
& __a
) _NOEXCEPT
428 #endif // _LIBCPP_HAS_NO_CHAR8_T
431 struct _LIBCPP_TEMPLATE_VIS char_traits
<char16_t
>
433 using char_type
= char16_t
;
434 using int_type
= uint_least16_t;
435 using off_type
= streamoff
;
436 using pos_type
= u16streampos
;
437 using state_type
= mbstate_t;
438 #if _LIBCPP_STD_VER >= 20
439 using comparison_category
= strong_ordering
;
442 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
443 void assign(char_type
& __c1
, const char_type
& __c2
) _NOEXCEPT
{__c1
= __c2
;}
444 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool eq(char_type __c1
, char_type __c2
) _NOEXCEPT
445 {return __c1
== __c2
;}
446 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool lt(char_type __c1
, char_type __c2
) _NOEXCEPT
447 {return __c1
< __c2
;}
449 _LIBCPP_INLINE_VISIBILITY
static _LIBCPP_CONSTEXPR_SINCE_CXX17
450 int compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
;
451 _LIBCPP_INLINE_VISIBILITY
static _LIBCPP_CONSTEXPR_SINCE_CXX17
452 size_t length(const char_type
* __s
) _NOEXCEPT
;
453 _LIBCPP_INLINE_VISIBILITY
static _LIBCPP_CONSTEXPR_SINCE_CXX17
454 const char_type
* find(const char_type
* __s
, size_t __n
, const char_type
& __a
) _NOEXCEPT
;
456 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
457 static char_type
* move(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
458 return std::__constexpr_memmove(__s1
, __s2
, __element_count(__n
));
461 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
462 static char_type
* copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
463 if (!__libcpp_is_constant_evaluated())
464 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
465 __s2
< __s1
|| __s2
>= __s1
+__n
, "char_traits::copy overlapped range");
466 std::copy_n(__s2
, __n
, __s1
);
470 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
471 static char_type
* assign(char_type
* __s
, size_t __n
, char_type __a
) _NOEXCEPT
{
472 std::fill_n(__s
, __n
, __a
);
476 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
not_eof(int_type __c
) _NOEXCEPT
477 {return eq_int_type(__c
, eof()) ? ~eof() : __c
;}
478 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type
to_char_type(int_type __c
) _NOEXCEPT
479 {return char_type(__c
);}
480 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
to_int_type(char_type __c
) _NOEXCEPT
481 {return int_type(__c
);}
482 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool eq_int_type(int_type __c1
, int_type __c2
) _NOEXCEPT
483 {return __c1
== __c2
;}
484 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
eof() _NOEXCEPT
485 {return int_type(0xFFFF);}
488 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
490 char_traits
<char16_t
>::compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
492 for (; __n
; --__n
, ++__s1
, ++__s2
)
494 if (lt(*__s1
, *__s2
))
496 if (lt(*__s2
, *__s1
))
502 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
504 char_traits
<char16_t
>::length(const char_type
* __s
) _NOEXCEPT
507 for (; !eq(*__s
, char_type(0)); ++__s
)
512 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
514 char_traits
<char16_t
>::find(const char_type
* __s
, size_t __n
, const char_type
& __a
) _NOEXCEPT
526 struct _LIBCPP_TEMPLATE_VIS char_traits
<char32_t
>
528 using char_type
= char32_t
;
529 using int_type
= uint_least32_t;
530 using off_type
= streamoff
;
531 using pos_type
= u32streampos
;
532 using state_type
= mbstate_t;
533 #if _LIBCPP_STD_VER >= 20
534 using comparison_category
= strong_ordering
;
537 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17
538 void assign(char_type
& __c1
, const char_type
& __c2
) _NOEXCEPT
{__c1
= __c2
;}
539 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool eq(char_type __c1
, char_type __c2
) _NOEXCEPT
540 {return __c1
== __c2
;}
541 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool lt(char_type __c1
, char_type __c2
) _NOEXCEPT
542 {return __c1
< __c2
;}
544 _LIBCPP_INLINE_VISIBILITY
static _LIBCPP_CONSTEXPR_SINCE_CXX17
545 int compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
;
546 _LIBCPP_INLINE_VISIBILITY
static _LIBCPP_CONSTEXPR_SINCE_CXX17
547 size_t length(const char_type
* __s
) _NOEXCEPT
;
548 _LIBCPP_INLINE_VISIBILITY
static _LIBCPP_CONSTEXPR_SINCE_CXX17
549 const char_type
* find(const char_type
* __s
, size_t __n
, const char_type
& __a
) _NOEXCEPT
;
551 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
552 static char_type
* move(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
553 return std::__constexpr_memmove(__s1
, __s2
, __element_count(__n
));
556 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
557 static char_type
* copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
{
558 std::copy_n(__s2
, __n
, __s1
);
562 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
563 static char_type
* assign(char_type
* __s
, size_t __n
, char_type __a
) _NOEXCEPT
{
564 std::fill_n(__s
, __n
, __a
);
568 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
not_eof(int_type __c
) _NOEXCEPT
569 {return eq_int_type(__c
, eof()) ? ~eof() : __c
;}
570 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type
to_char_type(int_type __c
) _NOEXCEPT
571 {return char_type(__c
);}
572 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
to_int_type(char_type __c
) _NOEXCEPT
573 {return int_type(__c
);}
574 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
bool eq_int_type(int_type __c1
, int_type __c2
) _NOEXCEPT
575 {return __c1
== __c2
;}
576 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type
eof() _NOEXCEPT
577 {return int_type(0xFFFFFFFF);}
580 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
582 char_traits
<char32_t
>::compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
) _NOEXCEPT
584 for (; __n
; --__n
, ++__s1
, ++__s2
)
586 if (lt(*__s1
, *__s2
))
588 if (lt(*__s2
, *__s1
))
594 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
596 char_traits
<char32_t
>::length(const char_type
* __s
) _NOEXCEPT
599 for (; !eq(*__s
, char_type(0)); ++__s
)
604 inline _LIBCPP_CONSTEXPR_SINCE_CXX17
606 char_traits
<char32_t
>::find(const char_type
* __s
, size_t __n
, const char_type
& __a
) _NOEXCEPT
617 // helper fns for basic_string and string_view
620 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
621 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
622 __str_find(const _CharT
*__p
, _SizeT __sz
,
623 _CharT __c
, _SizeT __pos
) _NOEXCEPT
627 const _CharT
* __r
= _Traits::find(__p
+ __pos
, __sz
- __pos
, __c
);
630 return static_cast<_SizeT
>(__r
- __p
);
633 template <class _CharT
, class _Traits
>
634 _LIBCPP_HIDE_FROM_ABI
inline _LIBCPP_CONSTEXPR_SINCE_CXX14
const _CharT
*
635 __search_substring(const _CharT
*__first1
, const _CharT
*__last1
,
636 const _CharT
*__first2
, const _CharT
*__last2
) _NOEXCEPT
{
637 // Take advantage of knowing source and pattern lengths.
638 // Stop short when source is smaller than pattern.
639 const ptrdiff_t __len2
= __last2
- __first2
;
643 ptrdiff_t __len1
= __last1
- __first1
;
647 // First element of __first2 is loop invariant.
648 _CharT __f2
= *__first2
;
650 __len1
= __last1
- __first1
;
651 // Check whether __first1 still has at least __len2 bytes.
655 // Find __f2 the first byte matching in __first1.
656 __first1
= _Traits::find(__first1
, __len1
- __len2
+ 1, __f2
);
657 if (__first1
== nullptr)
660 // It is faster to compare from the first byte of __first1 even if we
661 // already know that it matches the first byte of __first2: this is because
662 // __first2 is most likely aligned, as it is user's "pattern" string, and
663 // __first1 + 1 is most likely not aligned, as the match is in the middle of
665 if (_Traits::compare(__first1
, __first2
, __len2
) == 0)
672 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
673 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
674 __str_find(const _CharT
*__p
, _SizeT __sz
,
675 const _CharT
* __s
, _SizeT __pos
, _SizeT __n
) _NOEXCEPT
680 if (__n
== 0) // There is nothing to search, just return __pos.
683 const _CharT
*__r
= std::__search_substring
<_CharT
, _Traits
>(
684 __p
+ __pos
, __p
+ __sz
, __s
, __s
+ __n
);
686 if (__r
== __p
+ __sz
)
688 return static_cast<_SizeT
>(__r
- __p
);
694 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
695 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
696 __str_rfind(const _CharT
*__p
, _SizeT __sz
,
697 _CharT __c
, _SizeT __pos
) _NOEXCEPT
705 for (const _CharT
* __ps
= __p
+ __pos
; __ps
!= __p
;)
707 if (_Traits::eq(*--__ps
, __c
))
708 return static_cast<_SizeT
>(__ps
- __p
);
713 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
714 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
715 __str_rfind(const _CharT
*__p
, _SizeT __sz
,
716 const _CharT
* __s
, _SizeT __pos
, _SizeT __n
) _NOEXCEPT
718 __pos
= _VSTD::min(__pos
, __sz
);
719 if (__n
< __sz
- __pos
)
723 const _CharT
* __r
= std::__find_end_classic(__p
, __p
+ __pos
, __s
, __s
+ __n
, _Traits::eq
);
724 if (__n
> 0 && __r
== __p
+ __pos
)
726 return static_cast<_SizeT
>(__r
- __p
);
729 // __str_find_first_of
730 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
731 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
732 __str_find_first_of(const _CharT
*__p
, _SizeT __sz
,
733 const _CharT
* __s
, _SizeT __pos
, _SizeT __n
) _NOEXCEPT
735 if (__pos
>= __sz
|| __n
== 0)
737 const _CharT
* __r
= _VSTD::__find_first_of_ce
738 (__p
+ __pos
, __p
+ __sz
, __s
, __s
+ __n
, _Traits::eq
);
739 if (__r
== __p
+ __sz
)
741 return static_cast<_SizeT
>(__r
- __p
);
745 // __str_find_last_of
746 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
747 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
748 __str_find_last_of(const _CharT
*__p
, _SizeT __sz
,
749 const _CharT
* __s
, _SizeT __pos
, _SizeT __n
) _NOEXCEPT
757 for (const _CharT
* __ps
= __p
+ __pos
; __ps
!= __p
;)
759 const _CharT
* __r
= _Traits::find(__s
, __n
, *--__ps
);
761 return static_cast<_SizeT
>(__ps
- __p
);
768 // __str_find_first_not_of
769 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
770 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
771 __str_find_first_not_of(const _CharT
*__p
, _SizeT __sz
,
772 const _CharT
* __s
, _SizeT __pos
, _SizeT __n
) _NOEXCEPT
776 const _CharT
* __pe
= __p
+ __sz
;
777 for (const _CharT
* __ps
= __p
+ __pos
; __ps
!= __pe
; ++__ps
)
778 if (_Traits::find(__s
, __n
, *__ps
) == nullptr)
779 return static_cast<_SizeT
>(__ps
- __p
);
785 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
786 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
787 __str_find_first_not_of(const _CharT
*__p
, _SizeT __sz
,
788 _CharT __c
, _SizeT __pos
) _NOEXCEPT
792 const _CharT
* __pe
= __p
+ __sz
;
793 for (const _CharT
* __ps
= __p
+ __pos
; __ps
!= __pe
; ++__ps
)
794 if (!_Traits::eq(*__ps
, __c
))
795 return static_cast<_SizeT
>(__ps
- __p
);
801 // __str_find_last_not_of
802 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
803 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
804 __str_find_last_not_of(const _CharT
*__p
, _SizeT __sz
,
805 const _CharT
* __s
, _SizeT __pos
, _SizeT __n
) _NOEXCEPT
811 for (const _CharT
* __ps
= __p
+ __pos
; __ps
!= __p
;)
812 if (_Traits::find(__s
, __n
, *--__ps
) == nullptr)
813 return static_cast<_SizeT
>(__ps
- __p
);
818 template<class _CharT
, class _SizeT
, class _Traits
, _SizeT __npos
>
819 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY
820 __str_find_last_not_of(const _CharT
*__p
, _SizeT __sz
,
821 _CharT __c
, _SizeT __pos
) _NOEXCEPT
827 for (const _CharT
* __ps
= __p
+ __pos
; __ps
!= __p
;)
828 if (!_Traits::eq(*--__ps
, __c
))
829 return static_cast<_SizeT
>(__ps
- __p
);
834 inline _LIBCPP_INLINE_VISIBILITY
835 size_t __do_string_hash(_Ptr __p
, _Ptr __e
)
837 typedef typename iterator_traits
<_Ptr
>::value_type value_type
;
838 return __murmur2_or_cityhash
<size_t>()(__p
, (__e
-__p
)*sizeof(value_type
));
841 _LIBCPP_END_NAMESPACE_STD
845 #endif // _LIBCPP___STRING_CHAR_TRAITS_H