1 // Character Traits for use by standard string and iostream -*- C++ -*-
3 // Copyright (C) 1997-2022 Free Software Foundation, Inc.
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)
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.
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.
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/>.
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}
31 // ISO C++ 14882: 21 Strings library
34 #ifndef _CHAR_TRAITS_H
35 #define _CHAR_TRAITS_H 1
37 #pragma GCC system_header
39 #include <bits/postypes.h> // For streampos
40 #include <cwchar> // For WEOF, wmemmove, wmemset, etc.
41 #if __cplusplus >= 201103L
42 # include <type_traits>
44 #if __cplusplus >= 202002L
46 # include <bits/stl_construct.h>
49 #ifndef _GLIBCXX_ALWAYS_INLINE
50 # define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
53 namespace __gnu_cxx
_GLIBCXX_VISIBILITY(default)
55 _GLIBCXX_BEGIN_NAMESPACE_VERSION
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"
63 * @brief Mapping from character type to associated types.
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
>
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
;
83 * @brief Base class used to implement std::char_traits.
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.
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.
97 template<typename _CharT
>
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
;
109 static _GLIBCXX14_CONSTEXPR
void
110 assign(char_type
& __c1
, const char_type
& __c2
)
112 #if __cpp_constexpr_dynamic_alloc
113 if (std::__is_constant_evaluated())
114 std::construct_at(__builtin_addressof(__c1
), __c2
);
120 static _GLIBCXX_CONSTEXPR
bool
121 eq(const char_type
& __c1
, const char_type
& __c2
)
122 { return __c1
== __c2
; }
124 static _GLIBCXX_CONSTEXPR
bool
125 lt(const char_type
& __c1
, const char_type
& __c2
)
126 { return __c1
< __c2
; }
128 static _GLIBCXX14_CONSTEXPR
int
129 compare(const char_type
* __s1
, const char_type
* __s2
, std::size_t __n
);
131 static _GLIBCXX14_CONSTEXPR
std::size_t
132 length(const char_type
* __s
);
134 static _GLIBCXX14_CONSTEXPR
const char_type
*
135 find(const char_type
* __s
, std::size_t __n
, const char_type
& __a
);
137 static _GLIBCXX20_CONSTEXPR char_type
*
138 move(char_type
* __s1
, const char_type
* __s2
, std::size_t __n
);
140 static _GLIBCXX20_CONSTEXPR char_type
*
141 copy(char_type
* __s1
, const char_type
* __s2
, std::size_t __n
);
143 static _GLIBCXX20_CONSTEXPR char_type
*
144 assign(char_type
* __s
, std::size_t __n
, char_type __a
);
146 static _GLIBCXX_CONSTEXPR char_type
147 to_char_type(const int_type
& __c
)
148 { return static_cast<char_type
>(__c
); }
150 static _GLIBCXX_CONSTEXPR int_type
151 to_int_type(const char_type
& __c
)
152 { return static_cast<int_type
>(__c
); }
154 static _GLIBCXX_CONSTEXPR
bool
155 eq_int_type(const int_type
& __c1
, const int_type
& __c2
)
156 { return __c1
== __c2
; }
158 static _GLIBCXX_CONSTEXPR int_type
160 { return static_cast<int_type
>(_GLIBCXX_STDIO_EOF
); }
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()); }
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
)
172 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
173 if (lt(__s1
[__i
], __s2
[__i
]))
175 else if (lt(__s2
[__i
], __s1
[__i
]))
180 template<typename _CharT
>
181 _GLIBCXX14_CONSTEXPR
std::size_t
182 char_traits
<_CharT
>::
183 length(const char_type
* __p
)
186 while (!eq(__p
[__i
], char_type()))
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
)
196 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
197 if (eq(__s
[__i
], __a
))
202 template<typename _CharT
>
204 typename char_traits
<_CharT
>::char_type
*
205 char_traits
<_CharT
>::
206 move(char_type
* __s1
, const char_type
* __s2
, std::size_t __n
)
210 #if __cplusplus >= 202002L
211 if (std::__is_constant_evaluated())
213 if (__s1
== __s2
) // unlikely, but saves a lot of work
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
);
223 const auto __end
= __s2
+ __n
- 1;
224 bool __overlap
= false;
225 for (std::size_t __i
= 0; __i
< __n
- 1; ++__i
)
227 if (__s1
+ __i
== __end
)
238 assign(__s1
[__n
], __s2
[__n
]);
243 copy(__s1
, __s2
, __n
);
248 __builtin_memmove(__s1
, __s2
, __n
* sizeof(char_type
));
252 template<typename _CharT
>
254 typename char_traits
<_CharT
>::char_type
*
255 char_traits
<_CharT
>::
256 copy(char_type
* __s1
, const char_type
* __s2
, std::size_t __n
)
258 #if __cplusplus >= 202002L
259 if (std::__is_constant_evaluated())
261 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
262 std::construct_at(__s1
+ __i
, __s2
[__i
]);
267 __builtin_memcpy(__s1
, __s2
, __n
* sizeof(char_type
));
271 template<typename _CharT
>
273 typename char_traits
<_CharT
>::char_type
*
274 char_traits
<_CharT
>::
275 assign(char_type
* __s
, std::size_t __n
, char_type __a
)
277 #if __cplusplus >= 202002L
278 if (std::__is_constant_evaluated())
280 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
281 std::construct_at(__s
+ __i
, __a
);
286 if _GLIBCXX17_CONSTEXPR (sizeof(_CharT
) == 1 && __is_trivial(_CharT
))
289 __builtin_memcpy(&__c
, __builtin_addressof(__a
), 1);
290 __builtin_memset(__s
, __c
, __n
);
294 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
300 _GLIBCXX_END_NAMESPACE_VERSION
303 namespace std
_GLIBCXX_VISIBILITY(default)
305 _GLIBCXX_BEGIN_NAMESPACE_VERSION
307 #ifdef __cpp_lib_is_constant_evaluated
308 // Unofficial macro indicating P1032R1 support in C++20
309 # define __cpp_lib_constexpr_char_traits 201811L
310 #elif __cplusplus >= 201703L && _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED
311 // Unofficial macro indicating P0426R1 support in C++17
312 # define __cpp_lib_constexpr_char_traits 201611L
317 * @brief Basis for explicit traits specializations.
319 * @note For any given actual character type, this definition is
320 * probably wrong. Since this is just a thin wrapper around
321 * __gnu_cxx::char_traits, it is possible to achieve a more
322 * appropriate definition by specializing __gnu_cxx::char_traits.
324 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
325 * for advice on how to make use of this class for @a unusual character
326 * types. Also, check out include/ext/pod_char_traits.h.
328 template<typename _CharT
>
329 struct char_traits
: public __gnu_cxx::char_traits
<_CharT
>
333 /// 21.1.3.1 char_traits specializations
335 struct char_traits
<char>
337 typedef char char_type
;
338 typedef int int_type
;
339 typedef streampos pos_type
;
340 typedef streamoff off_type
;
341 typedef mbstate_t state_type
;
342 #if __cpp_lib_three_way_comparison
343 using comparison_category
= strong_ordering
;
346 static _GLIBCXX17_CONSTEXPR
void
347 assign(char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
349 #if __cpp_constexpr_dynamic_alloc
350 if (std::__is_constant_evaluated())
351 std::construct_at(__builtin_addressof(__c1
), __c2
);
357 static _GLIBCXX_CONSTEXPR
bool
358 eq(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
359 { return __c1
== __c2
; }
361 static _GLIBCXX_CONSTEXPR
bool
362 lt(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
365 return (static_cast<unsigned char>(__c1
)
366 < static_cast<unsigned char>(__c2
));
369 static _GLIBCXX17_CONSTEXPR
int
370 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
374 #if __cplusplus >= 201703L
375 if (std::__is_constant_evaluated())
377 for (size_t __i
= 0; __i
< __n
; ++__i
)
378 if (lt(__s1
[__i
], __s2
[__i
]))
380 else if (lt(__s2
[__i
], __s1
[__i
]))
385 return __builtin_memcmp(__s1
, __s2
, __n
);
388 static _GLIBCXX17_CONSTEXPR
size_t
389 length(const char_type
* __s
)
391 #if __cplusplus >= 201703L
392 if (std::__is_constant_evaluated())
393 return __gnu_cxx::char_traits
<char_type
>::length(__s
);
395 return __builtin_strlen(__s
);
398 static _GLIBCXX17_CONSTEXPR
const char_type
*
399 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
403 #if __cplusplus >= 201703L
404 if (std::__is_constant_evaluated())
405 return __gnu_cxx::char_traits
<char_type
>::find(__s
, __n
, __a
);
407 return static_cast<const char_type
*>(__builtin_memchr(__s
, __a
, __n
));
410 static _GLIBCXX20_CONSTEXPR char_type
*
411 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
415 #if __cplusplus >= 202002L
416 if (std::__is_constant_evaluated())
417 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
419 return static_cast<char_type
*>(__builtin_memmove(__s1
, __s2
, __n
));
422 static _GLIBCXX20_CONSTEXPR char_type
*
423 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
427 #if __cplusplus >= 202002L
428 if (std::__is_constant_evaluated())
429 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
431 return static_cast<char_type
*>(__builtin_memcpy(__s1
, __s2
, __n
));
434 static _GLIBCXX20_CONSTEXPR char_type
*
435 assign(char_type
* __s
, size_t __n
, char_type __a
)
439 #if __cplusplus >= 202002L
440 if (std::__is_constant_evaluated())
441 return __gnu_cxx::char_traits
<char_type
>::assign(__s
, __n
, __a
);
443 return static_cast<char_type
*>(__builtin_memset(__s
, __a
, __n
));
446 static _GLIBCXX_CONSTEXPR char_type
447 to_char_type(const int_type
& __c
) _GLIBCXX_NOEXCEPT
448 { return static_cast<char_type
>(__c
); }
450 // To keep both the byte 0xff and the eof symbol 0xffffffff
451 // from ending up as 0xffffffff.
452 static _GLIBCXX_CONSTEXPR int_type
453 to_int_type(const char_type
& __c
) _GLIBCXX_NOEXCEPT
454 { return static_cast<int_type
>(static_cast<unsigned char>(__c
)); }
456 static _GLIBCXX_CONSTEXPR
bool
457 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) _GLIBCXX_NOEXCEPT
458 { return __c1
== __c2
; }
460 static _GLIBCXX_CONSTEXPR int_type
461 eof() _GLIBCXX_NOEXCEPT
462 { return static_cast<int_type
>(_GLIBCXX_STDIO_EOF
); }
464 static _GLIBCXX_CONSTEXPR int_type
465 not_eof(const int_type
& __c
) _GLIBCXX_NOEXCEPT
466 { return (__c
== eof()) ? 0 : __c
; }
470 #ifdef _GLIBCXX_USE_WCHAR_T
471 /// 21.1.3.2 char_traits specializations
473 struct char_traits
<wchar_t>
475 typedef wchar_t char_type
;
476 typedef wint_t int_type
;
477 typedef streamoff off_type
;
478 typedef wstreampos pos_type
;
479 typedef mbstate_t state_type
;
480 #if __cpp_lib_three_way_comparison
481 using comparison_category
= strong_ordering
;
484 static _GLIBCXX17_CONSTEXPR
void
485 assign(char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
487 #if __cpp_constexpr_dynamic_alloc
488 if (std::__is_constant_evaluated())
489 std::construct_at(__builtin_addressof(__c1
), __c2
);
495 static _GLIBCXX_CONSTEXPR
bool
496 eq(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
497 { return __c1
== __c2
; }
499 static _GLIBCXX_CONSTEXPR
bool
500 lt(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
501 { return __c1
< __c2
; }
503 static _GLIBCXX17_CONSTEXPR
int
504 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
508 #if __cplusplus >= 201703L
509 if (std::__is_constant_evaluated())
510 return __gnu_cxx::char_traits
<char_type
>::compare(__s1
, __s2
, __n
);
512 return wmemcmp(__s1
, __s2
, __n
);
515 static _GLIBCXX17_CONSTEXPR
size_t
516 length(const char_type
* __s
)
518 #if __cplusplus >= 201703L
519 if (std::__is_constant_evaluated())
520 return __gnu_cxx::char_traits
<char_type
>::length(__s
);
525 static _GLIBCXX17_CONSTEXPR
const char_type
*
526 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
530 #if __cplusplus >= 201703L
531 if (std::__is_constant_evaluated())
532 return __gnu_cxx::char_traits
<char_type
>::find(__s
, __n
, __a
);
534 return wmemchr(__s
, __a
, __n
);
537 static _GLIBCXX20_CONSTEXPR char_type
*
538 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
542 #if __cplusplus >= 202002L
543 if (std::__is_constant_evaluated())
544 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
546 return wmemmove(__s1
, __s2
, __n
);
549 static _GLIBCXX20_CONSTEXPR char_type
*
550 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
554 #if __cplusplus >= 202002L
555 if (std::__is_constant_evaluated())
556 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
558 return wmemcpy(__s1
, __s2
, __n
);
561 static _GLIBCXX20_CONSTEXPR char_type
*
562 assign(char_type
* __s
, size_t __n
, char_type __a
)
566 #if __cplusplus >= 202002L
567 if (std::__is_constant_evaluated())
568 return __gnu_cxx::char_traits
<char_type
>::assign(__s
, __n
, __a
);
570 return wmemset(__s
, __a
, __n
);
573 static _GLIBCXX_CONSTEXPR char_type
574 to_char_type(const int_type
& __c
) _GLIBCXX_NOEXCEPT
575 { return char_type(__c
); }
577 static _GLIBCXX_CONSTEXPR int_type
578 to_int_type(const char_type
& __c
) _GLIBCXX_NOEXCEPT
579 { return int_type(__c
); }
581 static _GLIBCXX_CONSTEXPR
bool
582 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) _GLIBCXX_NOEXCEPT
583 { return __c1
== __c2
; }
585 static _GLIBCXX_CONSTEXPR int_type
586 eof() _GLIBCXX_NOEXCEPT
587 { return static_cast<int_type
>(WEOF
); }
589 static _GLIBCXX_CONSTEXPR int_type
590 not_eof(const int_type
& __c
) _GLIBCXX_NOEXCEPT
591 { return eq_int_type(__c
, eof()) ? 0 : __c
; }
593 #else // _GLIBCXX_USE_WCHAR_T
595 struct char_traits
<wchar_t> : public __gnu_cxx::char_traits
<wchar_t>
597 #endif //_GLIBCXX_USE_WCHAR_T
599 #ifdef _GLIBCXX_USE_CHAR8_T
601 struct char_traits
<char8_t
>
603 typedef char8_t char_type
;
604 typedef unsigned int int_type
;
605 typedef u8streampos pos_type
;
606 typedef streamoff off_type
;
607 typedef mbstate_t state_type
;
608 #if __cpp_lib_three_way_comparison
609 using comparison_category
= strong_ordering
;
612 static _GLIBCXX17_CONSTEXPR
void
613 assign(char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
615 #if __cpp_constexpr_dynamic_alloc
616 if (std::__is_constant_evaluated())
617 std::construct_at(__builtin_addressof(__c1
), __c2
);
623 static _GLIBCXX_CONSTEXPR
bool
624 eq(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
625 { return __c1
== __c2
; }
627 static _GLIBCXX_CONSTEXPR
bool
628 lt(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
629 { return __c1
< __c2
; }
631 static _GLIBCXX17_CONSTEXPR
int
632 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
636 #if __cplusplus >= 201703L
637 if (std::__is_constant_evaluated())
638 return __gnu_cxx::char_traits
<char_type
>::compare(__s1
, __s2
, __n
);
640 return __builtin_memcmp(__s1
, __s2
, __n
);
643 static _GLIBCXX17_CONSTEXPR
size_t
644 length(const char_type
* __s
)
646 #if __cplusplus >= 201703L
647 if (std::__is_constant_evaluated())
648 return __gnu_cxx::char_traits
<char_type
>::length(__s
);
651 while (!eq(__s
[__i
], char_type()))
656 static _GLIBCXX17_CONSTEXPR
const char_type
*
657 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
661 #if __cplusplus >= 201703L
662 if (std::__is_constant_evaluated())
663 return __gnu_cxx::char_traits
<char_type
>::find(__s
, __n
, __a
);
665 return static_cast<const char_type
*>(__builtin_memchr(__s
, __a
, __n
));
668 static _GLIBCXX20_CONSTEXPR char_type
*
669 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
673 #if __cplusplus >= 202002L
674 if (std::__is_constant_evaluated())
675 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
677 return static_cast<char_type
*>(__builtin_memmove(__s1
, __s2
, __n
));
680 static _GLIBCXX20_CONSTEXPR char_type
*
681 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
685 #if __cplusplus >= 202002L
686 if (std::__is_constant_evaluated())
687 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
689 return static_cast<char_type
*>(__builtin_memcpy(__s1
, __s2
, __n
));
692 static _GLIBCXX20_CONSTEXPR char_type
*
693 assign(char_type
* __s
, size_t __n
, char_type __a
)
697 #if __cplusplus >= 202002L
698 if (std::__is_constant_evaluated())
699 return __gnu_cxx::char_traits
<char_type
>::assign(__s
, __n
, __a
);
701 return static_cast<char_type
*>(__builtin_memset(__s
, __a
, __n
));
704 static _GLIBCXX_CONSTEXPR char_type
705 to_char_type(const int_type
& __c
) _GLIBCXX_NOEXCEPT
706 { return char_type(__c
); }
708 static _GLIBCXX_CONSTEXPR int_type
709 to_int_type(const char_type
& __c
) _GLIBCXX_NOEXCEPT
710 { return int_type(__c
); }
712 static _GLIBCXX_CONSTEXPR
bool
713 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) _GLIBCXX_NOEXCEPT
714 { return __c1
== __c2
; }
716 static _GLIBCXX_CONSTEXPR int_type
717 eof() _GLIBCXX_NOEXCEPT
718 { return static_cast<int_type
>(-1); }
720 static _GLIBCXX_CONSTEXPR int_type
721 not_eof(const int_type
& __c
) _GLIBCXX_NOEXCEPT
722 { return eq_int_type(__c
, eof()) ? 0 : __c
; }
724 #endif //_GLIBCXX_USE_CHAR8_T
726 _GLIBCXX_END_NAMESPACE_VERSION
729 #if __cplusplus >= 201103L
733 namespace std
_GLIBCXX_VISIBILITY(default)
735 _GLIBCXX_BEGIN_NAMESPACE_VERSION
738 struct char_traits
<char16_t
>
740 typedef char16_t char_type
;
741 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
742 typedef uint_least16_t int_type
;
743 #elif defined __UINT_LEAST16_TYPE__
744 typedef __UINT_LEAST16_TYPE__ int_type
;
746 typedef make_unsigned
<char16_t
>::type int_type
;
748 typedef streamoff off_type
;
749 typedef u16streampos pos_type
;
750 typedef mbstate_t state_type
;
751 #if __cpp_lib_three_way_comparison
752 using comparison_category
= strong_ordering
;
755 static _GLIBCXX17_CONSTEXPR
void
756 assign(char_type
& __c1
, const char_type
& __c2
) noexcept
758 #if __cpp_constexpr_dynamic_alloc
759 if (std::__is_constant_evaluated())
760 std::construct_at(__builtin_addressof(__c1
), __c2
);
766 static constexpr bool
767 eq(const char_type
& __c1
, const char_type
& __c2
) noexcept
768 { return __c1
== __c2
; }
770 static constexpr bool
771 lt(const char_type
& __c1
, const char_type
& __c2
) noexcept
772 { return __c1
< __c2
; }
774 static _GLIBCXX17_CONSTEXPR
int
775 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
777 for (size_t __i
= 0; __i
< __n
; ++__i
)
778 if (lt(__s1
[__i
], __s2
[__i
]))
780 else if (lt(__s2
[__i
], __s1
[__i
]))
785 static _GLIBCXX17_CONSTEXPR
size_t
786 length(const char_type
* __s
)
789 while (!eq(__s
[__i
], char_type()))
794 static _GLIBCXX17_CONSTEXPR
const char_type
*
795 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
797 for (size_t __i
= 0; __i
< __n
; ++__i
)
798 if (eq(__s
[__i
], __a
))
803 static _GLIBCXX20_CONSTEXPR char_type
*
804 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
808 #if __cplusplus >= 202002L
809 if (std::__is_constant_evaluated())
810 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
812 return (static_cast<char_type
*>
813 (__builtin_memmove(__s1
, __s2
, __n
* sizeof(char_type
))));
816 static _GLIBCXX20_CONSTEXPR char_type
*
817 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
821 #if __cplusplus >= 202002L
822 if (std::__is_constant_evaluated())
823 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
825 return (static_cast<char_type
*>
826 (__builtin_memcpy(__s1
, __s2
, __n
* sizeof(char_type
))));
829 static _GLIBCXX20_CONSTEXPR char_type
*
830 assign(char_type
* __s
, size_t __n
, char_type __a
)
832 for (size_t __i
= 0; __i
< __n
; ++__i
)
833 assign(__s
[__i
], __a
);
837 static constexpr char_type
838 to_char_type(const int_type
& __c
) noexcept
839 { return char_type(__c
); }
841 static constexpr int_type
842 to_int_type(const char_type
& __c
) noexcept
843 { return __c
== eof() ? int_type(0xfffd) : int_type(__c
); }
845 static constexpr bool
846 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) noexcept
847 { return __c1
== __c2
; }
849 static constexpr int_type
851 { return static_cast<int_type
>(-1); }
853 static constexpr int_type
854 not_eof(const int_type
& __c
) noexcept
855 { return eq_int_type(__c
, eof()) ? 0 : __c
; }
859 struct char_traits
<char32_t
>
861 typedef char32_t char_type
;
862 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
863 typedef uint_least32_t int_type
;
864 #elif defined __UINT_LEAST32_TYPE__
865 typedef __UINT_LEAST32_TYPE__ int_type
;
867 typedef make_unsigned
<char32_t
>::type int_type
;
869 typedef streamoff off_type
;
870 typedef u32streampos pos_type
;
871 typedef mbstate_t state_type
;
872 #if __cpp_lib_three_way_comparison
873 using comparison_category
= strong_ordering
;
876 static _GLIBCXX17_CONSTEXPR
void
877 assign(char_type
& __c1
, const char_type
& __c2
) noexcept
879 #if __cpp_constexpr_dynamic_alloc
880 if (std::__is_constant_evaluated())
881 std::construct_at(__builtin_addressof(__c1
), __c2
);
887 static constexpr bool
888 eq(const char_type
& __c1
, const char_type
& __c2
) noexcept
889 { return __c1
== __c2
; }
891 static constexpr bool
892 lt(const char_type
& __c1
, const char_type
& __c2
) noexcept
893 { return __c1
< __c2
; }
895 static _GLIBCXX17_CONSTEXPR
int
896 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
898 for (size_t __i
= 0; __i
< __n
; ++__i
)
899 if (lt(__s1
[__i
], __s2
[__i
]))
901 else if (lt(__s2
[__i
], __s1
[__i
]))
906 static _GLIBCXX17_CONSTEXPR
size_t
907 length(const char_type
* __s
)
910 while (!eq(__s
[__i
], char_type()))
915 static _GLIBCXX17_CONSTEXPR
const char_type
*
916 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
918 for (size_t __i
= 0; __i
< __n
; ++__i
)
919 if (eq(__s
[__i
], __a
))
924 static _GLIBCXX20_CONSTEXPR char_type
*
925 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
929 #if __cplusplus >= 202002L
930 if (std::__is_constant_evaluated())
931 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
933 return (static_cast<char_type
*>
934 (__builtin_memmove(__s1
, __s2
, __n
* sizeof(char_type
))));
937 static _GLIBCXX20_CONSTEXPR char_type
*
938 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
942 #if __cplusplus >= 202002L
943 if (std::__is_constant_evaluated())
944 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
946 return (static_cast<char_type
*>
947 (__builtin_memcpy(__s1
, __s2
, __n
* sizeof(char_type
))));
950 static _GLIBCXX20_CONSTEXPR char_type
*
951 assign(char_type
* __s
, size_t __n
, char_type __a
)
953 for (size_t __i
= 0; __i
< __n
; ++__i
)
954 assign(__s
[__i
], __a
);
958 static constexpr char_type
959 to_char_type(const int_type
& __c
) noexcept
960 { return char_type(__c
); }
962 static constexpr int_type
963 to_int_type(const char_type
& __c
) noexcept
964 { return int_type(__c
); }
966 static constexpr bool
967 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) noexcept
968 { return __c1
== __c2
; }
970 static constexpr int_type
972 { return static_cast<int_type
>(-1); }
974 static constexpr int_type
975 not_eof(const int_type
& __c
) noexcept
976 { return eq_int_type(__c
, eof()) ? 0 : __c
; }
979 #if __cpp_lib_three_way_comparison
982 template<typename _ChTraits
>
984 __char_traits_cmp_cat(int __cmp
) noexcept
986 if constexpr (requires
{ typename
_ChTraits::comparison_category
; })
988 using _Cat
= typename
_ChTraits::comparison_category
;
989 static_assert( !is_void_v
<common_comparison_category_t
<_Cat
>> );
990 return static_cast<_Cat
>(__cmp
<=> 0);
993 return static_cast<weak_ordering
>(__cmp
<=> 0);
995 } // namespace __detail
998 #pragma GCC diagnostic pop
1000 _GLIBCXX_END_NAMESPACE_VERSION
1005 #endif // _CHAR_TRAITS_H