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