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