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