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
53namespace __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(c1: __c, c2: eof()) ? __c : to_int_type(c: 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(c1: __s1[__i], c2: __s2[__i]))
174 return -1;
175 else if (lt(c1: __s2[__i], c2: __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(c1: __p[__i], c2: 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(c1: __s[__i], c2: __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
307namespace 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(c1: __s1[__i], c2: __s2[__i]))
383 return -1;
384 else if (lt(c1: __s2[__i], c2: __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(p: __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(p: __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, c: __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, c: __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(c1: __c, c2: 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
737namespace 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(c1: __s1[__i], c2: __s2[__i]))
783 return -1;
784 else if (lt(c1: __s2[__i], c2: __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(c1: __s[__i], c2: 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(c1: __s[__i], c2: __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(c1&: __s[__i], c2: __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(c1: __c, c2: 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(c1: __s1[__i], c2: __s2[__i]))
904 return -1;
905 else if (lt(c1: __s2[__i], c2: __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(c1: __s[__i], c2: 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(c1: __s[__i], c2: __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(c1&: __s[__i], c2: __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(c1: __c, c2: 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