1 // Character Traits for use by standard string and iostream -*- C++ -*-
3 // Copyright (C) 1997-2021 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
58 * @brief Mapping from character type to associated types.
60 * @note This is an implementation class for the generic version
61 * of char_traits. It defines int_type, off_type, pos_type, and
62 * state_type. By default these are unsigned long, streamoff,
63 * streampos, and mbstate_t. Users who need a different set of
64 * types, but who don't need to change the definitions of any function
65 * defined in char_traits, can specialize __gnu_cxx::_Char_types
66 * while leaving __gnu_cxx::char_traits alone. */
67 template<typename _CharT
>
70 typedef unsigned long int_type
;
71 typedef std::streampos pos_type
;
72 typedef std::streamoff off_type
;
73 typedef std::mbstate_t state_type
;
78 * @brief Base class used to implement std::char_traits.
80 * @note For any given actual character type, this definition is
81 * probably wrong. (Most of the member functions are likely to be
82 * right, but the int_type and state_type typedefs, and the eof()
83 * member function, are likely to be wrong.) The reason this class
84 * exists is so users can specialize it. Classes in namespace std
85 * may not be specialized for fundamental types, but classes in
86 * namespace __gnu_cxx may be.
88 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
89 * for advice on how to make use of this class for @a unusual character
90 * types. Also, check out include/ext/pod_char_traits.h.
92 template<typename _CharT
>
95 typedef _CharT char_type
;
96 typedef typename _Char_types
<_CharT
>::int_type int_type
;
97 typedef typename _Char_types
<_CharT
>::pos_type pos_type
;
98 typedef typename _Char_types
<_CharT
>::off_type off_type
;
99 typedef typename _Char_types
<_CharT
>::state_type state_type
;
100 #if __cpp_lib_three_way_comparison
101 using comparison_category
= std::strong_ordering
;
104 static _GLIBCXX14_CONSTEXPR
void
105 assign(char_type
& __c1
, const char_type
& __c2
)
107 #if __cpp_constexpr_dynamic_alloc
108 if (std::__is_constant_evaluated())
109 std::construct_at(__builtin_addressof(__c1
), __c2
);
115 static _GLIBCXX_CONSTEXPR
bool
116 eq(const char_type
& __c1
, const char_type
& __c2
)
117 { return __c1
== __c2
; }
119 static _GLIBCXX_CONSTEXPR
bool
120 lt(const char_type
& __c1
, const char_type
& __c2
)
121 { return __c1
< __c2
; }
123 static _GLIBCXX14_CONSTEXPR
int
124 compare(const char_type
* __s1
, const char_type
* __s2
, std::size_t __n
);
126 static _GLIBCXX14_CONSTEXPR
std::size_t
127 length(const char_type
* __s
);
129 static _GLIBCXX14_CONSTEXPR
const char_type
*
130 find(const char_type
* __s
, std::size_t __n
, const char_type
& __a
);
132 static _GLIBCXX20_CONSTEXPR char_type
*
133 move(char_type
* __s1
, const char_type
* __s2
, std::size_t __n
);
135 static _GLIBCXX20_CONSTEXPR char_type
*
136 copy(char_type
* __s1
, const char_type
* __s2
, std::size_t __n
);
138 static _GLIBCXX20_CONSTEXPR char_type
*
139 assign(char_type
* __s
, std::size_t __n
, char_type __a
);
141 static _GLIBCXX_CONSTEXPR char_type
142 to_char_type(const int_type
& __c
)
143 { return static_cast<char_type
>(__c
); }
145 static _GLIBCXX_CONSTEXPR int_type
146 to_int_type(const char_type
& __c
)
147 { return static_cast<int_type
>(__c
); }
149 static _GLIBCXX_CONSTEXPR
bool
150 eq_int_type(const int_type
& __c1
, const int_type
& __c2
)
151 { return __c1
== __c2
; }
153 static _GLIBCXX_CONSTEXPR int_type
155 { return static_cast<int_type
>(_GLIBCXX_STDIO_EOF
); }
157 static _GLIBCXX_CONSTEXPR int_type
158 not_eof(const int_type
& __c
)
159 { return !eq_int_type(__c
, eof()) ? __c
: to_int_type(char_type()); }
162 template<typename _CharT
>
163 _GLIBCXX14_CONSTEXPR
int
164 char_traits
<_CharT
>::
165 compare(const char_type
* __s1
, const char_type
* __s2
, std::size_t __n
)
167 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
168 if (lt(__s1
[__i
], __s2
[__i
]))
170 else if (lt(__s2
[__i
], __s1
[__i
]))
175 template<typename _CharT
>
176 _GLIBCXX14_CONSTEXPR
std::size_t
177 char_traits
<_CharT
>::
178 length(const char_type
* __p
)
181 while (!eq(__p
[__i
], char_type()))
186 template<typename _CharT
>
187 _GLIBCXX14_CONSTEXPR
const typename char_traits
<_CharT
>::char_type
*
188 char_traits
<_CharT
>::
189 find(const char_type
* __s
, std::size_t __n
, const char_type
& __a
)
191 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
192 if (eq(__s
[__i
], __a
))
197 template<typename _CharT
>
199 typename char_traits
<_CharT
>::char_type
*
200 char_traits
<_CharT
>::
201 move(char_type
* __s1
, const char_type
* __s2
, std::size_t __n
)
205 #if __cplusplus >= 202002L
206 if (std::__is_constant_evaluated())
208 if (__s1
== __s2
) // unlikely, but saves a lot of work
210 #if __cpp_constexpr_dynamic_alloc
211 // The overlap detection below fails due to PR c++/89074,
212 // so use a temporary buffer instead.
213 char_type
* __tmp
= new char_type
[__n
];
214 copy(__tmp
, __s2
, __n
);
215 copy(__s1
, __tmp
, __n
);
218 const auto __end
= __s2
+ __n
- 1;
219 bool __overlap
= false;
220 for (std::size_t __i
= 0; __i
< __n
- 1; ++__i
)
222 if (__s1
+ __i
== __end
)
233 assign(__s1
[__n
], __s2
[__n
]);
238 copy(__s1
, __s2
, __n
);
243 __builtin_memmove(__s1
, __s2
, __n
* sizeof(char_type
));
247 template<typename _CharT
>
249 typename char_traits
<_CharT
>::char_type
*
250 char_traits
<_CharT
>::
251 copy(char_type
* __s1
, const char_type
* __s2
, std::size_t __n
)
253 #if __cplusplus >= 202002L
254 if (std::__is_constant_evaluated())
256 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
257 std::construct_at(__s1
+ __i
, __s2
[__i
]);
262 __builtin_memcpy(__s1
, __s2
, __n
* sizeof(char_type
));
266 template<typename _CharT
>
268 typename char_traits
<_CharT
>::char_type
*
269 char_traits
<_CharT
>::
270 assign(char_type
* __s
, std::size_t __n
, char_type __a
)
272 #if __cplusplus >= 202002L
273 if (std::__is_constant_evaluated())
275 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
276 std::construct_at(__s
+ __i
, __a
);
281 if _GLIBCXX17_CONSTEXPR (sizeof(_CharT
) == 1 && __is_trivial(_CharT
))
284 __builtin_memcpy(&__c
, __builtin_addressof(__a
), 1);
285 __builtin_memset(__s
, __c
, __n
);
289 for (std::size_t __i
= 0; __i
< __n
; ++__i
)
295 _GLIBCXX_END_NAMESPACE_VERSION
298 namespace std
_GLIBCXX_VISIBILITY(default)
300 _GLIBCXX_BEGIN_NAMESPACE_VERSION
302 #ifdef __cpp_lib_is_constant_evaluated
303 // Unofficial macro indicating P1032R1 support in C++20
304 # define __cpp_lib_constexpr_char_traits 201811L
305 #elif __cplusplus >= 201703L && _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED
306 // Unofficial macro indicating P0426R1 support in C++17
307 # define __cpp_lib_constexpr_char_traits 201611L
312 * @brief Basis for explicit traits specializations.
314 * @note For any given actual character type, this definition is
315 * probably wrong. Since this is just a thin wrapper around
316 * __gnu_cxx::char_traits, it is possible to achieve a more
317 * appropriate definition by specializing __gnu_cxx::char_traits.
319 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
320 * for advice on how to make use of this class for @a unusual character
321 * types. Also, check out include/ext/pod_char_traits.h.
323 template<typename _CharT
>
324 struct char_traits
: public __gnu_cxx::char_traits
<_CharT
>
328 /// 21.1.3.1 char_traits specializations
330 struct char_traits
<char>
332 typedef char char_type
;
333 typedef int int_type
;
334 typedef streampos pos_type
;
335 typedef streamoff off_type
;
336 typedef mbstate_t state_type
;
337 #if __cpp_lib_three_way_comparison
338 using comparison_category
= strong_ordering
;
341 static _GLIBCXX17_CONSTEXPR
void
342 assign(char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
344 #if __cpp_constexpr_dynamic_alloc
345 if (std::__is_constant_evaluated())
346 std::construct_at(__builtin_addressof(__c1
), __c2
);
352 static _GLIBCXX_CONSTEXPR
bool
353 eq(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
354 { return __c1
== __c2
; }
356 static _GLIBCXX_CONSTEXPR
bool
357 lt(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
360 return (static_cast<unsigned char>(__c1
)
361 < static_cast<unsigned char>(__c2
));
364 static _GLIBCXX17_CONSTEXPR
int
365 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
369 #if __cplusplus >= 201703L
370 if (std::__is_constant_evaluated())
372 for (size_t __i
= 0; __i
< __n
; ++__i
)
373 if (lt(__s1
[__i
], __s2
[__i
]))
375 else if (lt(__s2
[__i
], __s1
[__i
]))
380 return __builtin_memcmp(__s1
, __s2
, __n
);
383 static _GLIBCXX17_CONSTEXPR
size_t
384 length(const char_type
* __s
)
386 #if __cplusplus >= 201703L
387 if (std::__is_constant_evaluated())
388 return __gnu_cxx::char_traits
<char_type
>::length(__s
);
390 return __builtin_strlen(__s
);
393 static _GLIBCXX17_CONSTEXPR
const char_type
*
394 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
398 #if __cplusplus >= 201703L
399 if (std::__is_constant_evaluated())
400 return __gnu_cxx::char_traits
<char_type
>::find(__s
, __n
, __a
);
402 return static_cast<const char_type
*>(__builtin_memchr(__s
, __a
, __n
));
405 static _GLIBCXX20_CONSTEXPR char_type
*
406 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
410 #if __cplusplus >= 202002L
411 if (std::__is_constant_evaluated())
412 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
414 return static_cast<char_type
*>(__builtin_memmove(__s1
, __s2
, __n
));
417 static _GLIBCXX20_CONSTEXPR char_type
*
418 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
422 #if __cplusplus >= 202002L
423 if (std::__is_constant_evaluated())
424 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
426 return static_cast<char_type
*>(__builtin_memcpy(__s1
, __s2
, __n
));
429 static _GLIBCXX20_CONSTEXPR char_type
*
430 assign(char_type
* __s
, size_t __n
, char_type __a
)
434 #if __cplusplus >= 202002L
435 if (std::__is_constant_evaluated())
436 return __gnu_cxx::char_traits
<char_type
>::assign(__s
, __n
, __a
);
438 return static_cast<char_type
*>(__builtin_memset(__s
, __a
, __n
));
441 static _GLIBCXX_CONSTEXPR char_type
442 to_char_type(const int_type
& __c
) _GLIBCXX_NOEXCEPT
443 { return static_cast<char_type
>(__c
); }
445 // To keep both the byte 0xff and the eof symbol 0xffffffff
446 // from ending up as 0xffffffff.
447 static _GLIBCXX_CONSTEXPR int_type
448 to_int_type(const char_type
& __c
) _GLIBCXX_NOEXCEPT
449 { return static_cast<int_type
>(static_cast<unsigned char>(__c
)); }
451 static _GLIBCXX_CONSTEXPR
bool
452 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) _GLIBCXX_NOEXCEPT
453 { return __c1
== __c2
; }
455 static _GLIBCXX_CONSTEXPR int_type
456 eof() _GLIBCXX_NOEXCEPT
457 { return static_cast<int_type
>(_GLIBCXX_STDIO_EOF
); }
459 static _GLIBCXX_CONSTEXPR int_type
460 not_eof(const int_type
& __c
) _GLIBCXX_NOEXCEPT
461 { return (__c
== eof()) ? 0 : __c
; }
465 #ifdef _GLIBCXX_USE_WCHAR_T
466 /// 21.1.3.2 char_traits specializations
468 struct char_traits
<wchar_t>
470 typedef wchar_t char_type
;
471 typedef wint_t int_type
;
472 typedef streamoff off_type
;
473 typedef wstreampos pos_type
;
474 typedef mbstate_t state_type
;
475 #if __cpp_lib_three_way_comparison
476 using comparison_category
= strong_ordering
;
479 static _GLIBCXX17_CONSTEXPR
void
480 assign(char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
482 #if __cpp_constexpr_dynamic_alloc
483 if (std::__is_constant_evaluated())
484 std::construct_at(__builtin_addressof(__c1
), __c2
);
490 static _GLIBCXX_CONSTEXPR
bool
491 eq(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
492 { return __c1
== __c2
; }
494 static _GLIBCXX_CONSTEXPR
bool
495 lt(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
496 { return __c1
< __c2
; }
498 static _GLIBCXX17_CONSTEXPR
int
499 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
503 #if __cplusplus >= 201703L
504 if (std::__is_constant_evaluated())
505 return __gnu_cxx::char_traits
<char_type
>::compare(__s1
, __s2
, __n
);
507 return wmemcmp(__s1
, __s2
, __n
);
510 static _GLIBCXX17_CONSTEXPR
size_t
511 length(const char_type
* __s
)
513 #if __cplusplus >= 201703L
514 if (std::__is_constant_evaluated())
515 return __gnu_cxx::char_traits
<char_type
>::length(__s
);
520 static _GLIBCXX17_CONSTEXPR
const char_type
*
521 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
525 #if __cplusplus >= 201703L
526 if (std::__is_constant_evaluated())
527 return __gnu_cxx::char_traits
<char_type
>::find(__s
, __n
, __a
);
529 return wmemchr(__s
, __a
, __n
);
532 static _GLIBCXX20_CONSTEXPR char_type
*
533 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
537 #if __cplusplus >= 202002L
538 if (std::__is_constant_evaluated())
539 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
541 return wmemmove(__s1
, __s2
, __n
);
544 static _GLIBCXX20_CONSTEXPR char_type
*
545 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
549 #if __cplusplus >= 202002L
550 if (std::__is_constant_evaluated())
551 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
553 return wmemcpy(__s1
, __s2
, __n
);
556 static _GLIBCXX20_CONSTEXPR char_type
*
557 assign(char_type
* __s
, size_t __n
, char_type __a
)
561 #if __cplusplus >= 202002L
562 if (std::__is_constant_evaluated())
563 return __gnu_cxx::char_traits
<char_type
>::assign(__s
, __n
, __a
);
565 return wmemset(__s
, __a
, __n
);
568 static _GLIBCXX_CONSTEXPR char_type
569 to_char_type(const int_type
& __c
) _GLIBCXX_NOEXCEPT
570 { return char_type(__c
); }
572 static _GLIBCXX_CONSTEXPR int_type
573 to_int_type(const char_type
& __c
) _GLIBCXX_NOEXCEPT
574 { return int_type(__c
); }
576 static _GLIBCXX_CONSTEXPR
bool
577 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) _GLIBCXX_NOEXCEPT
578 { return __c1
== __c2
; }
580 static _GLIBCXX_CONSTEXPR int_type
581 eof() _GLIBCXX_NOEXCEPT
582 { return static_cast<int_type
>(WEOF
); }
584 static _GLIBCXX_CONSTEXPR int_type
585 not_eof(const int_type
& __c
) _GLIBCXX_NOEXCEPT
586 { return eq_int_type(__c
, eof()) ? 0 : __c
; }
588 #else // _GLIBCXX_USE_WCHAR_T
590 struct char_traits
<wchar_t> : public __gnu_cxx::char_traits
<wchar_t>
592 #endif //_GLIBCXX_USE_WCHAR_T
594 #ifdef _GLIBCXX_USE_CHAR8_T
596 struct char_traits
<char8_t
>
598 typedef char8_t char_type
;
599 typedef unsigned int int_type
;
600 typedef u8streampos pos_type
;
601 typedef streamoff off_type
;
602 typedef mbstate_t state_type
;
603 #if __cpp_lib_three_way_comparison
604 using comparison_category
= strong_ordering
;
607 static _GLIBCXX17_CONSTEXPR
void
608 assign(char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
610 #if __cpp_constexpr_dynamic_alloc
611 if (std::__is_constant_evaluated())
612 std::construct_at(__builtin_addressof(__c1
), __c2
);
618 static _GLIBCXX_CONSTEXPR
bool
619 eq(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
620 { return __c1
== __c2
; }
622 static _GLIBCXX_CONSTEXPR
bool
623 lt(const char_type
& __c1
, const char_type
& __c2
) _GLIBCXX_NOEXCEPT
624 { return __c1
< __c2
; }
626 static _GLIBCXX17_CONSTEXPR
int
627 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
631 #if __cplusplus >= 201703L
632 if (std::__is_constant_evaluated())
633 return __gnu_cxx::char_traits
<char_type
>::compare(__s1
, __s2
, __n
);
635 return __builtin_memcmp(__s1
, __s2
, __n
);
638 static _GLIBCXX17_CONSTEXPR
size_t
639 length(const char_type
* __s
)
641 #if __cplusplus >= 201703L
642 if (std::__is_constant_evaluated())
643 return __gnu_cxx::char_traits
<char_type
>::length(__s
);
646 while (!eq(__s
[__i
], char_type()))
651 static _GLIBCXX17_CONSTEXPR
const char_type
*
652 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
656 #if __cplusplus >= 201703L
657 if (std::__is_constant_evaluated())
658 return __gnu_cxx::char_traits
<char_type
>::find(__s
, __n
, __a
);
660 return static_cast<const char_type
*>(__builtin_memchr(__s
, __a
, __n
));
663 static _GLIBCXX20_CONSTEXPR char_type
*
664 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
668 #if __cplusplus >= 202002L
669 if (std::__is_constant_evaluated())
670 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
672 return static_cast<char_type
*>(__builtin_memmove(__s1
, __s2
, __n
));
675 static _GLIBCXX20_CONSTEXPR char_type
*
676 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
680 #if __cplusplus >= 202002L
681 if (std::__is_constant_evaluated())
682 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
684 return static_cast<char_type
*>(__builtin_memcpy(__s1
, __s2
, __n
));
687 static _GLIBCXX20_CONSTEXPR char_type
*
688 assign(char_type
* __s
, size_t __n
, char_type __a
)
692 #if __cplusplus >= 202002L
693 if (std::__is_constant_evaluated())
694 return __gnu_cxx::char_traits
<char_type
>::assign(__s
, __n
, __a
);
696 return static_cast<char_type
*>(__builtin_memset(__s
, __a
, __n
));
699 static _GLIBCXX_CONSTEXPR char_type
700 to_char_type(const int_type
& __c
) _GLIBCXX_NOEXCEPT
701 { return char_type(__c
); }
703 static _GLIBCXX_CONSTEXPR int_type
704 to_int_type(const char_type
& __c
) _GLIBCXX_NOEXCEPT
705 { return int_type(__c
); }
707 static _GLIBCXX_CONSTEXPR
bool
708 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) _GLIBCXX_NOEXCEPT
709 { return __c1
== __c2
; }
711 static _GLIBCXX_CONSTEXPR int_type
712 eof() _GLIBCXX_NOEXCEPT
713 { return static_cast<int_type
>(-1); }
715 static _GLIBCXX_CONSTEXPR int_type
716 not_eof(const int_type
& __c
) _GLIBCXX_NOEXCEPT
717 { return eq_int_type(__c
, eof()) ? 0 : __c
; }
719 #endif //_GLIBCXX_USE_CHAR8_T
721 _GLIBCXX_END_NAMESPACE_VERSION
724 #if __cplusplus >= 201103L
728 namespace std
_GLIBCXX_VISIBILITY(default)
730 _GLIBCXX_BEGIN_NAMESPACE_VERSION
733 struct char_traits
<char16_t
>
735 typedef char16_t char_type
;
736 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
737 typedef uint_least16_t int_type
;
738 #elif defined __UINT_LEAST16_TYPE__
739 typedef __UINT_LEAST16_TYPE__ int_type
;
741 typedef make_unsigned
<char16_t
>::type int_type
;
743 typedef streamoff off_type
;
744 typedef u16streampos pos_type
;
745 typedef mbstate_t state_type
;
746 #if __cpp_lib_three_way_comparison
747 using comparison_category
= strong_ordering
;
750 static _GLIBCXX17_CONSTEXPR
void
751 assign(char_type
& __c1
, const char_type
& __c2
) noexcept
753 #if __cpp_constexpr_dynamic_alloc
754 if (std::__is_constant_evaluated())
755 std::construct_at(__builtin_addressof(__c1
), __c2
);
761 static constexpr bool
762 eq(const char_type
& __c1
, const char_type
& __c2
) noexcept
763 { return __c1
== __c2
; }
765 static constexpr bool
766 lt(const char_type
& __c1
, const char_type
& __c2
) noexcept
767 { return __c1
< __c2
; }
769 static _GLIBCXX17_CONSTEXPR
int
770 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
772 for (size_t __i
= 0; __i
< __n
; ++__i
)
773 if (lt(__s1
[__i
], __s2
[__i
]))
775 else if (lt(__s2
[__i
], __s1
[__i
]))
780 static _GLIBCXX17_CONSTEXPR
size_t
781 length(const char_type
* __s
)
784 while (!eq(__s
[__i
], char_type()))
789 static _GLIBCXX17_CONSTEXPR
const char_type
*
790 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
792 for (size_t __i
= 0; __i
< __n
; ++__i
)
793 if (eq(__s
[__i
], __a
))
798 static _GLIBCXX20_CONSTEXPR char_type
*
799 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
803 #if __cplusplus >= 202002L
804 if (std::__is_constant_evaluated())
805 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
807 return (static_cast<char_type
*>
808 (__builtin_memmove(__s1
, __s2
, __n
* sizeof(char_type
))));
811 static _GLIBCXX20_CONSTEXPR char_type
*
812 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
816 #if __cplusplus >= 202002L
817 if (std::__is_constant_evaluated())
818 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
820 return (static_cast<char_type
*>
821 (__builtin_memcpy(__s1
, __s2
, __n
* sizeof(char_type
))));
824 static _GLIBCXX20_CONSTEXPR char_type
*
825 assign(char_type
* __s
, size_t __n
, char_type __a
)
827 for (size_t __i
= 0; __i
< __n
; ++__i
)
828 assign(__s
[__i
], __a
);
832 static constexpr char_type
833 to_char_type(const int_type
& __c
) noexcept
834 { return char_type(__c
); }
836 static constexpr int_type
837 to_int_type(const char_type
& __c
) noexcept
838 { return __c
== eof() ? int_type(0xfffd) : int_type(__c
); }
840 static constexpr bool
841 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) noexcept
842 { return __c1
== __c2
; }
844 static constexpr int_type
846 { return static_cast<int_type
>(-1); }
848 static constexpr int_type
849 not_eof(const int_type
& __c
) noexcept
850 { return eq_int_type(__c
, eof()) ? 0 : __c
; }
854 struct char_traits
<char32_t
>
856 typedef char32_t char_type
;
857 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
858 typedef uint_least32_t int_type
;
859 #elif defined __UINT_LEAST32_TYPE__
860 typedef __UINT_LEAST32_TYPE__ int_type
;
862 typedef make_unsigned
<char32_t
>::type int_type
;
864 typedef streamoff off_type
;
865 typedef u32streampos pos_type
;
866 typedef mbstate_t state_type
;
867 #if __cpp_lib_three_way_comparison
868 using comparison_category
= strong_ordering
;
871 static _GLIBCXX17_CONSTEXPR
void
872 assign(char_type
& __c1
, const char_type
& __c2
) noexcept
874 #if __cpp_constexpr_dynamic_alloc
875 if (std::__is_constant_evaluated())
876 std::construct_at(__builtin_addressof(__c1
), __c2
);
882 static constexpr bool
883 eq(const char_type
& __c1
, const char_type
& __c2
) noexcept
884 { return __c1
== __c2
; }
886 static constexpr bool
887 lt(const char_type
& __c1
, const char_type
& __c2
) noexcept
888 { return __c1
< __c2
; }
890 static _GLIBCXX17_CONSTEXPR
int
891 compare(const char_type
* __s1
, const char_type
* __s2
, size_t __n
)
893 for (size_t __i
= 0; __i
< __n
; ++__i
)
894 if (lt(__s1
[__i
], __s2
[__i
]))
896 else if (lt(__s2
[__i
], __s1
[__i
]))
901 static _GLIBCXX17_CONSTEXPR
size_t
902 length(const char_type
* __s
)
905 while (!eq(__s
[__i
], char_type()))
910 static _GLIBCXX17_CONSTEXPR
const char_type
*
911 find(const char_type
* __s
, size_t __n
, const char_type
& __a
)
913 for (size_t __i
= 0; __i
< __n
; ++__i
)
914 if (eq(__s
[__i
], __a
))
919 static _GLIBCXX20_CONSTEXPR char_type
*
920 move(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
924 #if __cplusplus >= 202002L
925 if (std::__is_constant_evaluated())
926 return __gnu_cxx::char_traits
<char_type
>::move(__s1
, __s2
, __n
);
928 return (static_cast<char_type
*>
929 (__builtin_memmove(__s1
, __s2
, __n
* sizeof(char_type
))));
932 static _GLIBCXX20_CONSTEXPR char_type
*
933 copy(char_type
* __s1
, const char_type
* __s2
, size_t __n
)
937 #if __cplusplus >= 202002L
938 if (std::__is_constant_evaluated())
939 return __gnu_cxx::char_traits
<char_type
>::copy(__s1
, __s2
, __n
);
941 return (static_cast<char_type
*>
942 (__builtin_memcpy(__s1
, __s2
, __n
* sizeof(char_type
))));
945 static _GLIBCXX20_CONSTEXPR char_type
*
946 assign(char_type
* __s
, size_t __n
, char_type __a
)
948 for (size_t __i
= 0; __i
< __n
; ++__i
)
949 assign(__s
[__i
], __a
);
953 static constexpr char_type
954 to_char_type(const int_type
& __c
) noexcept
955 { return char_type(__c
); }
957 static constexpr int_type
958 to_int_type(const char_type
& __c
) noexcept
959 { return int_type(__c
); }
961 static constexpr bool
962 eq_int_type(const int_type
& __c1
, const int_type
& __c2
) noexcept
963 { return __c1
== __c2
; }
965 static constexpr int_type
967 { return static_cast<int_type
>(-1); }
969 static constexpr int_type
970 not_eof(const int_type
& __c
) noexcept
971 { return eq_int_type(__c
, eof()) ? 0 : __c
; }
974 #if __cpp_lib_three_way_comparison
977 template<typename _ChTraits
>
979 __char_traits_cmp_cat(int __cmp
) noexcept
981 if constexpr (requires
{ typename
_ChTraits::comparison_category
; })
983 using _Cat
= typename
_ChTraits::comparison_category
;
984 static_assert( !is_void_v
<common_comparison_category_t
<_Cat
>> );
985 return static_cast<_Cat
>(__cmp
<=> 0);
988 return static_cast<weak_ordering
>(__cmp
<=> 0);
990 } // namespace __detail
993 _GLIBCXX_END_NAMESPACE_VERSION
998 #endif // _CHAR_TRAITS_H