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