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#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
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
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*
212 char_traits<_CharT>::
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*
224 char_traits<_CharT>::
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*
255 char_traits<_CharT>::
256 copy(char_type* __s1, const char_type* __s2, std::size_t __n)
257 {
258 if (__n == 0)
259 return __s1;
260#if __cplusplus >= 202002L
261 if (std::__is_constant_evaluated())
262 {
263 for (std::size_t __i = 0; __i < __n; ++__i)
264 std::construct_at(__s1 + __i, __s2[__i]);
265 return __s1;
266 }
267#endif
268 __builtin_memcpy(__s1, __s2, __n * sizeof(char_type));
269 return __s1;
270 }
271
272 template<typename _CharT>
273 _GLIBCXX20_CONSTEXPR
274 typename char_traits<_CharT>::char_type*
275 char_traits<_CharT>::
276 assign(char_type* __s, std::size_t __n, char_type __a)
277 {
278#if __cplusplus >= 202002L
279 if (std::__is_constant_evaluated())
280 {
281 for (std::size_t __i = 0; __i < __n; ++__i)
282 std::construct_at(__s + __i, __a);
283 return __s;
284 }
285#endif
286
287 if _GLIBCXX17_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT))
288 {
289 if (__n)
290 {
291 unsigned char __c;
292 __builtin_memcpy(&__c, __builtin_addressof(__a), 1);
293 __builtin_memset(__s, __c, __n);
294 }
295 }
296 else
297 {
298 for (std::size_t __i = 0; __i < __n; ++__i)
299 __s[__i] = __a;
300 }
301 return __s;
302 }
303
304_GLIBCXX_END_NAMESPACE_VERSION
305} // namespace
306
307namespace std _GLIBCXX_VISIBILITY(default)
308{
309_GLIBCXX_BEGIN_NAMESPACE_VERSION
310
311 // 21.1
312 /**
313 * @brief Basis for explicit traits specializations.
314 *
315 * @note For any given actual character type, this definition is
316 * probably wrong. Since this is just a thin wrapper around
317 * __gnu_cxx::char_traits, it is possible to achieve a more
318 * appropriate definition by specializing __gnu_cxx::char_traits.
319 *
320 * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
321 * for advice on how to make use of this class for @a unusual character
322 * types. Also, check out include/ext/pod_char_traits.h.
323 */
324 template<typename _CharT>
325 struct char_traits : public __gnu_cxx::char_traits<_CharT>
326 { };
327
328
329 /// 21.1.3.1 char_traits specializations
330 template<>
331 struct char_traits<char>
332 {
333 typedef char char_type;
334 typedef int int_type;
335#if _GLIBCXX_HOSTED
336 typedef streampos pos_type;
337 typedef streamoff off_type;
338 typedef mbstate_t state_type;
339#endif // HOSTED
340#if __cpp_lib_three_way_comparison
341 using comparison_category = strong_ordering;
342#endif
343
344 static _GLIBCXX17_CONSTEXPR void
345 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
346 {
347#if __cpp_constexpr_dynamic_alloc
348 if (std::__is_constant_evaluated())
349 std::construct_at(__builtin_addressof(__c1), __c2);
350 else
351#endif
352 __c1 = __c2;
353 }
354
355 static _GLIBCXX_CONSTEXPR bool
356 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
357 { return __c1 == __c2; }
358
359 static _GLIBCXX_CONSTEXPR bool
360 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
361 {
362 // LWG 467.
363 return (static_cast<unsigned char>(__c1)
364 < static_cast<unsigned char>(__c2));
365 }
366
367 static _GLIBCXX17_CONSTEXPR int
368 compare(const char_type* __s1, const char_type* __s2, size_t __n)
369 {
370 if (__n == 0)
371 return 0;
372#if __cplusplus >= 201703L
373 if (std::__is_constant_evaluated())
374 {
375 for (size_t __i = 0; __i < __n; ++__i)
376 if (lt(__s1[__i], __s2[__i]))
377 return -1;
378 else if (lt(__s2[__i], __s1[__i]))
379 return 1;
380 return 0;
381 }
382#endif
383 return __builtin_memcmp(__s1, __s2, __n);
384 }
385
386 static _GLIBCXX17_CONSTEXPR size_t
387 length(const char_type* __s)
388 {
389#if __cplusplus >= 201703L
390 if (std::__is_constant_evaluated())
392#endif
393 return __builtin_strlen(__s);
394 }
395
396 static _GLIBCXX17_CONSTEXPR const char_type*
397 find(const char_type* __s, size_t __n, const char_type& __a)
398 {
399 if (__n == 0)
400 return 0;
401#if __cplusplus >= 201703L
402 if (std::__is_constant_evaluated())
403 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
404#endif
405 return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
406 }
407
408 static _GLIBCXX20_CONSTEXPR char_type*
409 move(char_type* __s1, const char_type* __s2, size_t __n)
410 {
411 if (__n == 0)
412 return __s1;
413#if __cplusplus >= 202002L
414 if (std::__is_constant_evaluated())
415 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
416#endif
417 return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
418 }
419
420 static _GLIBCXX20_CONSTEXPR char_type*
421 copy(char_type* __s1, const char_type* __s2, size_t __n)
422 {
423 if (__n == 0)
424 return __s1;
425#if __cplusplus >= 202002L
426 if (std::__is_constant_evaluated())
427 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
428#endif
429 return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
430 }
431
432 static _GLIBCXX20_CONSTEXPR char_type*
433 assign(char_type* __s, size_t __n, char_type __a)
434 {
435 if (__n == 0)
436 return __s;
437#if __cplusplus >= 202002L
438 if (std::__is_constant_evaluated())
439 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
440#endif
441 return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
442 }
443
444 static _GLIBCXX_CONSTEXPR char_type
445 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
446 { return static_cast<char_type>(__c); }
447
448 // To keep both the byte 0xff and the eof symbol 0xffffffff
449 // from ending up as 0xffffffff.
450 static _GLIBCXX_CONSTEXPR int_type
451 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
452 { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
453
454 static _GLIBCXX_CONSTEXPR bool
455 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
456 { return __c1 == __c2; }
457
458#ifdef _GLIBCXX_STDIO_EOF
459 static _GLIBCXX_CONSTEXPR int_type
460 eof() _GLIBCXX_NOEXCEPT
461 { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
462
463 static _GLIBCXX_CONSTEXPR int_type
464 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
465 { return (__c == eof()) ? 0 : __c; }
466#endif // defined(_GLIBCXX_STDIO_EOF)
467 };
468
469
470#ifdef _GLIBCXX_USE_WCHAR_T
471 /// 21.1.3.2 char_traits specializations
472 template<>
473 struct char_traits<wchar_t>
474 {
475 typedef wchar_t char_type;
476 typedef wint_t int_type;
477#if _GLIBCXX_HOSTED
478 typedef streamoff off_type;
479 typedef wstreampos pos_type;
480 typedef mbstate_t state_type;
481#endif // HOSTED
482#if __cpp_lib_three_way_comparison
483 using comparison_category = strong_ordering;
484#endif
485
486 static _GLIBCXX17_CONSTEXPR void
487 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
488 {
489#if __cpp_constexpr_dynamic_alloc
490 if (std::__is_constant_evaluated())
491 std::construct_at(__builtin_addressof(__c1), __c2);
492 else
493#endif
494 __c1 = __c2;
495 }
496
497 static _GLIBCXX_CONSTEXPR bool
498 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
499 { return __c1 == __c2; }
500
501 static _GLIBCXX_CONSTEXPR bool
502 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
503 { return __c1 < __c2; }
504
505 static _GLIBCXX17_CONSTEXPR int
506 compare(const char_type* __s1, const char_type* __s2, size_t __n)
507 {
508 if (__n == 0)
509 return 0;
510#if __cplusplus >= 201703L
511 if (std::__is_constant_evaluated())
512 return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
513#endif
514 return wmemcmp(__s1, __s2, __n);
515 }
516
517 static _GLIBCXX17_CONSTEXPR size_t
518 length(const char_type* __s)
519 {
520#if __cplusplus >= 201703L
521 if (std::__is_constant_evaluated())
523#endif
524 return wcslen(__s);
525 }
526
527 static _GLIBCXX17_CONSTEXPR const char_type*
528 find(const char_type* __s, size_t __n, const char_type& __a)
529 {
530 if (__n == 0)
531 return 0;
532#if __cplusplus >= 201703L
533 if (std::__is_constant_evaluated())
534 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
535#endif
536 return wmemchr(__s, __a, __n);
537 }
538
539 static _GLIBCXX20_CONSTEXPR char_type*
540 move(char_type* __s1, const char_type* __s2, size_t __n)
541 {
542 if (__n == 0)
543 return __s1;
544#if __cplusplus >= 202002L
545 if (std::__is_constant_evaluated())
546 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
547#endif
548 return wmemmove(__s1, __s2, __n);
549 }
550
551 static _GLIBCXX20_CONSTEXPR char_type*
552 copy(char_type* __s1, const char_type* __s2, size_t __n)
553 {
554 if (__n == 0)
555 return __s1;
556#if __cplusplus >= 202002L
557 if (std::__is_constant_evaluated())
558 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
559#endif
560 return wmemcpy(__s1, __s2, __n);
561 }
562
563 static _GLIBCXX20_CONSTEXPR char_type*
564 assign(char_type* __s, size_t __n, char_type __a)
565 {
566 if (__n == 0)
567 return __s;
568#if __cplusplus >= 202002L
569 if (std::__is_constant_evaluated())
570 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
571#endif
572 return wmemset(__s, __a, __n);
573 }
574
575 static _GLIBCXX_CONSTEXPR char_type
576 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
577 { return char_type(__c); }
578
579 static _GLIBCXX_CONSTEXPR int_type
580 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
581 { return int_type(__c); }
582
583 static _GLIBCXX_CONSTEXPR bool
584 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
585 { return __c1 == __c2; }
586
587#if _GLIBCXX_HOSTED
588 static _GLIBCXX_CONSTEXPR int_type
589 eof() _GLIBCXX_NOEXCEPT
590 { return static_cast<int_type>(WEOF); }
591
592 static _GLIBCXX_CONSTEXPR int_type
593 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
594 { return eq_int_type(__c, eof()) ? 0 : __c; }
595#endif // HOSTED
596 };
597#else // _GLIBCXX_USE_WCHAR_T
598 template<>
599 struct char_traits<wchar_t> : public __gnu_cxx::char_traits<wchar_t>
600 { };
601#endif //_GLIBCXX_USE_WCHAR_T
602
603#ifdef _GLIBCXX_USE_CHAR8_T
604 template<>
605 struct char_traits<char8_t>
606 {
607 typedef char8_t char_type;
608 typedef unsigned int int_type;
609#if _GLIBCXX_HOSTED
610 typedef u8streampos pos_type;
611 typedef streamoff off_type;
612 typedef mbstate_t state_type;
613#endif // HOSTED
614#if __cpp_lib_three_way_comparison
615 using comparison_category = strong_ordering;
616#endif
617
618 static _GLIBCXX17_CONSTEXPR void
619 assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
620 {
621#if __cpp_constexpr_dynamic_alloc
622 if (std::__is_constant_evaluated())
623 std::construct_at(__builtin_addressof(__c1), __c2);
624 else
625#endif
626 __c1 = __c2;
627 }
628
629 static _GLIBCXX_CONSTEXPR bool
630 eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
631 { return __c1 == __c2; }
632
633 static _GLIBCXX_CONSTEXPR bool
634 lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
635 { return __c1 < __c2; }
636
637 static _GLIBCXX17_CONSTEXPR int
638 compare(const char_type* __s1, const char_type* __s2, size_t __n)
639 {
640 if (__n == 0)
641 return 0;
642#if __cplusplus >= 201703L
643 if (std::__is_constant_evaluated())
644 return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
645#endif
646 return __builtin_memcmp(__s1, __s2, __n);
647 }
648
649 static _GLIBCXX17_CONSTEXPR size_t
650 length(const char_type* __s)
651 {
652#if __cplusplus >= 201703L
653 if (std::__is_constant_evaluated())
655#endif
656 return __builtin_strlen((const char*)__s);
657 }
658
659 static _GLIBCXX17_CONSTEXPR const char_type*
660 find(const char_type* __s, size_t __n, const char_type& __a)
661 {
662 if (__n == 0)
663 return 0;
664#if __cplusplus >= 201703L
665 if (std::__is_constant_evaluated())
666 return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
667#endif
668 return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
669 }
670
671 static _GLIBCXX20_CONSTEXPR char_type*
672 move(char_type* __s1, const char_type* __s2, size_t __n)
673 {
674 if (__n == 0)
675 return __s1;
676#if __cplusplus >= 202002L
677 if (std::__is_constant_evaluated())
678 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
679#endif
680 return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
681 }
682
683 static _GLIBCXX20_CONSTEXPR char_type*
684 copy(char_type* __s1, const char_type* __s2, size_t __n)
685 {
686 if (__n == 0)
687 return __s1;
688#if __cplusplus >= 202002L
689 if (std::__is_constant_evaluated())
690 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
691#endif
692 return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
693 }
694
695 static _GLIBCXX20_CONSTEXPR char_type*
696 assign(char_type* __s, size_t __n, char_type __a)
697 {
698 if (__n == 0)
699 return __s;
700#if __cplusplus >= 202002L
701 if (std::__is_constant_evaluated())
702 return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
703#endif
704 return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
705 }
706
707 static _GLIBCXX_CONSTEXPR char_type
708 to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
709 { return char_type(__c); }
710
711 static _GLIBCXX_CONSTEXPR int_type
712 to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
713 { return int_type(__c); }
714
715 static _GLIBCXX_CONSTEXPR bool
716 eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
717 { return __c1 == __c2; }
718
719#if _GLIBCXX_HOSTED
720 static _GLIBCXX_CONSTEXPR int_type
721 eof() _GLIBCXX_NOEXCEPT
722 { return static_cast<int_type>(-1); }
723
724 static _GLIBCXX_CONSTEXPR int_type
725 not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
726 { return eq_int_type(__c, eof()) ? 0 : __c; }
727#endif // HOSTED
728 };
729#endif //_GLIBCXX_USE_CHAR8_T
730
731_GLIBCXX_END_NAMESPACE_VERSION
732} // namespace
733
734#if __cplusplus >= 201103L
735
736namespace std _GLIBCXX_VISIBILITY(default)
737{
738_GLIBCXX_BEGIN_NAMESPACE_VERSION
739
740 template<>
741 struct char_traits<char16_t>
742 {
743 typedef char16_t char_type;
744#ifdef __UINT_LEAST16_TYPE__
745 typedef __UINT_LEAST16_TYPE__ int_type;
746#else
747 typedef uint_least16_t int_type;
748#endif
749#if _GLIBCXX_HOSTED
750 typedef streamoff off_type;
751 typedef u16streampos pos_type;
752 typedef mbstate_t state_type;
753#endif // HOSTED
754#if __cpp_lib_three_way_comparison
755 using comparison_category = strong_ordering;
756#endif
757
758 static _GLIBCXX17_CONSTEXPR void
759 assign(char_type& __c1, const char_type& __c2) noexcept
760 {
761#if __cpp_constexpr_dynamic_alloc
762 if (std::__is_constant_evaluated())
763 std::construct_at(__builtin_addressof(__c1), __c2);
764 else
765#endif
766 __c1 = __c2;
767 }
768
769 static constexpr bool
770 eq(const char_type& __c1, const char_type& __c2) noexcept
771 { return __c1 == __c2; }
772
773 static constexpr bool
774 lt(const char_type& __c1, const char_type& __c2) noexcept
775 { return __c1 < __c2; }
776
777 static _GLIBCXX17_CONSTEXPR int
778 compare(const char_type* __s1, const char_type* __s2, size_t __n)
779 {
780 for (size_t __i = 0; __i < __n; ++__i)
781 if (lt(__s1[__i], __s2[__i]))
782 return -1;
783 else if (lt(__s2[__i], __s1[__i]))
784 return 1;
785 return 0;
786 }
787
788 static _GLIBCXX17_CONSTEXPR size_t
789 length(const char_type* __s)
790 {
791 size_t __i = 0;
792 while (!eq(__s[__i], char_type()))
793 ++__i;
794 return __i;
795 }
796
797 static _GLIBCXX17_CONSTEXPR const char_type*
798 find(const char_type* __s, size_t __n, const char_type& __a)
799 {
800 for (size_t __i = 0; __i < __n; ++__i)
801 if (eq(__s[__i], __a))
802 return __s + __i;
803 return 0;
804 }
805
806 static _GLIBCXX20_CONSTEXPR char_type*
807 move(char_type* __s1, const char_type* __s2, size_t __n)
808 {
809 if (__n == 0)
810 return __s1;
811#if __cplusplus >= 202002L
812 if (std::__is_constant_evaluated())
813 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
814#endif
815 return (static_cast<char_type*>
816 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
817 }
818
819 static _GLIBCXX20_CONSTEXPR char_type*
820 copy(char_type* __s1, const char_type* __s2, size_t __n)
821 {
822 if (__n == 0)
823 return __s1;
824#if __cplusplus >= 202002L
825 if (std::__is_constant_evaluated())
826 return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
827#endif
828 return (static_cast<char_type*>
829 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
830 }
831
832 static _GLIBCXX20_CONSTEXPR char_type*
833 assign(char_type* __s, size_t __n, char_type __a)
834 {
835 for (size_t __i = 0; __i < __n; ++__i)
836 assign(__s[__i], __a);
837 return __s;
838 }
839
840 static constexpr char_type
841 to_char_type(const int_type& __c) noexcept
842 { return char_type(__c); }
843
844 static constexpr bool
845 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
846 { return __c1 == __c2; }
847
848#if _GLIBCXX_HOSTED
849 static constexpr int_type
850 to_int_type(const char_type& __c) noexcept
851 { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
852
853 static constexpr int_type
854 eof() noexcept
855 { return static_cast<int_type>(-1); }
856
857 static constexpr int_type
858 not_eof(const int_type& __c) noexcept
859 { return eq_int_type(__c, eof()) ? 0 : __c; }
860#else // !HOSTED
861 static constexpr int_type
862 to_int_type(const char_type& __c) noexcept
863 { return int_type(__c); }
864#endif // !HOSTED
865 };
866
867 template<>
868 struct char_traits<char32_t>
869 {
870 typedef char32_t char_type;
871#ifdef __UINT_LEAST32_TYPE__
872 typedef __UINT_LEAST32_TYPE__ int_type;
873#else
874 typedef uint_least32_t int_type;
875#endif
876#if _GLIBCXX_HOSTED
877 typedef streamoff off_type;
878 typedef u32streampos pos_type;
879 typedef mbstate_t state_type;
880#endif // HOSTED
881#if __cpp_lib_three_way_comparison
882 using comparison_category = strong_ordering;
883#endif
884
885 static _GLIBCXX17_CONSTEXPR void
886 assign(char_type& __c1, const char_type& __c2) noexcept
887 {
888#if __cpp_constexpr_dynamic_alloc
889 if (std::__is_constant_evaluated())
890 std::construct_at(__builtin_addressof(__c1), __c2);
891 else
892#endif
893 __c1 = __c2;
894 }
895
896 static constexpr bool
897 eq(const char_type& __c1, const char_type& __c2) noexcept
898 { return __c1 == __c2; }
899
900 static constexpr bool
901 lt(const char_type& __c1, const char_type& __c2) noexcept
902 { return __c1 < __c2; }
903
904 static _GLIBCXX17_CONSTEXPR int
905 compare(const char_type* __s1, const char_type* __s2, size_t __n)
906 {
907 for (size_t __i = 0; __i < __n; ++__i)
908 if (lt(__s1[__i], __s2[__i]))
909 return -1;
910 else if (lt(__s2[__i], __s1[__i]))
911 return 1;
912 return 0;
913 }
914
915 static _GLIBCXX17_CONSTEXPR size_t
916 length(const char_type* __s)
917 {
918 size_t __i = 0;
919 while (!eq(__s[__i], char_type()))
920 ++__i;
921 return __i;
922 }
923
924 static _GLIBCXX17_CONSTEXPR const char_type*
925 find(const char_type* __s, size_t __n, const char_type& __a)
926 {
927 for (size_t __i = 0; __i < __n; ++__i)
928 if (eq(__s[__i], __a))
929 return __s + __i;
930 return 0;
931 }
932
933 static _GLIBCXX20_CONSTEXPR char_type*
934 move(char_type* __s1, const char_type* __s2, size_t __n)
935 {
936 if (__n == 0)
937 return __s1;
938#if __cplusplus >= 202002L
939 if (std::__is_constant_evaluated())
940 return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
941#endif
942 return (static_cast<char_type*>
943 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
944 }
945
946 static _GLIBCXX20_CONSTEXPR char_type*
947 copy(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>::copy(__s1, __s2, __n);
954#endif
955 return (static_cast<char_type*>
956 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
957 }
958
959 static _GLIBCXX20_CONSTEXPR char_type*
960 assign(char_type* __s, size_t __n, char_type __a)
961 {
962 for (size_t __i = 0; __i < __n; ++__i)
963 assign(__s[__i], __a);
964 return __s;
965 }
966
967 static constexpr char_type
968 to_char_type(const int_type& __c) noexcept
969 { return char_type(__c); }
970
971 static constexpr int_type
972 to_int_type(const char_type& __c) noexcept
973 { return int_type(__c); }
974
975 static constexpr bool
976 eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
977 { return __c1 == __c2; }
978
979#if _GLIBCXX_HOSTED
980 static constexpr int_type
981 eof() noexcept
982 { return static_cast<int_type>(-1); }
983
984 static constexpr int_type
985 not_eof(const int_type& __c) noexcept
986 { return eq_int_type(__c, eof()) ? 0 : __c; }
987#endif // HOSTED
988 };
989
990#if __cpp_lib_three_way_comparison
991 namespace __detail
992 {
993 template<typename _ChTraits>
994 constexpr auto
995 __char_traits_cmp_cat(int __cmp) noexcept
996 {
997 if constexpr (requires { typename _ChTraits::comparison_category; })
998 {
999 using _Cat = typename _ChTraits::comparison_category;
1000 static_assert( !is_void_v<common_comparison_category_t<_Cat>> );
1001 return static_cast<_Cat>(__cmp <=> 0);
1002 }
1003 else
1004 return static_cast<weak_ordering>(__cmp <=> 0);
1005 }
1006 } // namespace __detail
1007#endif // C++20
1008
1009#pragma GCC diagnostic pop
1010
1011_GLIBCXX_END_NAMESPACE_VERSION
1012} // namespace
1013
1014#endif // C++11
1015
1016#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 > u16streampos
File position for char16_t streams.
Definition postypes.h:220
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.
Definition stringfwd.h:55
Class representing stream positions.
Definition postypes.h:88