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