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