1 // Character Traits for use by standard string and iostream -*- C++ -*- 2 3 // Copyright (C) 1997-2022 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file bits/char_traits.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{string} 28 */ 29 30 // 31 // ISO C++ 14882: 21 Strings library 32 // 33 34 #ifndef _CHAR_TRAITS_H 35 #define _CHAR_TRAITS_H 1 36 37 #pragma GCC system_header 38 39 #include <bits/postypes.h> // For streampos 40 #include <cwchar> // For WEOF, wmemmove, wmemset, etc. 41 #if __cplusplus >= 201103L 42 # include <type_traits> 43 #endif 44 #if __cplusplus >= 202002L 45 # include <compare> 46 # include <bits/stl_construct.h> 47 #endif 48 49 #ifndef _GLIBCXX_ALWAYS_INLINE 50 # define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) 51 #endif 52 53 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 54 { 55 _GLIBCXX_BEGIN_NAMESPACE_VERSION 56 57 #pragma GCC diagnostic push 58 #pragma GCC diagnostic ignored "-Wstringop-overflow" 59 #pragma GCC diagnostic ignored "-Wstringop-overread" 60 #pragma GCC diagnostic ignored "-Warray-bounds" 61 62 /** 63 * @brief Mapping from character type to associated types. 64 * 65 * @note This is an implementation class for the generic version 66 * of char_traits. It defines int_type, off_type, pos_type, and 67 * state_type. By default these are unsigned long, streamoff, 68 * streampos, and mbstate_t. Users who need a different set of 69 * types, but who don't need to change the definitions of any function 70 * defined in char_traits, can specialize __gnu_cxx::_Char_types 71 * while leaving __gnu_cxx::char_traits alone. */ 72 template<typename _CharT> 73 struct _Char_types 74 { 75 typedef unsigned long int_type; 76 typedef std::streampos pos_type; 77 typedef std::streamoff off_type; 78 typedef std::mbstate_t state_type; 79 }; 80 81 82 /** 83 * @brief Base class used to implement std::char_traits. 84 * 85 * @note For any given actual character type, this definition is 86 * probably wrong. (Most of the member functions are likely to be 87 * right, but the int_type and state_type typedefs, and the eof() 88 * member function, are likely to be wrong.) The reason this class 89 * exists is so users can specialize it. Classes in namespace std 90 * may not be specialized for fundamental types, but classes in 91 * namespace __gnu_cxx may be. 92 * 93 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types 94 * for advice on how to make use of this class for @a unusual character 95 * types. Also, check out include/ext/pod_char_traits.h. 96 */ 97 template<typename _CharT> 98 struct char_traits 99 { 100 typedef _CharT char_type; 101 typedef typename _Char_types<_CharT>::int_type int_type; 102 typedef typename _Char_types<_CharT>::pos_type pos_type; 103 typedef typename _Char_types<_CharT>::off_type off_type; 104 typedef typename _Char_types<_CharT>::state_type state_type; 105 #if __cpp_lib_three_way_comparison 106 using comparison_category = std::strong_ordering; 107 #endif 108 109 static _GLIBCXX14_CONSTEXPR void 110 assign(char_type& __c1, const char_type& __c2) 111 { 112 #if __cpp_constexpr_dynamic_alloc 113 if (std::__is_constant_evaluated()) 114 std::construct_at(__builtin_addressof(__c1), __c2); 115 else 116 #endif 117 __c1 = __c2; 118 } 119 120 static _GLIBCXX_CONSTEXPR bool 121 eq(const char_type& __c1, const char_type& __c2) 122 { return __c1 == __c2; } 123 124 static _GLIBCXX_CONSTEXPR bool 125 lt(const char_type& __c1, const char_type& __c2) 126 { return __c1 < __c2; } 127 128 static _GLIBCXX14_CONSTEXPR int 129 compare(const char_type* __s1, const char_type* __s2, std::size_t __n); 130 131 static _GLIBCXX14_CONSTEXPR std::size_t 132 length(const char_type* __s); 133 134 static _GLIBCXX14_CONSTEXPR const char_type* 135 find(const char_type* __s, std::size_t __n, const char_type& __a); 136 137 static _GLIBCXX20_CONSTEXPR char_type* 138 move(char_type* __s1, const char_type* __s2, std::size_t __n); 139 140 static _GLIBCXX20_CONSTEXPR char_type* 141 copy(char_type* __s1, const char_type* __s2, std::size_t __n); 142 143 static _GLIBCXX20_CONSTEXPR char_type* 144 assign(char_type* __s, std::size_t __n, char_type __a); 145 146 static _GLIBCXX_CONSTEXPR char_type 147 to_char_type(const int_type& __c) 148 { return static_cast<char_type>(__c); } 149 150 static _GLIBCXX_CONSTEXPR int_type 151 to_int_type(const char_type& __c) 152 { return static_cast<int_type>(__c); } 153 154 static _GLIBCXX_CONSTEXPR bool 155 eq_int_type(const int_type& __c1, const int_type& __c2) 156 { return __c1 == __c2; } 157 158 static _GLIBCXX_CONSTEXPR int_type 159 eof() 160 { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); } 161 162 static _GLIBCXX_CONSTEXPR int_type 163 not_eof(const int_type& __c) 164 { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } 165 }; 166 167 template<typename _CharT> 168 _GLIBCXX14_CONSTEXPR int 169 char_traits<_CharT>:: 170 compare(const char_type* __s1, const char_type* __s2, std::size_t __n) 171 { 172 for (std::size_t __i = 0; __i < __n; ++__i) 173 if (lt(__s1[__i], __s2[__i])) 174 return -1; 175 else if (lt(__s2[__i], __s1[__i])) 176 return 1; 177 return 0; 178 } 179 180 template<typename _CharT> 181 _GLIBCXX14_CONSTEXPR std::size_t 182 char_traits<_CharT>:: 183 length(const char_type* __p) 184 { 185 std::size_t __i = 0; 186 while (!eq(__p[__i], char_type())) 187 ++__i; 188 return __i; 189 } 190 191 template<typename _CharT> 192 _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type* 193 char_traits<_CharT>:: 194 find(const char_type* __s, std::size_t __n, const char_type& __a) 195 { 196 for (std::size_t __i = 0; __i < __n; ++__i) 197 if (eq(__s[__i], __a)) 198 return __s + __i; 199 return 0; 200 } 201 202 template<typename _CharT> 203 _GLIBCXX20_CONSTEXPR 204 typename char_traits<_CharT>::char_type* 205 char_traits<_CharT>:: 206 move(char_type* __s1, const char_type* __s2, std::size_t __n) 207 { 208 if (__n == 0) 209 return __s1; 210 #if __cplusplus >= 202002L 211 if (std::__is_constant_evaluated()) 212 { 213 if (__s1 == __s2) // unlikely, but saves a lot of work 214 return __s1; 215 #if __cpp_constexpr_dynamic_alloc 216 // The overlap detection below fails due to PR c++/89074, 217 // so use a temporary buffer instead. 218 char_type* __tmp = new char_type[__n]; 219 copy(__tmp, __s2, __n); 220 copy(__s1, __tmp, __n); 221 delete[] __tmp; 222 #else 223 const auto __end = __s2 + __n - 1; 224 bool __overlap = false; 225 for (std::size_t __i = 0; __i < __n - 1; ++__i) 226 { 227 if (__s1 + __i == __end) 228 { 229 __overlap = true; 230 break; 231 } 232 } 233 if (__overlap) 234 { 235 do 236 { 237 --__n; 238 assign(__s1[__n], __s2[__n]); 239 } 240 while (__n > 0); 241 } 242 else 243 copy(__s1, __s2, __n); 244 #endif 245 return __s1; 246 } 247 #endif 248 __builtin_memmove(__s1, __s2, __n * sizeof(char_type)); 249 return __s1; 250 } 251 252 template<typename _CharT> 253 _GLIBCXX20_CONSTEXPR 254 typename char_traits<_CharT>::char_type* 255 char_traits<_CharT>:: 256 copy(char_type* __s1, const char_type* __s2, std::size_t __n) 257 { 258 if (__n == 0) 259 return __s1; 260 #if __cplusplus >= 202002L 261 if (std::__is_constant_evaluated()) 262 { 263 for (std::size_t __i = 0; __i < __n; ++__i) 264 std::construct_at(__s1 + __i, __s2[__i]); 265 return __s1; 266 } 267 #endif 268 __builtin_memcpy(__s1, __s2, __n * sizeof(char_type)); 269 return __s1; 270 } 271 272 template<typename _CharT> 273 _GLIBCXX20_CONSTEXPR 274 typename char_traits<_CharT>::char_type* 275 char_traits<_CharT>:: 276 assign(char_type* __s, std::size_t __n, char_type __a) 277 { 278 #if __cplusplus >= 202002L 279 if (std::__is_constant_evaluated()) 280 { 281 for (std::size_t __i = 0; __i < __n; ++__i) 282 std::construct_at(__s + __i, __a); 283 return __s; 284 } 285 #endif 286 287 if _GLIBCXX17_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT)) 288 { 289 if (__n) 290 { 291 unsigned char __c; 292 __builtin_memcpy(&__c, __builtin_addressof(__a), 1); 293 __builtin_memset(__s, __c, __n); 294 } 295 } 296 else 297 { 298 for (std::size_t __i = 0; __i < __n; ++__i) 299 __s[__i] = __a; 300 } 301 return __s; 302 } 303 304 _GLIBCXX_END_NAMESPACE_VERSION 305 } // namespace 306 307 namespace std _GLIBCXX_VISIBILITY(default) 308 { 309 _GLIBCXX_BEGIN_NAMESPACE_VERSION 310 311 #ifdef __cpp_lib_is_constant_evaluated 312 // Unofficial macro indicating P1032R1 support in C++20 313 # define __cpp_lib_constexpr_char_traits 201811L 314 #elif __cplusplus >= 201703L && _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED 315 // Unofficial macro indicating P0426R1 support in C++17 316 # define __cpp_lib_constexpr_char_traits 201611L 317 #endif 318 319 // 21.1 320 /** 321 * @brief Basis for explicit traits specializations. 322 * 323 * @note For any given actual character type, this definition is 324 * probably wrong. Since this is just a thin wrapper around 325 * __gnu_cxx::char_traits, it is possible to achieve a more 326 * appropriate definition by specializing __gnu_cxx::char_traits. 327 * 328 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types 329 * for advice on how to make use of this class for @a unusual character 330 * types. Also, check out include/ext/pod_char_traits.h. 331 */ 332 template<typename _CharT> 333 struct char_traits : public __gnu_cxx::char_traits<_CharT> 334 { }; 335 336 337 /// 21.1.3.1 char_traits specializations 338 template<> 339 struct char_traits<char> 340 { 341 typedef char char_type; 342 typedef int int_type; 343 typedef streampos pos_type; 344 typedef streamoff off_type; 345 typedef mbstate_t state_type; 346 #if __cpp_lib_three_way_comparison 347 using comparison_category = strong_ordering; 348 #endif 349 350 static _GLIBCXX17_CONSTEXPR void 351 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 352 { 353 #if __cpp_constexpr_dynamic_alloc 354 if (std::__is_constant_evaluated()) 355 std::construct_at(__builtin_addressof(__c1), __c2); 356 else 357 #endif 358 __c1 = __c2; 359 } 360 361 static _GLIBCXX_CONSTEXPR bool 362 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 363 { return __c1 == __c2; } 364 365 static _GLIBCXX_CONSTEXPR bool 366 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 367 { 368 // LWG 467. 369 return (static_cast<unsigned char>(__c1) 370 < static_cast<unsigned char>(__c2)); 371 } 372 373 static _GLIBCXX17_CONSTEXPR int 374 compare(const char_type* __s1, const char_type* __s2, size_t __n) 375 { 376 if (__n == 0) 377 return 0; 378 #if __cplusplus >= 201703L 379 if (std::__is_constant_evaluated()) 380 { 381 for (size_t __i = 0; __i < __n; ++__i) 382 if (lt(__s1[__i], __s2[__i])) 383 return -1; 384 else if (lt(__s2[__i], __s1[__i])) 385 return 1; 386 return 0; 387 } 388 #endif 389 return __builtin_memcmp(__s1, __s2, __n); 390 } 391 392 static _GLIBCXX17_CONSTEXPR size_t 393 length(const char_type* __s) 394 { 395 #if __cplusplus >= 201703L 396 if (std::__is_constant_evaluated()) 397 return __gnu_cxx::char_traits<char_type>::length(__s); 398 #endif 399 return __builtin_strlen(__s); 400 } 401 402 static _GLIBCXX17_CONSTEXPR const char_type* 403 find(const char_type* __s, size_t __n, const char_type& __a) 404 { 405 if (__n == 0) 406 return 0; 407 #if __cplusplus >= 201703L 408 if (std::__is_constant_evaluated()) 409 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); 410 #endif 411 return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); 412 } 413 414 static _GLIBCXX20_CONSTEXPR char_type* 415 move(char_type* __s1, const char_type* __s2, size_t __n) 416 { 417 if (__n == 0) 418 return __s1; 419 #if __cplusplus >= 202002L 420 if (std::__is_constant_evaluated()) 421 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n); 422 #endif 423 return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); 424 } 425 426 static _GLIBCXX20_CONSTEXPR char_type* 427 copy(char_type* __s1, const char_type* __s2, size_t __n) 428 { 429 if (__n == 0) 430 return __s1; 431 #if __cplusplus >= 202002L 432 if (std::__is_constant_evaluated()) 433 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n); 434 #endif 435 return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); 436 } 437 438 static _GLIBCXX20_CONSTEXPR char_type* 439 assign(char_type* __s, size_t __n, char_type __a) 440 { 441 if (__n == 0) 442 return __s; 443 #if __cplusplus >= 202002L 444 if (std::__is_constant_evaluated()) 445 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a); 446 #endif 447 return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); 448 } 449 450 static _GLIBCXX_CONSTEXPR char_type 451 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT 452 { return static_cast<char_type>(__c); } 453 454 // To keep both the byte 0xff and the eof symbol 0xffffffff 455 // from ending up as 0xffffffff. 456 static _GLIBCXX_CONSTEXPR int_type 457 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT 458 { return static_cast<int_type>(static_cast<unsigned char>(__c)); } 459 460 static _GLIBCXX_CONSTEXPR bool 461 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT 462 { return __c1 == __c2; } 463 464 static _GLIBCXX_CONSTEXPR int_type 465 eof() _GLIBCXX_NOEXCEPT 466 { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); } 467 468 static _GLIBCXX_CONSTEXPR int_type 469 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT 470 { return (__c == eof()) ? 0 : __c; } 471 }; 472 473 474 #ifdef _GLIBCXX_USE_WCHAR_T 475 /// 21.1.3.2 char_traits specializations 476 template<> 477 struct char_traits<wchar_t> 478 { 479 typedef wchar_t char_type; 480 typedef wint_t int_type; 481 typedef streamoff off_type; 482 typedef wstreampos pos_type; 483 typedef mbstate_t state_type; 484 #if __cpp_lib_three_way_comparison 485 using comparison_category = strong_ordering; 486 #endif 487 488 static _GLIBCXX17_CONSTEXPR void 489 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 490 { 491 #if __cpp_constexpr_dynamic_alloc 492 if (std::__is_constant_evaluated()) 493 std::construct_at(__builtin_addressof(__c1), __c2); 494 else 495 #endif 496 __c1 = __c2; 497 } 498 499 static _GLIBCXX_CONSTEXPR bool 500 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 501 { return __c1 == __c2; } 502 503 static _GLIBCXX_CONSTEXPR bool 504 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 505 { return __c1 < __c2; } 506 507 static _GLIBCXX17_CONSTEXPR int 508 compare(const char_type* __s1, const char_type* __s2, size_t __n) 509 { 510 if (__n == 0) 511 return 0; 512 #if __cplusplus >= 201703L 513 if (std::__is_constant_evaluated()) 514 return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); 515 #endif 516 return wmemcmp(__s1, __s2, __n); 517 } 518 519 static _GLIBCXX17_CONSTEXPR size_t 520 length(const char_type* __s) 521 { 522 #if __cplusplus >= 201703L 523 if (std::__is_constant_evaluated()) 524 return __gnu_cxx::char_traits<char_type>::length(__s); 525 #endif 526 return wcslen(__s); 527 } 528 529 static _GLIBCXX17_CONSTEXPR const char_type* 530 find(const char_type* __s, size_t __n, const char_type& __a) 531 { 532 if (__n == 0) 533 return 0; 534 #if __cplusplus >= 201703L 535 if (std::__is_constant_evaluated()) 536 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); 537 #endif 538 return wmemchr(__s, __a, __n); 539 } 540 541 static _GLIBCXX20_CONSTEXPR char_type* 542 move(char_type* __s1, const char_type* __s2, size_t __n) 543 { 544 if (__n == 0) 545 return __s1; 546 #if __cplusplus >= 202002L 547 if (std::__is_constant_evaluated()) 548 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n); 549 #endif 550 return wmemmove(__s1, __s2, __n); 551 } 552 553 static _GLIBCXX20_CONSTEXPR char_type* 554 copy(char_type* __s1, const char_type* __s2, size_t __n) 555 { 556 if (__n == 0) 557 return __s1; 558 #if __cplusplus >= 202002L 559 if (std::__is_constant_evaluated()) 560 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n); 561 #endif 562 return wmemcpy(__s1, __s2, __n); 563 } 564 565 static _GLIBCXX20_CONSTEXPR char_type* 566 assign(char_type* __s, size_t __n, char_type __a) 567 { 568 if (__n == 0) 569 return __s; 570 #if __cplusplus >= 202002L 571 if (std::__is_constant_evaluated()) 572 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a); 573 #endif 574 return wmemset(__s, __a, __n); 575 } 576 577 static _GLIBCXX_CONSTEXPR char_type 578 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT 579 { return char_type(__c); } 580 581 static _GLIBCXX_CONSTEXPR int_type 582 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT 583 { return int_type(__c); } 584 585 static _GLIBCXX_CONSTEXPR bool 586 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT 587 { return __c1 == __c2; } 588 589 static _GLIBCXX_CONSTEXPR int_type 590 eof() _GLIBCXX_NOEXCEPT 591 { return static_cast<int_type>(WEOF); } 592 593 static _GLIBCXX_CONSTEXPR int_type 594 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT 595 { return eq_int_type(__c, eof()) ? 0 : __c; } 596 }; 597 #else // _GLIBCXX_USE_WCHAR_T 598 template<> 599 struct char_traits<wchar_t> : public __gnu_cxx::char_traits<wchar_t> 600 { }; 601 #endif //_GLIBCXX_USE_WCHAR_T 602 603 #ifdef _GLIBCXX_USE_CHAR8_T 604 template<> 605 struct char_traits<char8_t> 606 { 607 typedef char8_t char_type; 608 typedef unsigned int int_type; 609 typedef u8streampos pos_type; 610 typedef streamoff off_type; 611 typedef mbstate_t state_type; 612 #if __cpp_lib_three_way_comparison 613 using comparison_category = strong_ordering; 614 #endif 615 616 static _GLIBCXX17_CONSTEXPR void 617 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 618 { 619 #if __cpp_constexpr_dynamic_alloc 620 if (std::__is_constant_evaluated()) 621 std::construct_at(__builtin_addressof(__c1), __c2); 622 else 623 #endif 624 __c1 = __c2; 625 } 626 627 static _GLIBCXX_CONSTEXPR bool 628 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 629 { return __c1 == __c2; } 630 631 static _GLIBCXX_CONSTEXPR bool 632 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT 633 { return __c1 < __c2; } 634 635 static _GLIBCXX17_CONSTEXPR int 636 compare(const char_type* __s1, const char_type* __s2, size_t __n) 637 { 638 if (__n == 0) 639 return 0; 640 #if __cplusplus >= 201703L 641 if (std::__is_constant_evaluated()) 642 return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); 643 #endif 644 return __builtin_memcmp(__s1, __s2, __n); 645 } 646 647 static _GLIBCXX17_CONSTEXPR size_t 648 length(const char_type* __s) 649 { 650 #if __cplusplus >= 201703L 651 if (std::__is_constant_evaluated()) 652 return __gnu_cxx::char_traits<char_type>::length(__s); 653 #endif 654 size_t __i = 0; 655 while (!eq(__s[__i], char_type())) 656 ++__i; 657 return __i; 658 } 659 660 static _GLIBCXX17_CONSTEXPR const char_type* 661 find(const char_type* __s, size_t __n, const char_type& __a) 662 { 663 if (__n == 0) 664 return 0; 665 #if __cplusplus >= 201703L 666 if (std::__is_constant_evaluated()) 667 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); 668 #endif 669 return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); 670 } 671 672 static _GLIBCXX20_CONSTEXPR char_type* 673 move(char_type* __s1, const char_type* __s2, size_t __n) 674 { 675 if (__n == 0) 676 return __s1; 677 #if __cplusplus >= 202002L 678 if (std::__is_constant_evaluated()) 679 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n); 680 #endif 681 return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); 682 } 683 684 static _GLIBCXX20_CONSTEXPR char_type* 685 copy(char_type* __s1, const char_type* __s2, size_t __n) 686 { 687 if (__n == 0) 688 return __s1; 689 #if __cplusplus >= 202002L 690 if (std::__is_constant_evaluated()) 691 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n); 692 #endif 693 return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); 694 } 695 696 static _GLIBCXX20_CONSTEXPR char_type* 697 assign(char_type* __s, size_t __n, char_type __a) 698 { 699 if (__n == 0) 700 return __s; 701 #if __cplusplus >= 202002L 702 if (std::__is_constant_evaluated()) 703 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a); 704 #endif 705 return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); 706 } 707 708 static _GLIBCXX_CONSTEXPR char_type 709 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT 710 { return char_type(__c); } 711 712 static _GLIBCXX_CONSTEXPR int_type 713 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT 714 { return int_type(__c); } 715 716 static _GLIBCXX_CONSTEXPR bool 717 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT 718 { return __c1 == __c2; } 719 720 static _GLIBCXX_CONSTEXPR int_type 721 eof() _GLIBCXX_NOEXCEPT 722 { return static_cast<int_type>(-1); } 723 724 static _GLIBCXX_CONSTEXPR int_type 725 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT 726 { return eq_int_type(__c, eof()) ? 0 : __c; } 727 }; 728 #endif //_GLIBCXX_USE_CHAR8_T 729 730 _GLIBCXX_END_NAMESPACE_VERSION 731 } // namespace 732 733 #if __cplusplus >= 201103L 734 735 #include <cstdint> 736 737 namespace std _GLIBCXX_VISIBILITY(default) 738 { 739 _GLIBCXX_BEGIN_NAMESPACE_VERSION 740 741 template<> 742 struct char_traits<char16_t> 743 { 744 typedef char16_t char_type; 745 #ifdef _GLIBCXX_USE_C99_STDINT_TR1 746 typedef uint_least16_t int_type; 747 #elif defined __UINT_LEAST16_TYPE__ 748 typedef __UINT_LEAST16_TYPE__ int_type; 749 #else 750 typedef make_unsigned<char16_t>::type int_type; 751 #endif 752 typedef streamoff off_type; 753 typedef u16streampos pos_type; 754 typedef mbstate_t state_type; 755 #if __cpp_lib_three_way_comparison 756 using comparison_category = strong_ordering; 757 #endif 758 759 static _GLIBCXX17_CONSTEXPR void 760 assign(char_type& __c1, const char_type& __c2) noexcept 761 { 762 #if __cpp_constexpr_dynamic_alloc 763 if (std::__is_constant_evaluated()) 764 std::construct_at(__builtin_addressof(__c1), __c2); 765 else 766 #endif 767 __c1 = __c2; 768 } 769 770 static constexpr bool 771 eq(const char_type& __c1, const char_type& __c2) noexcept 772 { return __c1 == __c2; } 773 774 static constexpr bool 775 lt(const char_type& __c1, const char_type& __c2) noexcept 776 { return __c1 < __c2; } 777 778 static _GLIBCXX17_CONSTEXPR int 779 compare(const char_type* __s1, const char_type* __s2, size_t __n) 780 { 781 for (size_t __i = 0; __i < __n; ++__i) 782 if (lt(__s1[__i], __s2[__i])) 783 return -1; 784 else if (lt(__s2[__i], __s1[__i])) 785 return 1; 786 return 0; 787 } 788 789 static _GLIBCXX17_CONSTEXPR size_t 790 length(const char_type* __s) 791 { 792 size_t __i = 0; 793 while (!eq(__s[__i], char_type())) 794 ++__i; 795 return __i; 796 } 797 798 static _GLIBCXX17_CONSTEXPR const char_type* 799 find(const char_type* __s, size_t __n, const char_type& __a) 800 { 801 for (size_t __i = 0; __i < __n; ++__i) 802 if (eq(__s[__i], __a)) 803 return __s + __i; 804 return 0; 805 } 806 807 static _GLIBCXX20_CONSTEXPR char_type* 808 move(char_type* __s1, const char_type* __s2, size_t __n) 809 { 810 if (__n == 0) 811 return __s1; 812 #if __cplusplus >= 202002L 813 if (std::__is_constant_evaluated()) 814 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n); 815 #endif 816 return (static_cast<char_type*> 817 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); 818 } 819 820 static _GLIBCXX20_CONSTEXPR char_type* 821 copy(char_type* __s1, const char_type* __s2, size_t __n) 822 { 823 if (__n == 0) 824 return __s1; 825 #if __cplusplus >= 202002L 826 if (std::__is_constant_evaluated()) 827 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n); 828 #endif 829 return (static_cast<char_type*> 830 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); 831 } 832 833 static _GLIBCXX20_CONSTEXPR char_type* 834 assign(char_type* __s, size_t __n, char_type __a) 835 { 836 for (size_t __i = 0; __i < __n; ++__i) 837 assign(__s[__i], __a); 838 return __s; 839 } 840 841 static constexpr char_type 842 to_char_type(const int_type& __c) noexcept 843 { return char_type(__c); } 844 845 static constexpr int_type 846 to_int_type(const char_type& __c) noexcept 847 { return __c == eof() ? int_type(0xfffd) : int_type(__c); } 848 849 static constexpr bool 850 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept 851 { return __c1 == __c2; } 852 853 static constexpr int_type 854 eof() noexcept 855 { return static_cast<int_type>(-1); } 856 857 static constexpr int_type 858 not_eof(const int_type& __c) noexcept 859 { return eq_int_type(__c, eof()) ? 0 : __c; } 860 }; 861 862 template<> 863 struct char_traits<char32_t> 864 { 865 typedef char32_t char_type; 866 #ifdef _GLIBCXX_USE_C99_STDINT_TR1 867 typedef uint_least32_t int_type; 868 #elif defined __UINT_LEAST32_TYPE__ 869 typedef __UINT_LEAST32_TYPE__ int_type; 870 #else 871 typedef make_unsigned<char32_t>::type int_type; 872 #endif 873 typedef streamoff off_type; 874 typedef u32streampos pos_type; 875 typedef mbstate_t state_type; 876 #if __cpp_lib_three_way_comparison 877 using comparison_category = strong_ordering; 878 #endif 879 880 static _GLIBCXX17_CONSTEXPR void 881 assign(char_type& __c1, const char_type& __c2) noexcept 882 { 883 #if __cpp_constexpr_dynamic_alloc 884 if (std::__is_constant_evaluated()) 885 std::construct_at(__builtin_addressof(__c1), __c2); 886 else 887 #endif 888 __c1 = __c2; 889 } 890 891 static constexpr bool 892 eq(const char_type& __c1, const char_type& __c2) noexcept 893 { return __c1 == __c2; } 894 895 static constexpr bool 896 lt(const char_type& __c1, const char_type& __c2) noexcept 897 { return __c1 < __c2; } 898 899 static _GLIBCXX17_CONSTEXPR int 900 compare(const char_type* __s1, const char_type* __s2, size_t __n) 901 { 902 for (size_t __i = 0; __i < __n; ++__i) 903 if (lt(__s1[__i], __s2[__i])) 904 return -1; 905 else if (lt(__s2[__i], __s1[__i])) 906 return 1; 907 return 0; 908 } 909 910 static _GLIBCXX17_CONSTEXPR size_t 911 length(const char_type* __s) 912 { 913 size_t __i = 0; 914 while (!eq(__s[__i], char_type())) 915 ++__i; 916 return __i; 917 } 918 919 static _GLIBCXX17_CONSTEXPR const char_type* 920 find(const char_type* __s, size_t __n, const char_type& __a) 921 { 922 for (size_t __i = 0; __i < __n; ++__i) 923 if (eq(__s[__i], __a)) 924 return __s + __i; 925 return 0; 926 } 927 928 static _GLIBCXX20_CONSTEXPR char_type* 929 move(char_type* __s1, const char_type* __s2, size_t __n) 930 { 931 if (__n == 0) 932 return __s1; 933 #if __cplusplus >= 202002L 934 if (std::__is_constant_evaluated()) 935 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n); 936 #endif 937 return (static_cast<char_type*> 938 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); 939 } 940 941 static _GLIBCXX20_CONSTEXPR char_type* 942 copy(char_type* __s1, const char_type* __s2, size_t __n) 943 { 944 if (__n == 0) 945 return __s1; 946 #if __cplusplus >= 202002L 947 if (std::__is_constant_evaluated()) 948 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n); 949 #endif 950 return (static_cast<char_type*> 951 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); 952 } 953 954 static _GLIBCXX20_CONSTEXPR char_type* 955 assign(char_type* __s, size_t __n, char_type __a) 956 { 957 for (size_t __i = 0; __i < __n; ++__i) 958 assign(__s[__i], __a); 959 return __s; 960 } 961 962 static constexpr char_type 963 to_char_type(const int_type& __c) noexcept 964 { return char_type(__c); } 965 966 static constexpr int_type 967 to_int_type(const char_type& __c) noexcept 968 { return int_type(__c); } 969 970 static constexpr bool 971 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept 972 { return __c1 == __c2; } 973 974 static constexpr int_type 975 eof() noexcept 976 { return static_cast<int_type>(-1); } 977 978 static constexpr int_type 979 not_eof(const int_type& __c) noexcept 980 { return eq_int_type(__c, eof()) ? 0 : __c; } 981 }; 982 983 #if __cpp_lib_three_way_comparison 984 namespace __detail 985 { 986 template<typename _ChTraits> 987 constexpr auto 988 __char_traits_cmp_cat(int __cmp) noexcept 989 { 990 if constexpr (requires { typename _ChTraits::comparison_category; }) 991 { 992 using _Cat = typename _ChTraits::comparison_category; 993 static_assert( !is_void_v<common_comparison_category_t<_Cat>> ); 994 return static_cast<_Cat>(__cmp <=> 0); 995 } 996 else 997 return static_cast<weak_ordering>(__cmp <=> 0); 998 } 999 } // namespace __detail 1000 #endif // C++20 1001 1002 #pragma GCC diagnostic pop 1003 1004 _GLIBCXX_END_NAMESPACE_VERSION 1005 } // namespace 1006 1007 #endif // C++11 1008 1009 #endif // _CHAR_TRAITS_H 1010