1// Character Traits for use by standard string and iostream -*- C++ -*-
2
3// Copyright (C) 1997-2024 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/c++config.h>
40
41#if _GLIBCXX_HOSTED
42# include <bits/postypes.h> // For streampos
43#endif // HOSTED
44
45#ifdef _GLIBCXX_USE_WCHAR_T
46# include <cwchar> // For WEOF, wmemmove, wmemset, etc.
47#endif // USE_WCHAR_T
48
49#if __cplusplus >= 201103L
50# include <type_traits>
51#if !defined __UINT_LEAST16_TYPE__ || !defined __UINT_LEAST32_TYPE__
52# include <cstdint>
53#endif
54#endif
55#if __cplusplus >= 202002L
56# include <compare>
57# include <bits/stl_construct.h>
58#endif
59
60#ifndef _GLIBCXX_ALWAYS_INLINE
61# define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
62#endif
63
64namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
65{
66_GLIBCXX_BEGIN_NAMESPACE_VERSION
67
68#pragma GCC diagnostic push
69#pragma GCC diagnostic ignored "-Wstringop-overflow"
70#pragma GCC diagnostic ignored "-Wstringop-overread"
71#pragma GCC diagnostic ignored "-Warray-bounds"
72
73 /**
74 * @brief Mapping from character type to associated types.
75 *
76 * @note This is an implementation class for the generic version
77 * of char_traits. It defines int_type, off_type, pos_type, and
78 * state_type. By default these are unsigned long, streamoff,
79 * streampos, and mbstate_t. Users who need a different set of
80 * types, but who don't need to change the definitions of any function
81 * defined in char_traits, can specialize __gnu_cxx::_Char_types
82 * while leaving __gnu_cxx::char_traits alone. */
83 template<typename _CharT>
84 struct _Char_types
85 {
86 typedef unsigned long int_type;
87#if _GLIBCXX_HOSTED
88 typedef std::streampos pos_type;
89 typedef std::streamoff off_type;
90 typedef std::mbstate_t state_type;
91#endif // HOSTED
92 };
93
94
95 /**
96 * @brief Base class used to implement std::char_traits.
97 *
98 * @note For any given actual character type, this definition is
99 * probably wrong. (Most of the member functions are likely to be
100 * right, but the int_type and state_type typedefs, and the eof()
101 * member function, are likely to be wrong.) The reason this class
102 * exists is so users can specialize it. Classes in namespace std
103 * may not be specialized for fundamental types, but classes in
104 * namespace __gnu_cxx may be.
105 *
106 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
107 * for advice on how to make use of this class for @a unusual character
108 * types. Also, check out include/ext/pod_char_traits.h.
109 */
110 template<typename _CharT>
111 struct char_traits
112 {
113 typedef _CharT char_type;
114 typedef typename _Char_types<_CharT>::int_type int_type;
115#if _GLIBCXX_HOSTED
116 typedef typename _Char_types<_CharT>::pos_type pos_type;
117 typedef typename _Char_types<_CharT>::off_type off_type;
118 typedef typename _Char_types<_CharT>::state_type state_type;
119#endif // HOSTED
120#if __cpp_lib_three_way_comparison
121 using comparison_category = std::strong_ordering;
122#endif
123
124 static _GLIBCXX14_CONSTEXPR void
125 assign(char_type& __c1, const char_type& __c2)
126 {
127#if __cpp_constexpr_dynamic_alloc
128 if (std::__is_constant_evaluated())
129 std::construct_at(__builtin_addressof(__c1), __c2);
130 else
131#endif
132 __c1 = __c2;
133 }
134
135 static _GLIBCXX_CONSTEXPR bool
136 eq(const char_type& __c1, const char_type& __c2)
137 { return __c1 == __c2; }
138
139 static _GLIBCXX_CONSTEXPR bool
140 lt(const char_type& __c1, const char_type& __c2)
141 { return __c1 < __c2; }
142
143 static _GLIBCXX14_CONSTEXPR int
144 compare(const char_type* __s1, const char_type* __s2, std::size_t __n);
145
146 static _GLIBCXX14_CONSTEXPR std::size_t
147 length(const char_type* __s);
148
149 static _GLIBCXX14_CONSTEXPR const char_type*
150 find(const char_type* __s, std::size_t __n, const char_type& __a);
151
152 static _GLIBCXX20_CONSTEXPR char_type*
153 move(char_type* __s1, const char_type* __s2, std::size_t __n);
154
155 static _GLIBCXX20_CONSTEXPR char_type*
156 copy(char_type* __s1, const char_type* __s2, std::size_t __n);
157
158 static _GLIBCXX20_CONSTEXPR char_type*
159 assign(char_type* __s, std::size_t __n, char_type __a);
160
161 static _GLIBCXX_CONSTEXPR char_type
162 to_char_type(const int_type& __c)
163 { return static_cast<char_type>(__c); }
164
165 static _GLIBCXX_CONSTEXPR int_type
166 to_int_type(const char_type& __c)
167 { return static_cast<int_type>(__c); }
168
169 static _GLIBCXX_CONSTEXPR bool
170 eq_int_type(const int_type& __c1, const int_type& __c2)
171 { return __c1 == __c2; }
172
173#ifdef _GLIBCXX_STDIO_EOF
174 static _GLIBCXX_CONSTEXPR int_type
175 eof()
176 { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
177
178 static _GLIBCXX_CONSTEXPR int_type
179 not_eof(const int_type& __c)
180 { return !eq_int_type(c1: __c, c2: eof()) ? __c : to_int_type(c: char_type()); }
181#endif // defined(_GLIBCXX_STDIO_EOF)
182 };
183
184 template<typename _CharT>
185 _GLIBCXX14_CONSTEXPR int
186 char_traits<_CharT>::
187 compare(const char_type* __s1, const char_type* __s2, std::size_t __n)
188 {
189 for (std::size_t __i = 0; __i < __n; ++__i)
190 if (lt(c1: __s1[__i], c2: __s2[__i]))
191 return -1;
192 else if (lt(c1: __s2[__i], c2: __s1[__i]))
193 return 1;
194 return 0;
195 }
196
197 template<typename _CharT>
198 _GLIBCXX14_CONSTEXPR std::size_t
199 char_traits<_CharT>::
200 length(const char_type* __p)
201 {
202 std::size_t __i = 0;
203 while (!eq(c1: __p[__i], c2: char_type()))
204 ++__i;
205 return __i;
206 }
207
208 template<typename _CharT>
209 _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type*
210 char_traits<_CharT>::
211 find(const char_type* __s, std::size_t __n, const char_type& __a)
212 {
213 for (std::size_t __i = 0; __i < __n; ++__i)
214 if (eq(c1: __s[__i], c2: __a))
215 return __s + __i;
216 return 0;
217 }
218
219 template<typename _CharT>
220 _GLIBCXX20_CONSTEXPR
221 typename char_traits<_CharT>::char_type*
222 char_traits<_CharT>::
223 move(char_type* __s1, const char_type* __s2, std::size_t __n)
224 {
225 if (__n == 0)
226 return __s1;
227#if __cplusplus >= 202002L
228 if (std::__is_constant_evaluated())
229 {
230 // Use __builtin_constant_p to avoid comparing unrelated pointers.
231 if (__builtin_constant_p(__s2 < __s1)
232 && __s1 > __s2 && __s1 < (__s2 + __n))
233 {
234 do
235 {
236 --__n;
237 assign(__s1[__n], __s2[__n]);
238 }
239 while (__n > 0);
240 }
241 else
242 copy(__s1, __s2, __n);
243 return __s1;
244 }
245#endif
246 __builtin_memmove(__s1, __s2, __n * sizeof(char_type));
247 return __s1;
248 }
249
250 template<typename _CharT>
251 _GLIBCXX20_CONSTEXPR
252 typename char_traits<_CharT>::char_type*
253 char_traits<_CharT>::
254 copy(char_type* __s1, const char_type* __s2, std::size_t __n)
255 {
256 if (__n == 0)
257 return __s1;
258#if __cplusplus >= 202002L
259 if (std::__is_constant_evaluated())
260 {
261 for (std::size_t __i = 0; __i < __n; ++__i)
262 std::construct_at(__s1 + __i, __s2[__i]);
263 return __s1;
264 }
265#endif
266 __builtin_memcpy(__s1, __s2, __n * sizeof(char_type));
267 return __s1;
268 }
269
270 template<typename _CharT>
271 _GLIBCXX20_CONSTEXPR
272 typename char_traits<_CharT>::char_type*
273 char_traits<_CharT>::
274 assign(char_type* __s, std::size_t __n, char_type __a)
275 {
276#if __cplusplus >= 202002L
277 if (std::__is_constant_evaluated())
278 {
279 for (std::size_t __i = 0; __i < __n; ++__i)
280 std::construct_at(__s + __i, __a);
281 return __s;
282 }
283#endif
284
285 if _GLIBCXX17_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT))
286 {
287 if (__n)
288 {
289 unsigned char __c;
290 __builtin_memcpy(&__c, __builtin_addressof(__a), 1);
291 __builtin_memset(__s, __c, __n);
292 }
293 }
294 else
295 {
296 for (std::size_t __i = 0; __i < __n; ++__i)
297 __s[__i] = __a;
298 }
299 return __s;
300 }
301
302_GLIBCXX_END_NAMESPACE_VERSION
303} // namespace
304
305namespace std _GLIBCXX_VISIBILITY(default)
306{
307_GLIBCXX_BEGIN_NAMESPACE_VERSION
308
309 // 21.1
310 /**
311 * @brief Basis for explicit traits specializations.
312 *
313 * @note For any given actual character type, this definition is
314 * probably wrong. Since this is just a thin wrapper around
315 * __gnu_cxx::char_traits, it is possible to achieve a more
316 * appropriate definition by specializing __gnu_cxx::char_traits.
317 *
318 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
319 * for advice on how to make use of this class for @a unusual character
320 * types. Also, check out include/ext/pod_char_traits.h.
321 */
322 template<typename _CharT>
323 struct char_traits : public __gnu_cxx::char_traits<_CharT>
324 { };
325
326
327 /// 21.1.3.1 char_traits specializations
328 template<>
329 struct char_traits<char>
330 {
331 typedef char char_type;
332 typedef int int_type;
333#if _GLIBCXX_HOSTED
334 typedef streampos pos_type;
335 typedef streamoff off_type;
336 typedef mbstate_t state_type;
337#endif // HOSTED
338#if __cpp_lib_three_way_comparison
339 using comparison_category = strong_ordering;
340#endif
341
342 static _GLIBCXX17_CONSTEXPR void
343 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
344 {
345#if __cpp_constexpr_dynamic_alloc
346 if (std::__is_constant_evaluated())
347 std::construct_at(location: __builtin_addressof(__c1), args: __c2);
348 else
349#endif
350 __c1 = __c2;
351 }
352
353 static _GLIBCXX_CONSTEXPR bool
354 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
355 { return __c1 == __c2; }
356
357 static _GLIBCXX_CONSTEXPR bool
358 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
359 {
360 // LWG 467.
361 return (static_cast<unsigned char>(__c1)
362 < static_cast<unsigned char>(__c2));
363 }
364
365 static _GLIBCXX17_CONSTEXPR int
366 compare(const char_type* __s1, const char_type* __s2, size_t __n)
367 {
368 if (__n == 0)
369 return 0;
370#if __cplusplus >= 201703L
371 if (std::__is_constant_evaluated())
372 {
373 for (size_t __i = 0; __i < __n; ++__i)
374 if (lt(c1: __s1[__i], c2: __s2[__i]))
375 return -1;
376 else if (lt(c1: __s2[__i], c2: __s1[__i]))
377 return 1;
378 return 0;
379 }
380#endif
381 return __builtin_memcmp(__s1, __s2, __n);
382 }
383
384 static _GLIBCXX17_CONSTEXPR size_t
385 length(const char_type* __s)
386 {
387#if __cplusplus >= 201703L
388 if (std::__is_constant_evaluated())
389 return __gnu_cxx::char_traits<char_type>::length(p: __s);
390#endif
391 return __builtin_strlen(__s);
392 }
393
394 static _GLIBCXX17_CONSTEXPR const char_type*
395 find(const char_type* __s, size_t __n, const char_type& __a)
396 {
397 if (__n == 0)
398 return 0;
399#if __cplusplus >= 201703L
400 if (std::__is_constant_evaluated())
401 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
402#endif
403 return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
404 }
405
406 static _GLIBCXX20_CONSTEXPR char_type*
407 move(char_type* __s1, const char_type* __s2, size_t __n)
408 {
409 if (__n == 0)
410 return __s1;
411#if __cplusplus >= 202002L
412 if (std::__is_constant_evaluated())
413 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
414#endif
415 return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
416 }
417
418 static _GLIBCXX20_CONSTEXPR char_type*
419 copy(char_type* __s1, const char_type* __s2, size_t __n)
420 {
421 if (__n == 0)
422 return __s1;
423#if __cplusplus >= 202002L
424 if (std::__is_constant_evaluated())
425 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
426#endif
427 return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
428 }
429
430 static _GLIBCXX20_CONSTEXPR char_type*
431 assign(char_type* __s, size_t __n, char_type __a)
432 {
433 if (__n == 0)
434 return __s;
435#if __cplusplus >= 202002L
436 if (std::__is_constant_evaluated())
437 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
438#endif
439 return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
440 }
441
442 static _GLIBCXX_CONSTEXPR char_type
443 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
444 { return static_cast<char_type>(__c); }
445
446 // To keep both the byte 0xff and the eof symbol 0xffffffff
447 // from ending up as 0xffffffff.
448 static _GLIBCXX_CONSTEXPR int_type
449 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
450 { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
451
452 static _GLIBCXX_CONSTEXPR bool
453 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
454 { return __c1 == __c2; }
455
456#ifdef _GLIBCXX_STDIO_EOF
457 static _GLIBCXX_CONSTEXPR int_type
458 eof() _GLIBCXX_NOEXCEPT
459 { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
460
461 static _GLIBCXX_CONSTEXPR int_type
462 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
463 { return (__c == eof()) ? 0 : __c; }
464#endif // defined(_GLIBCXX_STDIO_EOF)
465 };
466
467
468#ifdef _GLIBCXX_USE_WCHAR_T
469 /// 21.1.3.2 char_traits specializations
470 template<>
471 struct char_traits<wchar_t>
472 {
473 typedef wchar_t char_type;
474 typedef wint_t int_type;
475#if _GLIBCXX_HOSTED
476 typedef streamoff off_type;
477 typedef wstreampos pos_type;
478 typedef mbstate_t state_type;
479#endif // HOSTED
480#if __cpp_lib_three_way_comparison
481 using comparison_category = strong_ordering;
482#endif
483
484 static _GLIBCXX17_CONSTEXPR void
485 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
486 {
487#if __cpp_constexpr_dynamic_alloc
488 if (std::__is_constant_evaluated())
489 std::construct_at(location: __builtin_addressof(__c1), args: __c2);
490 else
491#endif
492 __c1 = __c2;
493 }
494
495 static _GLIBCXX_CONSTEXPR bool
496 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
497 { return __c1 == __c2; }
498
499 static _GLIBCXX_CONSTEXPR bool
500 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
501 { return __c1 < __c2; }
502
503 static _GLIBCXX17_CONSTEXPR int
504 compare(const char_type* __s1, const char_type* __s2, size_t __n)
505 {
506 if (__n == 0)
507 return 0;
508#if __cplusplus >= 201703L
509 if (std::__is_constant_evaluated())
510 return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
511#endif
512 return wmemcmp(__s1, __s2, __n);
513 }
514
515 static _GLIBCXX17_CONSTEXPR size_t
516 length(const char_type* __s)
517 {
518#if __cplusplus >= 201703L
519 if (std::__is_constant_evaluated())
520 return __gnu_cxx::char_traits<char_type>::length(p: __s);
521#endif
522 return wcslen(__s);
523 }
524
525 static _GLIBCXX17_CONSTEXPR const char_type*
526 find(const char_type* __s, size_t __n, const char_type& __a)
527 {
528 if (__n == 0)
529 return 0;
530#if __cplusplus >= 201703L
531 if (std::__is_constant_evaluated())
532 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
533#endif
534 return wmemchr(__s, c: __a, __n);
535 }
536
537 static _GLIBCXX20_CONSTEXPR char_type*
538 move(char_type* __s1, const char_type* __s2, size_t __n)
539 {
540 if (__n == 0)
541 return __s1;
542#if __cplusplus >= 202002L
543 if (std::__is_constant_evaluated())
544 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
545#endif
546 return wmemmove(__s1, __s2, __n);
547 }
548
549 static _GLIBCXX20_CONSTEXPR char_type*
550 copy(char_type* __s1, const char_type* __s2, size_t __n)
551 {
552 if (__n == 0)
553 return __s1;
554#if __cplusplus >= 202002L
555 if (std::__is_constant_evaluated())
556 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
557#endif
558 return wmemcpy(__s1, __s2, __n);
559 }
560
561 static _GLIBCXX20_CONSTEXPR char_type*
562 assign(char_type* __s, size_t __n, char_type __a)
563 {
564 if (__n == 0)
565 return __s;
566#if __cplusplus >= 202002L
567 if (std::__is_constant_evaluated())
568 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
569#endif
570 return wmemset(__s, c: __a, __n);
571 }
572
573 static _GLIBCXX_CONSTEXPR char_type
574 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
575 { return char_type(__c); }
576
577 static _GLIBCXX_CONSTEXPR int_type
578 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
579 { return int_type(__c); }
580
581 static _GLIBCXX_CONSTEXPR bool
582 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
583 { return __c1 == __c2; }
584
585#if _GLIBCXX_HOSTED
586 static _GLIBCXX_CONSTEXPR int_type
587 eof() _GLIBCXX_NOEXCEPT
588 { return static_cast<int_type>(WEOF); }
589
590 static _GLIBCXX_CONSTEXPR int_type
591 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
592 { return eq_int_type(c1: __c, c2: eof()) ? 0 : __c; }
593#endif // HOSTED
594 };
595#else // _GLIBCXX_USE_WCHAR_T
596 template<>
597 struct char_traits<wchar_t> : public __gnu_cxx::char_traits<wchar_t>
598 { };
599#endif //_GLIBCXX_USE_WCHAR_T
600
601#ifdef _GLIBCXX_USE_CHAR8_T
602 template<>
603 struct char_traits<char8_t>
604 {
605 typedef char8_t char_type;
606 typedef unsigned int int_type;
607#if _GLIBCXX_HOSTED
608 typedef u8streampos pos_type;
609 typedef streamoff off_type;
610 typedef mbstate_t state_type;
611#endif // HOSTED
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(location: __builtin_addressof(__c1), args: __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(p: __s);
653#endif
654 size_t __i = 0;
655 while (!eq(c1: __s[__i], c2: 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#if _GLIBCXX_HOSTED
721 static _GLIBCXX_CONSTEXPR int_type
722 eof() _GLIBCXX_NOEXCEPT
723 { return static_cast<int_type>(-1); }
724
725 static _GLIBCXX_CONSTEXPR int_type
726 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
727 { return eq_int_type(c1: __c, c2: eof()) ? 0 : __c; }
728#endif // HOSTED
729 };
730#endif //_GLIBCXX_USE_CHAR8_T
731
732_GLIBCXX_END_NAMESPACE_VERSION
733} // namespace
734
735#if __cplusplus >= 201103L
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 __UINT_LEAST16_TYPE__
746 typedef __UINT_LEAST16_TYPE__ int_type;
747#else
748 typedef uint_least16_t int_type;
749#endif
750#if _GLIBCXX_HOSTED
751 typedef streamoff off_type;
752 typedef u16streampos pos_type;
753 typedef mbstate_t state_type;
754#endif // HOSTED
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(location: __builtin_addressof(__c1), args: __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 bool
846 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
847 { return __c1 == __c2; }
848
849#if _GLIBCXX_HOSTED
850 static constexpr int_type
851 to_int_type(const char_type& __c) noexcept
852 { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
853
854 static constexpr int_type
855 eof() noexcept
856 { return static_cast<int_type>(-1); }
857
858 static constexpr int_type
859 not_eof(const int_type& __c) noexcept
860 { return eq_int_type(c1: __c, c2: eof()) ? 0 : __c; }
861#else // !HOSTED
862 static constexpr int_type
863 to_int_type(const char_type& __c) noexcept
864 { return int_type(__c); }
865#endif // !HOSTED
866 };
867
868 template<>
869 struct char_traits<char32_t>
870 {
871 typedef char32_t char_type;
872#ifdef __UINT_LEAST32_TYPE__
873 typedef __UINT_LEAST32_TYPE__ int_type;
874#else
875 typedef uint_least32_t int_type;
876#endif
877#if _GLIBCXX_HOSTED
878 typedef streamoff off_type;
879 typedef u32streampos pos_type;
880 typedef mbstate_t state_type;
881#endif // HOSTED
882#if __cpp_lib_three_way_comparison
883 using comparison_category = strong_ordering;
884#endif
885
886 static _GLIBCXX17_CONSTEXPR void
887 assign(char_type& __c1, const char_type& __c2) noexcept
888 {
889#if __cpp_constexpr_dynamic_alloc
890 if (std::__is_constant_evaluated())
891 std::construct_at(location: __builtin_addressof(__c1), args: __c2);
892 else
893#endif
894 __c1 = __c2;
895 }
896
897 static constexpr bool
898 eq(const char_type& __c1, const char_type& __c2) noexcept
899 { return __c1 == __c2; }
900
901 static constexpr bool
902 lt(const char_type& __c1, const char_type& __c2) noexcept
903 { return __c1 < __c2; }
904
905 static _GLIBCXX17_CONSTEXPR int
906 compare(const char_type* __s1, const char_type* __s2, size_t __n)
907 {
908 for (size_t __i = 0; __i < __n; ++__i)
909 if (lt(c1: __s1[__i], c2: __s2[__i]))
910 return -1;
911 else if (lt(c1: __s2[__i], c2: __s1[__i]))
912 return 1;
913 return 0;
914 }
915
916 static _GLIBCXX17_CONSTEXPR size_t
917 length(const char_type* __s)
918 {
919 size_t __i = 0;
920 while (!eq(c1: __s[__i], c2: char_type()))
921 ++__i;
922 return __i;
923 }
924
925 static _GLIBCXX17_CONSTEXPR const char_type*
926 find(const char_type* __s, size_t __n, const char_type& __a)
927 {
928 for (size_t __i = 0; __i < __n; ++__i)
929 if (eq(c1: __s[__i], c2: __a))
930 return __s + __i;
931 return 0;
932 }
933
934 static _GLIBCXX20_CONSTEXPR char_type*
935 move(char_type* __s1, const char_type* __s2, size_t __n)
936 {
937 if (__n == 0)
938 return __s1;
939#if __cplusplus >= 202002L
940 if (std::__is_constant_evaluated())
941 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
942#endif
943 return (static_cast<char_type*>
944 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
945 }
946
947 static _GLIBCXX20_CONSTEXPR char_type*
948 copy(char_type* __s1, const char_type* __s2, size_t __n)
949 {
950 if (__n == 0)
951 return __s1;
952#if __cplusplus >= 202002L
953 if (std::__is_constant_evaluated())
954 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
955#endif
956 return (static_cast<char_type*>
957 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
958 }
959
960 static _GLIBCXX20_CONSTEXPR char_type*
961 assign(char_type* __s, size_t __n, char_type __a)
962 {
963 for (size_t __i = 0; __i < __n; ++__i)
964 assign(c1&: __s[__i], c2: __a);
965 return __s;
966 }
967
968 static constexpr char_type
969 to_char_type(const int_type& __c) noexcept
970 { return char_type(__c); }
971
972 static constexpr int_type
973 to_int_type(const char_type& __c) noexcept
974 { return int_type(__c); }
975
976 static constexpr bool
977 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
978 { return __c1 == __c2; }
979
980#if _GLIBCXX_HOSTED
981 static constexpr int_type
982 eof() noexcept
983 { return static_cast<int_type>(-1); }
984
985 static constexpr int_type
986 not_eof(const int_type& __c) noexcept
987 { return eq_int_type(c1: __c, c2: eof()) ? 0 : __c; }
988#endif // HOSTED
989 };
990
991#if __cpp_lib_three_way_comparison
992 namespace __detail
993 {
994 template<typename _ChTraits>
995 constexpr auto
996 __char_traits_cmp_cat(int __cmp) noexcept
997 {
998 if constexpr (requires { typename _ChTraits::comparison_category; })
999 {
1000 using _Cat = typename _ChTraits::comparison_category;
1001 static_assert( !is_void_v<common_comparison_category_t<_Cat>> );
1002 return static_cast<_Cat>(__cmp <=> 0);
1003 }
1004 else
1005 return static_cast<weak_ordering>(__cmp <=> 0);
1006 }
1007 } // namespace __detail
1008#endif // C++20
1009
1010#pragma GCC diagnostic pop
1011
1012_GLIBCXX_END_NAMESPACE_VERSION
1013} // namespace
1014
1015#endif // C++11
1016
1017#endif // _CHAR_TRAITS_H
1018