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