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-2023 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#ifdef __cpp_lib_is_constant_evaluated
310// Unofficial macro indicating P1032R1 support in C++20
311# define __cpp_lib_constexpr_char_traits 201811L
312#elif __cplusplus >= 201703L && _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED
313// Unofficial macro indicating P0426R1 support in C++17
314# define __cpp_lib_constexpr_char_traits 201611L
315#endif
316
317 // 21.1
318 /**
319 * @brief Basis for explicit traits specializations.
320 *
321 * @note For any given actual character type, this definition is
322 * probably wrong. Since this is just a thin wrapper around
323 * __gnu_cxx::char_traits, it is possible to achieve a more
324 * appropriate definition by specializing __gnu_cxx::char_traits.
325 *
326 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
327 * for advice on how to make use of this class for @a unusual character
328 * types. Also, check out include/ext/pod_char_traits.h.
329 */
330 template<typename _CharT>
331 struct char_traits : public __gnu_cxx::char_traits<_CharT>
332 { };
333
334
335 /// 21.1.3.1 char_traits specializations
336 template<>
337 struct char_traits<char>
338 {
339 typedef char char_type;
340 typedef int int_type;
341#if _GLIBCXX_HOSTED
342 typedef streampos pos_type;
343 typedef streamoff off_type;
344 typedef mbstate_t state_type;
345#endif // HOSTED
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(__s1[__i], __s2[__i]))
383 return -1;
384 else if (lt(__s2[__i], __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())
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#ifdef _GLIBCXX_STDIO_EOF
465 static _GLIBCXX_CONSTEXPR int_type
466 eof() _GLIBCXX_NOEXCEPT
467 { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
468
469 static _GLIBCXX_CONSTEXPR int_type
470 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
471 { return (__c == eof()) ? 0 : __c; }
472#endif // defined(_GLIBCXX_STDIO_EOF)
473 };
474
475
476#ifdef _GLIBCXX_USE_WCHAR_T
477 /// 21.1.3.2 char_traits specializations
478 template<>
479 struct char_traits<wchar_t>
480 {
481 typedef wchar_t char_type;
482 typedef wint_t int_type;
483#if _GLIBCXX_HOSTED
484 typedef streamoff off_type;
485 typedef wstreampos pos_type;
486 typedef mbstate_t state_type;
487#endif // HOSTED
488#if __cpp_lib_three_way_comparison
489 using comparison_category = strong_ordering;
490#endif
491
492 static _GLIBCXX17_CONSTEXPR void
493 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
494 {
495#if __cpp_constexpr_dynamic_alloc
496 if (std::__is_constant_evaluated())
497 std::construct_at(__builtin_addressof(__c1), __c2);
498 else
499#endif
500 __c1 = __c2;
501 }
502
503 static _GLIBCXX_CONSTEXPR bool
504 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
505 { return __c1 == __c2; }
506
507 static _GLIBCXX_CONSTEXPR bool
508 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
509 { return __c1 < __c2; }
510
511 static _GLIBCXX17_CONSTEXPR int
512 compare(const char_type* __s1, const char_type* __s2, size_t __n)
513 {
514 if (__n == 0)
515 return 0;
516#if __cplusplus >= 201703L
517 if (std::__is_constant_evaluated())
518 return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
519#endif
520 return wmemcmp(__s1, __s2, __n);
521 }
522
523 static _GLIBCXX17_CONSTEXPR size_t
524 length(const char_type* __s)
525 {
526#if __cplusplus >= 201703L
527 if (std::__is_constant_evaluated())
529#endif
530 return wcslen(__s);
531 }
532
533 static _GLIBCXX17_CONSTEXPR const char_type*
534 find(const char_type* __s, size_t __n, const char_type& __a)
535 {
536 if (__n == 0)
537 return 0;
538#if __cplusplus >= 201703L
539 if (std::__is_constant_evaluated())
540 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
541#endif
542 return wmemchr(__s, __a, __n);
543 }
544
545 static _GLIBCXX20_CONSTEXPR char_type*
546 move(char_type* __s1, const char_type* __s2, size_t __n)
547 {
548 if (__n == 0)
549 return __s1;
550#if __cplusplus >= 202002L
551 if (std::__is_constant_evaluated())
552 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
553#endif
554 return wmemmove(__s1, __s2, __n);
555 }
556
557 static _GLIBCXX20_CONSTEXPR char_type*
558 copy(char_type* __s1, const char_type* __s2, size_t __n)
559 {
560 if (__n == 0)
561 return __s1;
562#if __cplusplus >= 202002L
563 if (std::__is_constant_evaluated())
564 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
565#endif
566 return wmemcpy(__s1, __s2, __n);
567 }
568
569 static _GLIBCXX20_CONSTEXPR char_type*
570 assign(char_type* __s, size_t __n, char_type __a)
571 {
572 if (__n == 0)
573 return __s;
574#if __cplusplus >= 202002L
575 if (std::__is_constant_evaluated())
576 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
577#endif
578 return wmemset(__s, __a, __n);
579 }
580
581 static _GLIBCXX_CONSTEXPR char_type
582 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
583 { return char_type(__c); }
584
585 static _GLIBCXX_CONSTEXPR int_type
586 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
587 { return int_type(__c); }
588
589 static _GLIBCXX_CONSTEXPR bool
590 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
591 { return __c1 == __c2; }
592
593#if _GLIBCXX_HOSTED
594 static _GLIBCXX_CONSTEXPR int_type
595 eof() _GLIBCXX_NOEXCEPT
596 { return static_cast<int_type>(WEOF); }
597
598 static _GLIBCXX_CONSTEXPR int_type
599 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
600 { return eq_int_type(__c, eof()) ? 0 : __c; }
601#endif // HOSTED
602 };
603#else // _GLIBCXX_USE_WCHAR_T
604 template<>
605 struct char_traits<wchar_t> : public __gnu_cxx::char_traits<wchar_t>
606 { };
607#endif //_GLIBCXX_USE_WCHAR_T
608
609#ifdef _GLIBCXX_USE_CHAR8_T
610 template<>
611 struct char_traits<char8_t>
612 {
613 typedef char8_t char_type;
614 typedef unsigned int int_type;
615#if _GLIBCXX_HOSTED
616 typedef u8streampos pos_type;
617 typedef streamoff off_type;
618 typedef mbstate_t state_type;
619#endif // HOSTED
620#if __cpp_lib_three_way_comparison
621 using comparison_category = strong_ordering;
622#endif
623
624 static _GLIBCXX17_CONSTEXPR void
625 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
626 {
627#if __cpp_constexpr_dynamic_alloc
628 if (std::__is_constant_evaluated())
629 std::construct_at(__builtin_addressof(__c1), __c2);
630 else
631#endif
632 __c1 = __c2;
633 }
634
635 static _GLIBCXX_CONSTEXPR bool
636 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
637 { return __c1 == __c2; }
638
639 static _GLIBCXX_CONSTEXPR bool
640 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
641 { return __c1 < __c2; }
642
643 static _GLIBCXX17_CONSTEXPR int
644 compare(const char_type* __s1, const char_type* __s2, size_t __n)
645 {
646 if (__n == 0)
647 return 0;
648#if __cplusplus >= 201703L
649 if (std::__is_constant_evaluated())
650 return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
651#endif
652 return __builtin_memcmp(__s1, __s2, __n);
653 }
654
655 static _GLIBCXX17_CONSTEXPR size_t
656 length(const char_type* __s)
657 {
658#if __cplusplus >= 201703L
659 if (std::__is_constant_evaluated())
661#endif
662 size_t __i = 0;
663 while (!eq(__s[__i], char_type()))
664 ++__i;
665 return __i;
666 }
667
668 static _GLIBCXX17_CONSTEXPR const char_type*
669 find(const char_type* __s, size_t __n, const char_type& __a)
670 {
671 if (__n == 0)
672 return 0;
673#if __cplusplus >= 201703L
674 if (std::__is_constant_evaluated())
675 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
676#endif
677 return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
678 }
679
680 static _GLIBCXX20_CONSTEXPR char_type*
681 move(char_type* __s1, const char_type* __s2, size_t __n)
682 {
683 if (__n == 0)
684 return __s1;
685#if __cplusplus >= 202002L
686 if (std::__is_constant_evaluated())
687 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
688#endif
689 return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
690 }
691
692 static _GLIBCXX20_CONSTEXPR char_type*
693 copy(char_type* __s1, const char_type* __s2, size_t __n)
694 {
695 if (__n == 0)
696 return __s1;
697#if __cplusplus >= 202002L
698 if (std::__is_constant_evaluated())
699 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
700#endif
701 return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
702 }
703
704 static _GLIBCXX20_CONSTEXPR char_type*
705 assign(char_type* __s, size_t __n, char_type __a)
706 {
707 if (__n == 0)
708 return __s;
709#if __cplusplus >= 202002L
710 if (std::__is_constant_evaluated())
711 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
712#endif
713 return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
714 }
715
716 static _GLIBCXX_CONSTEXPR char_type
717 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
718 { return char_type(__c); }
719
720 static _GLIBCXX_CONSTEXPR int_type
721 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
722 { return int_type(__c); }
723
724 static _GLIBCXX_CONSTEXPR bool
725 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
726 { return __c1 == __c2; }
727
728#if _GLIBCXX_HOSTED
729 static _GLIBCXX_CONSTEXPR int_type
730 eof() _GLIBCXX_NOEXCEPT
731 { return static_cast<int_type>(-1); }
732
733 static _GLIBCXX_CONSTEXPR int_type
734 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
735 { return eq_int_type(__c, eof()) ? 0 : __c; }
736#endif // HOSTED
737 };
738#endif //_GLIBCXX_USE_CHAR8_T
739
740_GLIBCXX_END_NAMESPACE_VERSION
741} // namespace
742
743#if __cplusplus >= 201103L
744
745namespace std _GLIBCXX_VISIBILITY(default)
746{
747_GLIBCXX_BEGIN_NAMESPACE_VERSION
748
749 template<>
750 struct char_traits<char16_t>
751 {
752 typedef char16_t char_type;
753#ifdef __UINT_LEAST16_TYPE__
754 typedef __UINT_LEAST16_TYPE__ int_type;
755#elif defined _GLIBCXX_USE_C99_STDINT_TR1
756 typedef uint_least16_t int_type;
757#else
758 typedef make_unsigned<char16_t>::type int_type;
759#endif
760#if _GLIBCXX_HOSTED
761 typedef streamoff off_type;
762 typedef u16streampos pos_type;
763 typedef mbstate_t state_type;
764#endif // HOSTED
765#if __cpp_lib_three_way_comparison
766 using comparison_category = strong_ordering;
767#endif
768
769 static _GLIBCXX17_CONSTEXPR void
770 assign(char_type& __c1, const char_type& __c2) noexcept
771 {
772#if __cpp_constexpr_dynamic_alloc
773 if (std::__is_constant_evaluated())
774 std::construct_at(__builtin_addressof(__c1), __c2);
775 else
776#endif
777 __c1 = __c2;
778 }
779
780 static constexpr bool
781 eq(const char_type& __c1, const char_type& __c2) noexcept
782 { return __c1 == __c2; }
783
784 static constexpr bool
785 lt(const char_type& __c1, const char_type& __c2) noexcept
786 { return __c1 < __c2; }
787
788 static _GLIBCXX17_CONSTEXPR int
789 compare(const char_type* __s1, const char_type* __s2, size_t __n)
790 {
791 for (size_t __i = 0; __i < __n; ++__i)
792 if (lt(__s1[__i], __s2[__i]))
793 return -1;
794 else if (lt(__s2[__i], __s1[__i]))
795 return 1;
796 return 0;
797 }
798
799 static _GLIBCXX17_CONSTEXPR size_t
800 length(const char_type* __s)
801 {
802 size_t __i = 0;
803 while (!eq(__s[__i], char_type()))
804 ++__i;
805 return __i;
806 }
807
808 static _GLIBCXX17_CONSTEXPR const char_type*
809 find(const char_type* __s, size_t __n, const char_type& __a)
810 {
811 for (size_t __i = 0; __i < __n; ++__i)
812 if (eq(__s[__i], __a))
813 return __s + __i;
814 return 0;
815 }
816
817 static _GLIBCXX20_CONSTEXPR char_type*
818 move(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>::move(__s1, __s2, __n);
825#endif
826 return (static_cast<char_type*>
827 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
828 }
829
830 static _GLIBCXX20_CONSTEXPR char_type*
831 copy(char_type* __s1, const char_type* __s2, size_t __n)
832 {
833 if (__n == 0)
834 return __s1;
835#if __cplusplus >= 202002L
836 if (std::__is_constant_evaluated())
837 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
838#endif
839 return (static_cast<char_type*>
840 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
841 }
842
843 static _GLIBCXX20_CONSTEXPR char_type*
844 assign(char_type* __s, size_t __n, char_type __a)
845 {
846 for (size_t __i = 0; __i < __n; ++__i)
847 assign(__s[__i], __a);
848 return __s;
849 }
850
851 static constexpr char_type
852 to_char_type(const int_type& __c) noexcept
853 { return char_type(__c); }
854
855 static constexpr bool
856 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
857 { return __c1 == __c2; }
858
859#if _GLIBCXX_HOSTED
860 static constexpr int_type
861 to_int_type(const char_type& __c) noexcept
862 { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
863
864 static constexpr int_type
865 eof() noexcept
866 { return static_cast<int_type>(-1); }
867
868 static constexpr int_type
869 not_eof(const int_type& __c) noexcept
870 { return eq_int_type(__c, eof()) ? 0 : __c; }
871#else // !HOSTED
872 static constexpr int_type
873 to_int_type(const char_type& __c) noexcept
874 { return int_type(__c); }
875#endif // !HOSTED
876 };
877
878 template<>
879 struct char_traits<char32_t>
880 {
881 typedef char32_t char_type;
882#ifdef __UINT_LEAST32_TYPE__
883 typedef __UINT_LEAST32_TYPE__ int_type;
884#elif defined _GLIBCXX_USE_C99_STDINT_TR1
885 typedef uint_least32_t int_type;
886#else
887 typedef make_unsigned<char32_t>::type int_type;
888#endif
889#if _GLIBCXX_HOSTED
890 typedef streamoff off_type;
891 typedef u32streampos pos_type;
892 typedef mbstate_t state_type;
893#endif // HOSTED
894#if __cpp_lib_three_way_comparison
895 using comparison_category = strong_ordering;
896#endif
897
898 static _GLIBCXX17_CONSTEXPR void
899 assign(char_type& __c1, const char_type& __c2) noexcept
900 {
901#if __cpp_constexpr_dynamic_alloc
902 if (std::__is_constant_evaluated())
903 std::construct_at(__builtin_addressof(__c1), __c2);
904 else
905#endif
906 __c1 = __c2;
907 }
908
909 static constexpr bool
910 eq(const char_type& __c1, const char_type& __c2) noexcept
911 { return __c1 == __c2; }
912
913 static constexpr bool
914 lt(const char_type& __c1, const char_type& __c2) noexcept
915 { return __c1 < __c2; }
916
917 static _GLIBCXX17_CONSTEXPR int
918 compare(const char_type* __s1, const char_type* __s2, size_t __n)
919 {
920 for (size_t __i = 0; __i < __n; ++__i)
921 if (lt(__s1[__i], __s2[__i]))
922 return -1;
923 else if (lt(__s2[__i], __s1[__i]))
924 return 1;
925 return 0;
926 }
927
928 static _GLIBCXX17_CONSTEXPR size_t
929 length(const char_type* __s)
930 {
931 size_t __i = 0;
932 while (!eq(__s[__i], char_type()))
933 ++__i;
934 return __i;
935 }
936
937 static _GLIBCXX17_CONSTEXPR const char_type*
938 find(const char_type* __s, size_t __n, const char_type& __a)
939 {
940 for (size_t __i = 0; __i < __n; ++__i)
941 if (eq(__s[__i], __a))
942 return __s + __i;
943 return 0;
944 }
945
946 static _GLIBCXX20_CONSTEXPR char_type*
947 move(char_type* __s1, const char_type* __s2, size_t __n)
948 {
949 if (__n == 0)
950 return __s1;
951#if __cplusplus >= 202002L
952 if (std::__is_constant_evaluated())
953 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
954#endif
955 return (static_cast<char_type*>
956 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
957 }
958
959 static _GLIBCXX20_CONSTEXPR char_type*
960 copy(char_type* __s1, const char_type* __s2, size_t __n)
961 {
962 if (__n == 0)
963 return __s1;
964#if __cplusplus >= 202002L
965 if (std::__is_constant_evaluated())
966 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
967#endif
968 return (static_cast<char_type*>
969 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
970 }
971
972 static _GLIBCXX20_CONSTEXPR char_type*
973 assign(char_type* __s, size_t __n, char_type __a)
974 {
975 for (size_t __i = 0; __i < __n; ++__i)
976 assign(__s[__i], __a);
977 return __s;
978 }
979
980 static constexpr char_type
981 to_char_type(const int_type& __c) noexcept
982 { return char_type(__c); }
983
984 static constexpr int_type
985 to_int_type(const char_type& __c) noexcept
986 { return int_type(__c); }
987
988 static constexpr bool
989 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
990 { return __c1 == __c2; }
991
992#if _GLIBCXX_HOSTED
993 static constexpr int_type
994 eof() noexcept
995 { return static_cast<int_type>(-1); }
996
997 static constexpr int_type
998 not_eof(const int_type& __c) noexcept
999 { return eq_int_type(__c, eof()) ? 0 : __c; }
1000#endif // HOSTED
1001 };
1002
1003#if __cpp_lib_three_way_comparison
1004 namespace __detail
1005 {
1006 template<typename _ChTraits>
1007 constexpr auto
1008 __char_traits_cmp_cat(int __cmp) noexcept
1009 {
1010 if constexpr (requires { typename _ChTraits::comparison_category; })
1011 {
1012 using _Cat = typename _ChTraits::comparison_category;
1013 static_assert( !is_void_v<common_comparison_category_t<_Cat>> );
1014 return static_cast<_Cat>(__cmp <=> 0);
1015 }
1016 else
1017 return static_cast<weak_ordering>(__cmp <=> 0);
1018 }
1019 } // namespace __detail
1020#endif // C++20
1021
1022#pragma GCC diagnostic pop
1023
1024_GLIBCXX_END_NAMESPACE_VERSION
1025} // namespace
1026
1027#endif // C++11
1028
1029#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.
Definition: char_traits.h:112
Basis for explicit traits specializations.
Definition: char_traits.h:332
Class representing stream positions.
Definition: postypes.h:83