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 <__utility/is_pointer_in_range.h> 24 #include <cstddef> 25 #include <cstdint> 26 #include <cstdio> 27 #include <iosfwd> 28 29 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 30 # include <cwchar> // for wmemcpy 31 #endif 32 33 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 34 # pragma GCC system_header 35 #endif 36 37 _LIBCPP_PUSH_MACROS 38 #include <__undef_macros> 39 40 _LIBCPP_BEGIN_NAMESPACE_STD 41 42 template <class _CharT> 43 struct char_traits; 44 /* 45 The Standard does not define the base template for char_traits because it is impossible to provide 46 a correct definition for arbitrary character types. Instead, it requires implementations to provide 47 specializations for predefined character types like `char`, `wchar_t` and others. We provide this as 48 exposition-only to document what members a char_traits specialization should provide: 49 { 50 using char_type = _CharT; 51 using int_type = ...; 52 using off_type = ...; 53 using pos_type = ...; 54 using state_type = ...; 55 56 static void assign(char_type&, const char_type&); 57 static bool eq(char_type, char_type); 58 static bool lt(char_type, char_type); 59 60 static int compare(const char_type*, const char_type*, size_t); 61 static size_t length(const char_type*); 62 static const char_type* find(const char_type*, size_t, const char_type&); 63 static char_type* move(char_type*, const char_type*, size_t); 64 static char_type* copy(char_type*, const char_type*, size_t); 65 static char_type* assign(char_type*, size_t, char_type); 66 67 static int_type not_eof(int_type); 68 static char_type to_char_type(int_type); 69 static int_type to_int_type(char_type); 70 static bool eq_int_type(int_type, int_type); 71 static int_type eof(); 72 }; 73 */ 74 75 // 76 // Temporary extension to provide a base template for std::char_traits. 77 // TODO(LLVM-19): Remove this class. 78 // 79 #if !defined(_LIBCPP_CHAR_TRAITS_REMOVE_BASE_SPECIALIZATION) 80 template <class _CharT> 81 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 19, so please migrate off of it.") 82 char_traits 83 { 84 using char_type = _CharT; 85 using int_type = int; 86 using off_type = streamoff; 87 using pos_type = streampos; 88 using state_type = mbstate_t; 89 90 static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_HIDE_FROM_ABI assignchar_traits91 assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} eqchar_traits92 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 93 {return __c1 == __c2;} ltchar_traits94 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 95 {return __c1 < __c2;} 96 97 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 comparechar_traits98 int compare(const char_type* __s1, const char_type* __s2, size_t __n) { 99 for (; __n; --__n, ++__s1, ++__s2) 100 { 101 if (lt(*__s1, *__s2)) 102 return -1; 103 if (lt(*__s2, *__s1)) 104 return 1; 105 } 106 return 0; 107 } 108 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 lengthchar_traits109 size_t length(const char_type* __s) { 110 size_t __len = 0; 111 for (; !eq(*__s, char_type(0)); ++__s) 112 ++__len; 113 return __len; 114 } 115 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 findchar_traits116 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { 117 for (; __n; --__n) 118 { 119 if (eq(*__s, __a)) 120 return __s; 121 ++__s; 122 } 123 return nullptr; 124 } 125 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 movechar_traits126 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) { 127 if (__n == 0) return __s1; 128 char_type* __r = __s1; 129 if (__s1 < __s2) 130 { 131 for (; __n; --__n, ++__s1, ++__s2) 132 assign(*__s1, *__s2); 133 } 134 else if (__s2 < __s1) 135 { 136 __s1 += __n; 137 __s2 += __n; 138 for (; __n; --__n) 139 assign(*--__s1, *--__s2); 140 } 141 return __r; 142 } 143 _LIBCPP_INLINE_VISIBILITY 144 static _LIBCPP_CONSTEXPR_SINCE_CXX20 copychar_traits145 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) { 146 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), 147 "char_traits::copy: source and destination ranges overlap"); 148 char_type* __r = __s1; 149 for (; __n; --__n, ++__s1, ++__s2) 150 assign(*__s1, *__s2); 151 return __r; 152 } 153 _LIBCPP_INLINE_VISIBILITY 154 static _LIBCPP_CONSTEXPR_SINCE_CXX20 assignchar_traits155 char_type* assign(char_type* __s, size_t __n, char_type __a) { 156 char_type* __r = __s; 157 for (; __n; --__n, ++__s) 158 assign(*__s, __a); 159 return __r; 160 } 161 not_eofchar_traits162 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 163 {return eq_int_type(__c, eof()) ? ~eof() : __c;} to_char_typechar_traits164 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 165 {return char_type(__c);} to_int_typechar_traits166 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 167 {return int_type(__c);} eq_int_typechar_traits168 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 169 {return __c1 == __c2;} eofchar_traits170 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 171 {return int_type(EOF);} 172 }; 173 #endif // !defined(_LIBCPP_CHAR_TRAITS_REMOVE_BASE_SPECIALIZATION) 174 175 // char_traits<char> 176 177 template <> 178 struct _LIBCPP_TEMPLATE_VIS char_traits<char> 179 { 180 using char_type = char; 181 using int_type = int; 182 using off_type = streamoff; 183 using pos_type = streampos; 184 using state_type = mbstate_t; 185 #if _LIBCPP_STD_VER >= 20 186 using comparison_category = strong_ordering; 187 #endif 188 189 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 190 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 191 192 // TODO: Make this _LIBCPP_HIDE_FROM_ABI 193 static inline _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 194 {return __c1 == __c2;} 195 static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 196 {return (unsigned char)__c1 < (unsigned char)__c2;} 197 198 // __constexpr_memcmp requires a trivially lexicographically comparable type, but char is not when char is a signed type 199 static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int 200 compare(const char_type* __lhs, const char_type* __rhs, size_t __count) _NOEXCEPT { 201 if (__libcpp_is_constant_evaluated()) { 202 #ifdef _LIBCPP_COMPILER_CLANG_BASED 203 return __builtin_memcmp(__lhs, __rhs, __count); 204 #else 205 while (__count != 0) { 206 if (lt(*__lhs, *__rhs)) 207 return -1; 208 if (lt(*__rhs, *__lhs)) 209 return 1; 210 211 __count -= sizeof(char_type); 212 ++__lhs; 213 ++__rhs; 214 } 215 return 0; 216 #endif // _LIBCPP_COMPILER_CLANG_BASED 217 } else { 218 return __builtin_memcmp(__lhs, __rhs, __count); 219 } 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_memchr(__s, __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::__constexpr_memmove(__s1, __s2, __element_count(__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 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), 241 "char_traits::copy: source and destination ranges overlap"); 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::__constexpr_memmove(__s1, __s2, __element_count(__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 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), 312 "char_traits::copy: source and destination ranges overlap"); 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, __element_count(__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::__constexpr_memmove(__s1, __s2, __element_count(__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 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), 376 "char_traits::copy: source and destination ranges overlap"); 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::__constexpr_memmove(__s1, __s2, __element_count(__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 _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), 460 "char_traits::copy: source and destination ranges overlap"); 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::__constexpr_memmove(__s1, __s2, __element_count(__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