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-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>
85 {
86 typedef unsigned long int_type;
87#if _GLIBCXX_HOSTED
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>
112 {
113 typedef _CharT char_type;
114 typedef typename _Char_types<_CharT>::int_type int_type;
115#if _GLIBCXX_HOSTED
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(__c, eof()) ? __c : to_int_type(char_type()); }
181#endif // defined(_GLIBCXX_STDIO_EOF)
182 };
183
184 template<typename _CharT>
185 _GLIBCXX14_CONSTEXPR int
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(__s1[__i], __s2[__i]))
191 return -1;
192 else if (lt(__s2[__i], __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(__p[__i], 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(__s[__i], __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(__builtin_addressof(__c1), __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(__s1[__i], __s2[__i]))
375 return -1;
376 else if (lt(__s2[__i], __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())
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(__builtin_addressof(__c1), __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())
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, __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, __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(__c, 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(__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())
653#endif
654 return __builtin_strlen((const char*)__s);
655 }
656
657 static _GLIBCXX17_CONSTEXPR const char_type*
658 find(const char_type* __s, size_t __n, const char_type& __a)
659 {
660 if (__n == 0)
661 return 0;
662#if __cplusplus >= 201703L
663 if (std::__is_constant_evaluated())
664 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
665#endif
666 return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
667 }
668
669 static _GLIBCXX20_CONSTEXPR char_type*
670 move(char_type* __s1, const char_type* __s2, size_t __n)
671 {
672 if (__n == 0)
673 return __s1;
674#if __cplusplus >= 202002L
675 if (std::__is_constant_evaluated())
676 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
677#endif
678 return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
679 }
680
681 static _GLIBCXX20_CONSTEXPR char_type*
682 copy(char_type* __s1, const char_type* __s2, size_t __n)
683 {
684 if (__n == 0)
685 return __s1;
686#if __cplusplus >= 202002L
687 if (std::__is_constant_evaluated())
688 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
689#endif
690 return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
691 }
692
693 static _GLIBCXX20_CONSTEXPR char_type*
694 assign(char_type* __s, size_t __n, char_type __a)
695 {
696 if (__n == 0)
697 return __s;
698#if __cplusplus >= 202002L
699 if (std::__is_constant_evaluated())
700 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
701#endif
702 return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
703 }
704
705 static _GLIBCXX_CONSTEXPR char_type
706 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
707 { return char_type(__c); }
708
709 static _GLIBCXX_CONSTEXPR int_type
710 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
711 { return int_type(__c); }
712
713 static _GLIBCXX_CONSTEXPR bool
714 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
715 { return __c1 == __c2; }
716
717#if _GLIBCXX_HOSTED
718 static _GLIBCXX_CONSTEXPR int_type
719 eof() _GLIBCXX_NOEXCEPT
720 { return static_cast<int_type>(-1); }
721
722 static _GLIBCXX_CONSTEXPR int_type
723 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
724 { return eq_int_type(__c, eof()) ? 0 : __c; }
725#endif // HOSTED
726 };
727#endif //_GLIBCXX_USE_CHAR8_T
728
729_GLIBCXX_END_NAMESPACE_VERSION
730} // namespace
731
732#if __cplusplus >= 201103L
733
734namespace std _GLIBCXX_VISIBILITY(default)
735{
736_GLIBCXX_BEGIN_NAMESPACE_VERSION
737
738 template<>
739 struct char_traits<char16_t>
740 {
741 typedef char16_t char_type;
742#ifdef __UINT_LEAST16_TYPE__
743 typedef __UINT_LEAST16_TYPE__ int_type;
744#else
745 typedef uint_least16_t int_type;
746#endif
747#if _GLIBCXX_HOSTED
748 typedef streamoff off_type;
749 typedef u16streampos pos_type;
750 typedef mbstate_t state_type;
751#endif // HOSTED
752#if __cpp_lib_three_way_comparison
753 using comparison_category = strong_ordering;
754#endif
755
756 static _GLIBCXX17_CONSTEXPR void
757 assign(char_type& __c1, const char_type& __c2) noexcept
758 {
759#if __cpp_constexpr_dynamic_alloc
760 if (std::__is_constant_evaluated())
761 std::construct_at(__builtin_addressof(__c1), __c2);
762 else
763#endif
764 __c1 = __c2;
765 }
766
767 static constexpr bool
768 eq(const char_type& __c1, const char_type& __c2) noexcept
769 { return __c1 == __c2; }
770
771 static constexpr bool
772 lt(const char_type& __c1, const char_type& __c2) noexcept
773 { return __c1 < __c2; }
774
775 static _GLIBCXX17_CONSTEXPR int
776 compare(const char_type* __s1, const char_type* __s2, size_t __n)
777 {
778 for (size_t __i = 0; __i < __n; ++__i)
779 if (lt(__s1[__i], __s2[__i]))
780 return -1;
781 else if (lt(__s2[__i], __s1[__i]))
782 return 1;
783 return 0;
784 }
785
786 static _GLIBCXX17_CONSTEXPR size_t
787 length(const char_type* __s)
788 {
789 size_t __i = 0;
790 while (!eq(__s[__i], char_type()))
791 ++__i;
792 return __i;
793 }
794
795 static _GLIBCXX17_CONSTEXPR const char_type*
796 find(const char_type* __s, size_t __n, const char_type& __a)
797 {
798 for (size_t __i = 0; __i < __n; ++__i)
799 if (eq(__s[__i], __a))
800 return __s + __i;
801 return 0;
802 }
803
804 static _GLIBCXX20_CONSTEXPR char_type*
805 move(char_type* __s1, const char_type* __s2, size_t __n)
806 {
807 if (__n == 0)
808 return __s1;
809#if __cplusplus >= 202002L
810 if (std::__is_constant_evaluated())
811 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
812#endif
813 return (static_cast<char_type*>
814 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
815 }
816
817 static _GLIBCXX20_CONSTEXPR char_type*
818 copy(char_type* __s1, const char_type* __s2, size_t __n)
819 {
820 if (__n == 0)
821 return __s1;
822#if __cplusplus >= 202002L
823 if (std::__is_constant_evaluated())
824 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
825#endif
826 return (static_cast<char_type*>
827 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
828 }
829
830 static _GLIBCXX20_CONSTEXPR char_type*
831 assign(char_type* __s, size_t __n, char_type __a)
832 {
833 for (size_t __i = 0; __i < __n; ++__i)
834 assign(__s[__i], __a);
835 return __s;
836 }
837
838 static constexpr char_type
839 to_char_type(const int_type& __c) noexcept
840 { return char_type(__c); }
841
842 static constexpr bool
843 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
844 { return __c1 == __c2; }
845
846#if _GLIBCXX_HOSTED
847 static constexpr int_type
848 to_int_type(const char_type& __c) noexcept
849 { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
850
851 static constexpr int_type
852 eof() noexcept
853 { return static_cast<int_type>(-1); }
854
855 static constexpr int_type
856 not_eof(const int_type& __c) noexcept
857 { return eq_int_type(__c, eof()) ? 0 : __c; }
858#else // !HOSTED
859 static constexpr int_type
860 to_int_type(const char_type& __c) noexcept
861 { return int_type(__c); }
862#endif // !HOSTED
863 };
864
865 template<>
866 struct char_traits<char32_t>
867 {
868 typedef char32_t char_type;
869#ifdef __UINT_LEAST32_TYPE__
870 typedef __UINT_LEAST32_TYPE__ int_type;
871#else
872 typedef uint_least32_t int_type;
873#endif
874#if _GLIBCXX_HOSTED
875 typedef streamoff off_type;
876 typedef u32streampos pos_type;
877 typedef mbstate_t state_type;
878#endif // HOSTED
879#if __cpp_lib_three_way_comparison
880 using comparison_category = strong_ordering;
881#endif
882
883 static _GLIBCXX17_CONSTEXPR void
884 assign(char_type& __c1, const char_type& __c2) noexcept
885 {
886#if __cpp_constexpr_dynamic_alloc
887 if (std::__is_constant_evaluated())
888 std::construct_at(__builtin_addressof(__c1), __c2);
889 else
890#endif
891 __c1 = __c2;
892 }
893
894 static constexpr bool
895 eq(const char_type& __c1, const char_type& __c2) noexcept
896 { return __c1 == __c2; }
897
898 static constexpr bool
899 lt(const char_type& __c1, const char_type& __c2) noexcept
900 { return __c1 < __c2; }
901
902 static _GLIBCXX17_CONSTEXPR int
903 compare(const char_type* __s1, const char_type* __s2, size_t __n)
904 {
905 for (size_t __i = 0; __i < __n; ++__i)
906 if (lt(__s1[__i], __s2[__i]))
907 return -1;
908 else if (lt(__s2[__i], __s1[__i]))
909 return 1;
910 return 0;
911 }
912
913 static _GLIBCXX17_CONSTEXPR size_t
914 length(const char_type* __s)
915 {
916 size_t __i = 0;
917 while (!eq(__s[__i], char_type()))
918 ++__i;
919 return __i;
920 }
921
922 static _GLIBCXX17_CONSTEXPR const char_type*
923 find(const char_type* __s, size_t __n, const char_type& __a)
924 {
925 for (size_t __i = 0; __i < __n; ++__i)
926 if (eq(__s[__i], __a))
927 return __s + __i;
928 return 0;
929 }
930
931 static _GLIBCXX20_CONSTEXPR char_type*
932 move(char_type* __s1, const char_type* __s2, size_t __n)
933 {
934 if (__n == 0)
935 return __s1;
936#if __cplusplus >= 202002L
937 if (std::__is_constant_evaluated())
938 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
939#endif
940 return (static_cast<char_type*>
941 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
942 }
943
944 static _GLIBCXX20_CONSTEXPR char_type*
945 copy(char_type* __s1, const char_type* __s2, size_t __n)
946 {
947 if (__n == 0)
948 return __s1;
949#if __cplusplus >= 202002L
950 if (std::__is_constant_evaluated())
951 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
952#endif
953 return (static_cast<char_type*>
954 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
955 }
956
957 static _GLIBCXX20_CONSTEXPR char_type*
958 assign(char_type* __s, size_t __n, char_type __a)
959 {
960 for (size_t __i = 0; __i < __n; ++__i)
961 assign(__s[__i], __a);
962 return __s;
963 }
964
965 static constexpr char_type
966 to_char_type(const int_type& __c) noexcept
967 { return char_type(__c); }
968
969 static constexpr int_type
970 to_int_type(const char_type& __c) noexcept
971 { return int_type(__c); }
972
973 static constexpr bool
974 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
975 { return __c1 == __c2; }
976
977#if _GLIBCXX_HOSTED
978 static constexpr int_type
979 eof() noexcept
980 { return static_cast<int_type>(-1); }
981
982 static constexpr int_type
983 not_eof(const int_type& __c) noexcept
984 { return eq_int_type(__c, eof()) ? 0 : __c; }
985#endif // HOSTED
986 };
987
988#if __cpp_lib_three_way_comparison
989 namespace __detail
990 {
991 template<typename _ChTraits>
992 constexpr auto
993 __char_traits_cmp_cat(int __cmp) noexcept
994 {
995 if constexpr (requires { typename _ChTraits::comparison_category; })
996 {
997 using _Cat = typename _ChTraits::comparison_category;
998 static_assert( !is_void_v<common_comparison_category_t<_Cat>> );
999 return static_cast<_Cat>(__cmp <=> 0);
1000 }
1001 else
1002 return static_cast<weak_ordering>(__cmp <=> 0);
1003 }
1004 } // namespace __detail
1005#endif // C++20
1006
1007#pragma GCC diagnostic pop
1008
1009_GLIBCXX_END_NAMESPACE_VERSION
1010} // namespace
1011
1012#endif // C++11
1013
1014#endif // _CHAR_TRAITS_H
ISO C++ entities toplevel namespace is std.
fpos< mbstate_t > u32streampos
File position for char32_t streams.
Definition postypes.h:217
long long streamoff
Type used by fpos, char_traits<char>, and char_traits<wchar_t>.
Definition postypes.h:64
fpos< mbstate_t > u16streampos
File position for char16_t streams.
Definition postypes.h:215
GNU extensions for public use.
Mapping from character type to associated types.
Definition char_traits.h:85
Base class used to implement std::char_traits.
Basis for explicit traits specializations.
Class representing stream positions.
Definition postypes.h:83