Line data Source code
1 : // Character Traits for use by standard string and iostream -*- C++ -*-
2 :
3 : // Copyright (C) 1997-2024 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 :
64 : namespace __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>
84 : struct _Char_types
85 : {
86 : typedef unsigned long int_type;
87 : #if _GLIBCXX_HOSTED
88 : typedef std::streampos pos_type;
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>
111 : struct char_traits
112 : {
113 : typedef _CharT char_type;
114 : typedef typename _Char_types<_CharT>::int_type int_type;
115 : #if _GLIBCXX_HOSTED
116 : typedef typename _Char_types<_CharT>::pos_type pos_type;
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 0 : eq(const char_type& __c1, const char_type& __c2)
137 0 : { 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
186 : char_traits<_CharT>::
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 0 : char_traits<_CharT>::
200 : length(const char_type* __p)
201 : {
202 0 : std::size_t __i = 0;
203 0 : while (!eq(__p[__i], char_type()))
204 0 : ++__i;
205 0 : 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 : // Use __builtin_constant_p to avoid comparing unrelated pointers.
231 : if (__builtin_constant_p(__s2 < __s1)
232 : && __s1 > __s2 && __s1 < (__s2 + __n))
233 : {
234 : do
235 : {
236 : --__n;
237 : assign(__s1[__n], __s2[__n]);
238 : }
239 : while (__n > 0);
240 : }
241 : else
242 : copy(__s1, __s2, __n);
243 : return __s1;
244 : }
245 : #endif
246 : __builtin_memmove(__s1, __s2, __n * sizeof(char_type));
247 : return __s1;
248 : }
249 :
250 : template<typename _CharT>
251 : _GLIBCXX20_CONSTEXPR
252 : typename char_traits<_CharT>::char_type*
253 : char_traits<_CharT>::
254 : copy(char_type* __s1, const char_type* __s2, std::size_t __n)
255 : {
256 : if (__n == 0)
257 : return __s1;
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 : __builtin_memcpy(__s1, __s2, __n * sizeof(char_type));
267 : return __s1;
268 : }
269 :
270 : template<typename _CharT>
271 : _GLIBCXX20_CONSTEXPR
272 : typename char_traits<_CharT>::char_type*
273 : char_traits<_CharT>::
274 : assign(char_type* __s, std::size_t __n, char_type __a)
275 : {
276 : #if __cplusplus >= 202002L
277 : if (std::__is_constant_evaluated())
278 : {
279 : for (std::size_t __i = 0; __i < __n; ++__i)
280 : std::construct_at(__s + __i, __a);
281 : return __s;
282 : }
283 : #endif
284 :
285 : if _GLIBCXX17_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT))
286 : {
287 : if (__n)
288 : {
289 : unsigned char __c;
290 : __builtin_memcpy(&__c, __builtin_addressof(__a), 1);
291 : __builtin_memset(__s, __c, __n);
292 : }
293 : }
294 : else
295 : {
296 : for (std::size_t __i = 0; __i < __n; ++__i)
297 : __s[__i] = __a;
298 : }
299 : return __s;
300 : }
301 :
302 : _GLIBCXX_END_NAMESPACE_VERSION
303 : } // namespace
304 :
305 : namespace std _GLIBCXX_VISIBILITY(default)
306 : {
307 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
308 :
309 : // 21.1
310 : /**
311 : * @brief Basis for explicit traits specializations.
312 : *
313 : * @note For any given actual character type, this definition is
314 : * probably wrong. Since this is just a thin wrapper around
315 : * __gnu_cxx::char_traits, it is possible to achieve a more
316 : * appropriate definition by specializing __gnu_cxx::char_traits.
317 : *
318 : * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
319 : * for advice on how to make use of this class for @a unusual character
320 : * types. Also, check out include/ext/pod_char_traits.h.
321 : */
322 : template<typename _CharT>
323 : struct char_traits : public __gnu_cxx::char_traits<_CharT>
324 : { };
325 :
326 :
327 : /// 21.1.3.1 char_traits specializations
328 : template<>
329 : struct char_traits<char>
330 : {
331 : typedef char char_type;
332 : typedef int int_type;
333 : #if _GLIBCXX_HOSTED
334 : typedef streampos pos_type;
335 : typedef streamoff off_type;
336 : typedef mbstate_t state_type;
337 : #endif // HOSTED
338 : #if __cpp_lib_three_way_comparison
339 : using comparison_category = strong_ordering;
340 : #endif
341 :
342 : static _GLIBCXX17_CONSTEXPR void
343 : assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
344 : {
345 : #if __cpp_constexpr_dynamic_alloc
346 : if (std::__is_constant_evaluated())
347 : std::construct_at(__builtin_addressof(__c1), __c2);
348 : else
349 : #endif
350 : __c1 = __c2;
351 : }
352 :
353 : static _GLIBCXX_CONSTEXPR bool
354 : eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
355 : { return __c1 == __c2; }
356 :
357 : static _GLIBCXX_CONSTEXPR bool
358 : lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
359 : {
360 : // LWG 467.
361 : return (static_cast<unsigned char>(__c1)
362 : < static_cast<unsigned char>(__c2));
363 : }
364 :
365 : static _GLIBCXX17_CONSTEXPR int
366 : compare(const char_type* __s1, const char_type* __s2, size_t __n)
367 : {
368 : if (__n == 0)
369 : return 0;
370 : #if __cplusplus >= 201703L
371 : if (std::__is_constant_evaluated())
372 : {
373 : for (size_t __i = 0; __i < __n; ++__i)
374 : if (lt(__s1[__i], __s2[__i]))
375 : return -1;
376 : else if (lt(__s2[__i], __s1[__i]))
377 : return 1;
378 : return 0;
379 : }
380 : #endif
381 : return __builtin_memcmp(__s1, __s2, __n);
382 : }
383 :
384 : static _GLIBCXX17_CONSTEXPR size_t
385 9358 : length(const char_type* __s)
386 : {
387 : #if __cplusplus >= 201703L
388 9358 : if (std::__is_constant_evaluated())
389 0 : return __gnu_cxx::char_traits<char_type>::length(__s);
390 : #endif
391 9358 : return __builtin_strlen(__s);
392 : }
393 :
394 : static _GLIBCXX17_CONSTEXPR const char_type*
395 : find(const char_type* __s, size_t __n, const char_type& __a)
396 : {
397 : if (__n == 0)
398 : return 0;
399 : #if __cplusplus >= 201703L
400 : if (std::__is_constant_evaluated())
401 : return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
402 : #endif
403 : return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
404 : }
405 :
406 : static _GLIBCXX20_CONSTEXPR char_type*
407 : move(char_type* __s1, const char_type* __s2, size_t __n)
408 : {
409 : if (__n == 0)
410 : return __s1;
411 : #if __cplusplus >= 202002L
412 : if (std::__is_constant_evaluated())
413 : return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
414 : #endif
415 : return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
416 : }
417 :
418 : static _GLIBCXX20_CONSTEXPR char_type*
419 0 : copy(char_type* __s1, const char_type* __s2, size_t __n)
420 : {
421 0 : if (__n == 0)
422 0 : return __s1;
423 : #if __cplusplus >= 202002L
424 : if (std::__is_constant_evaluated())
425 : return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
426 : #endif
427 0 : return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
428 : }
429 :
430 : static _GLIBCXX20_CONSTEXPR char_type*
431 : assign(char_type* __s, size_t __n, char_type __a)
432 : {
433 : if (__n == 0)
434 : return __s;
435 : #if __cplusplus >= 202002L
436 : if (std::__is_constant_evaluated())
437 : return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
438 : #endif
439 : return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
440 : }
441 :
442 : static _GLIBCXX_CONSTEXPR char_type
443 : to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
444 : { return static_cast<char_type>(__c); }
445 :
446 : // To keep both the byte 0xff and the eof symbol 0xffffffff
447 : // from ending up as 0xffffffff.
448 : static _GLIBCXX_CONSTEXPR int_type
449 : to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
450 : { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
451 :
452 : static _GLIBCXX_CONSTEXPR bool
453 : eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
454 : { return __c1 == __c2; }
455 :
456 : #ifdef _GLIBCXX_STDIO_EOF
457 : static _GLIBCXX_CONSTEXPR int_type
458 : eof() _GLIBCXX_NOEXCEPT
459 : { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
460 :
461 : static _GLIBCXX_CONSTEXPR int_type
462 : not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
463 : { return (__c == eof()) ? 0 : __c; }
464 : #endif // defined(_GLIBCXX_STDIO_EOF)
465 : };
466 :
467 :
468 : #ifdef _GLIBCXX_USE_WCHAR_T
469 : /// 21.1.3.2 char_traits specializations
470 : template<>
471 : struct char_traits<wchar_t>
472 : {
473 : typedef wchar_t char_type;
474 : typedef wint_t int_type;
475 : #if _GLIBCXX_HOSTED
476 : typedef streamoff off_type;
477 : typedef wstreampos pos_type;
478 : typedef mbstate_t state_type;
479 : #endif // HOSTED
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 : #if _GLIBCXX_HOSTED
586 : static _GLIBCXX_CONSTEXPR int_type
587 : eof() _GLIBCXX_NOEXCEPT
588 : { return static_cast<int_type>(WEOF); }
589 :
590 : static _GLIBCXX_CONSTEXPR int_type
591 : not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
592 : { return eq_int_type(__c, eof()) ? 0 : __c; }
593 : #endif // HOSTED
594 : };
595 : #else // _GLIBCXX_USE_WCHAR_T
596 : template<>
597 : struct char_traits<wchar_t> : public __gnu_cxx::char_traits<wchar_t>
598 : { };
599 : #endif //_GLIBCXX_USE_WCHAR_T
600 :
601 : #ifdef _GLIBCXX_USE_CHAR8_T
602 : template<>
603 : struct char_traits<char8_t>
604 : {
605 : typedef char8_t char_type;
606 : typedef unsigned int int_type;
607 : #if _GLIBCXX_HOSTED
608 : typedef u8streampos pos_type;
609 : typedef streamoff off_type;
610 : typedef mbstate_t state_type;
611 : #endif // HOSTED
612 : #if __cpp_lib_three_way_comparison
613 : using comparison_category = strong_ordering;
614 : #endif
615 :
616 : static _GLIBCXX17_CONSTEXPR void
617 : assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
618 : {
619 : #if __cpp_constexpr_dynamic_alloc
620 : if (std::__is_constant_evaluated())
621 : std::construct_at(__builtin_addressof(__c1), __c2);
622 : else
623 : #endif
624 : __c1 = __c2;
625 : }
626 :
627 : static _GLIBCXX_CONSTEXPR bool
628 : eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
629 : { return __c1 == __c2; }
630 :
631 : static _GLIBCXX_CONSTEXPR bool
632 : lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
633 : { return __c1 < __c2; }
634 :
635 : static _GLIBCXX17_CONSTEXPR int
636 : compare(const char_type* __s1, const char_type* __s2, size_t __n)
637 : {
638 : if (__n == 0)
639 : return 0;
640 : #if __cplusplus >= 201703L
641 : if (std::__is_constant_evaluated())
642 : return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
643 : #endif
644 : return __builtin_memcmp(__s1, __s2, __n);
645 : }
646 :
647 : static _GLIBCXX17_CONSTEXPR size_t
648 : length(const char_type* __s)
649 : {
650 : #if __cplusplus >= 201703L
651 : if (std::__is_constant_evaluated())
652 : return __gnu_cxx::char_traits<char_type>::length(__s);
653 : #endif
654 : size_t __i = 0;
655 : while (!eq(__s[__i], char_type()))
656 : ++__i;
657 : return __i;
658 : }
659 :
660 : static _GLIBCXX17_CONSTEXPR const char_type*
661 : find(const char_type* __s, size_t __n, const char_type& __a)
662 : {
663 : if (__n == 0)
664 : return 0;
665 : #if __cplusplus >= 201703L
666 : if (std::__is_constant_evaluated())
667 : return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
668 : #endif
669 : return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
670 : }
671 :
672 : static _GLIBCXX20_CONSTEXPR char_type*
673 : move(char_type* __s1, const char_type* __s2, size_t __n)
674 : {
675 : if (__n == 0)
676 : return __s1;
677 : #if __cplusplus >= 202002L
678 : if (std::__is_constant_evaluated())
679 : return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
680 : #endif
681 : return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
682 : }
683 :
684 : static _GLIBCXX20_CONSTEXPR char_type*
685 : copy(char_type* __s1, const char_type* __s2, size_t __n)
686 : {
687 : if (__n == 0)
688 : return __s1;
689 : #if __cplusplus >= 202002L
690 : if (std::__is_constant_evaluated())
691 : return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
692 : #endif
693 : return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
694 : }
695 :
696 : static _GLIBCXX20_CONSTEXPR char_type*
697 : assign(char_type* __s, size_t __n, char_type __a)
698 : {
699 : if (__n == 0)
700 : return __s;
701 : #if __cplusplus >= 202002L
702 : if (std::__is_constant_evaluated())
703 : return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
704 : #endif
705 : return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
706 : }
707 :
708 : static _GLIBCXX_CONSTEXPR char_type
709 : to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
710 : { return char_type(__c); }
711 :
712 : static _GLIBCXX_CONSTEXPR int_type
713 : to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
714 : { return int_type(__c); }
715 :
716 : static _GLIBCXX_CONSTEXPR bool
717 : eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
718 : { return __c1 == __c2; }
719 :
720 : #if _GLIBCXX_HOSTED
721 : static _GLIBCXX_CONSTEXPR int_type
722 : eof() _GLIBCXX_NOEXCEPT
723 : { return static_cast<int_type>(-1); }
724 :
725 : static _GLIBCXX_CONSTEXPR int_type
726 : not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
727 : { return eq_int_type(__c, eof()) ? 0 : __c; }
728 : #endif // HOSTED
729 : };
730 : #endif //_GLIBCXX_USE_CHAR8_T
731 :
732 : _GLIBCXX_END_NAMESPACE_VERSION
733 : } // namespace
734 :
735 : #if __cplusplus >= 201103L
736 :
737 : namespace std _GLIBCXX_VISIBILITY(default)
738 : {
739 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
740 :
741 : template<>
742 : struct char_traits<char16_t>
743 : {
744 : typedef char16_t char_type;
745 : #ifdef __UINT_LEAST16_TYPE__
746 : typedef __UINT_LEAST16_TYPE__ int_type;
747 : #else
748 : typedef uint_least16_t int_type;
749 : #endif
750 : #if _GLIBCXX_HOSTED
751 : typedef streamoff off_type;
752 : typedef u16streampos pos_type;
753 : typedef mbstate_t state_type;
754 : #endif // HOSTED
755 : #if __cpp_lib_three_way_comparison
756 : using comparison_category = strong_ordering;
757 : #endif
758 :
759 : static _GLIBCXX17_CONSTEXPR void
760 : assign(char_type& __c1, const char_type& __c2) noexcept
761 : {
762 : #if __cpp_constexpr_dynamic_alloc
763 : if (std::__is_constant_evaluated())
764 : std::construct_at(__builtin_addressof(__c1), __c2);
765 : else
766 : #endif
767 : __c1 = __c2;
768 : }
769 :
770 : static constexpr bool
771 : eq(const char_type& __c1, const char_type& __c2) noexcept
772 : { return __c1 == __c2; }
773 :
774 : static constexpr bool
775 : lt(const char_type& __c1, const char_type& __c2) noexcept
776 : { return __c1 < __c2; }
777 :
778 : static _GLIBCXX17_CONSTEXPR int
779 : compare(const char_type* __s1, const char_type* __s2, size_t __n)
780 : {
781 : for (size_t __i = 0; __i < __n; ++__i)
782 : if (lt(__s1[__i], __s2[__i]))
783 : return -1;
784 : else if (lt(__s2[__i], __s1[__i]))
785 : return 1;
786 : return 0;
787 : }
788 :
789 : static _GLIBCXX17_CONSTEXPR size_t
790 : length(const char_type* __s)
791 : {
792 : size_t __i = 0;
793 : while (!eq(__s[__i], char_type()))
794 : ++__i;
795 : return __i;
796 : }
797 :
798 : static _GLIBCXX17_CONSTEXPR const char_type*
799 : find(const char_type* __s, size_t __n, const char_type& __a)
800 : {
801 : for (size_t __i = 0; __i < __n; ++__i)
802 : if (eq(__s[__i], __a))
803 : return __s + __i;
804 : return 0;
805 : }
806 :
807 : static _GLIBCXX20_CONSTEXPR char_type*
808 : move(char_type* __s1, const char_type* __s2, size_t __n)
809 : {
810 : if (__n == 0)
811 : return __s1;
812 : #if __cplusplus >= 202002L
813 : if (std::__is_constant_evaluated())
814 : return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
815 : #endif
816 : return (static_cast<char_type*>
817 : (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
818 : }
819 :
820 : static _GLIBCXX20_CONSTEXPR char_type*
821 : copy(char_type* __s1, const char_type* __s2, size_t __n)
822 : {
823 : if (__n == 0)
824 : return __s1;
825 : #if __cplusplus >= 202002L
826 : if (std::__is_constant_evaluated())
827 : return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
828 : #endif
829 : return (static_cast<char_type*>
830 : (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
831 : }
832 :
833 : static _GLIBCXX20_CONSTEXPR char_type*
834 : assign(char_type* __s, size_t __n, char_type __a)
835 : {
836 : for (size_t __i = 0; __i < __n; ++__i)
837 : assign(__s[__i], __a);
838 : return __s;
839 : }
840 :
841 : static constexpr char_type
842 : to_char_type(const int_type& __c) noexcept
843 : { return char_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 : #if _GLIBCXX_HOSTED
850 : static constexpr int_type
851 : to_int_type(const char_type& __c) noexcept
852 : { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
853 :
854 : static constexpr int_type
855 : eof() noexcept
856 : { return static_cast<int_type>(-1); }
857 :
858 : static constexpr int_type
859 : not_eof(const int_type& __c) noexcept
860 : { return eq_int_type(__c, eof()) ? 0 : __c; }
861 : #else // !HOSTED
862 : static constexpr int_type
863 : to_int_type(const char_type& __c) noexcept
864 : { return int_type(__c); }
865 : #endif // !HOSTED
866 : };
867 :
868 : template<>
869 : struct char_traits<char32_t>
870 : {
871 : typedef char32_t char_type;
872 : #ifdef __UINT_LEAST32_TYPE__
873 : typedef __UINT_LEAST32_TYPE__ int_type;
874 : #else
875 : typedef uint_least32_t int_type;
876 : #endif
877 : #if _GLIBCXX_HOSTED
878 : typedef streamoff off_type;
879 : typedef u32streampos pos_type;
880 : typedef mbstate_t state_type;
881 : #endif // HOSTED
882 : #if __cpp_lib_three_way_comparison
883 : using comparison_category = strong_ordering;
884 : #endif
885 :
886 : static _GLIBCXX17_CONSTEXPR void
887 : assign(char_type& __c1, const char_type& __c2) noexcept
888 : {
889 : #if __cpp_constexpr_dynamic_alloc
890 : if (std::__is_constant_evaluated())
891 : std::construct_at(__builtin_addressof(__c1), __c2);
892 : else
893 : #endif
894 : __c1 = __c2;
895 : }
896 :
897 : static constexpr bool
898 : eq(const char_type& __c1, const char_type& __c2) noexcept
899 : { return __c1 == __c2; }
900 :
901 : static constexpr bool
902 : lt(const char_type& __c1, const char_type& __c2) noexcept
903 : { return __c1 < __c2; }
904 :
905 : static _GLIBCXX17_CONSTEXPR int
906 : compare(const char_type* __s1, const char_type* __s2, size_t __n)
907 : {
908 : for (size_t __i = 0; __i < __n; ++__i)
909 : if (lt(__s1[__i], __s2[__i]))
910 : return -1;
911 : else if (lt(__s2[__i], __s1[__i]))
912 : return 1;
913 : return 0;
914 : }
915 :
916 : static _GLIBCXX17_CONSTEXPR size_t
917 : length(const char_type* __s)
918 : {
919 : size_t __i = 0;
920 : while (!eq(__s[__i], char_type()))
921 : ++__i;
922 : return __i;
923 : }
924 :
925 : static _GLIBCXX17_CONSTEXPR const char_type*
926 : find(const char_type* __s, size_t __n, const char_type& __a)
927 : {
928 : for (size_t __i = 0; __i < __n; ++__i)
929 : if (eq(__s[__i], __a))
930 : return __s + __i;
931 : return 0;
932 : }
933 :
934 : static _GLIBCXX20_CONSTEXPR char_type*
935 : move(char_type* __s1, const char_type* __s2, size_t __n)
936 : {
937 : if (__n == 0)
938 : return __s1;
939 : #if __cplusplus >= 202002L
940 : if (std::__is_constant_evaluated())
941 : return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
942 : #endif
943 : return (static_cast<char_type*>
944 : (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
945 : }
946 :
947 : static _GLIBCXX20_CONSTEXPR char_type*
948 : copy(char_type* __s1, const char_type* __s2, size_t __n)
949 : {
950 : if (__n == 0)
951 : return __s1;
952 : #if __cplusplus >= 202002L
953 : if (std::__is_constant_evaluated())
954 : return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
955 : #endif
956 : return (static_cast<char_type*>
957 : (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
958 : }
959 :
960 : static _GLIBCXX20_CONSTEXPR char_type*
961 : assign(char_type* __s, size_t __n, char_type __a)
962 : {
963 : for (size_t __i = 0; __i < __n; ++__i)
964 : assign(__s[__i], __a);
965 : return __s;
966 : }
967 :
968 : static constexpr char_type
969 : to_char_type(const int_type& __c) noexcept
970 : { return char_type(__c); }
971 :
972 : static constexpr int_type
973 : to_int_type(const char_type& __c) noexcept
974 : { return int_type(__c); }
975 :
976 : static constexpr bool
977 : eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
978 : { return __c1 == __c2; }
979 :
980 : #if _GLIBCXX_HOSTED
981 : static constexpr int_type
982 : eof() noexcept
983 : { return static_cast<int_type>(-1); }
984 :
985 : static constexpr int_type
986 : not_eof(const int_type& __c) noexcept
987 : { return eq_int_type(__c, eof()) ? 0 : __c; }
988 : #endif // HOSTED
989 : };
990 :
991 : #if __cpp_lib_three_way_comparison
992 : namespace __detail
993 : {
994 : template<typename _ChTraits>
995 : constexpr auto
996 : __char_traits_cmp_cat(int __cmp) noexcept
997 : {
998 : if constexpr (requires { typename _ChTraits::comparison_category; })
999 : {
1000 : using _Cat = typename _ChTraits::comparison_category;
1001 : static_assert( !is_void_v<common_comparison_category_t<_Cat>> );
1002 : return static_cast<_Cat>(__cmp <=> 0);
1003 : }
1004 : else
1005 : return static_cast<weak_ordering>(__cmp <=> 0);
1006 : }
1007 : } // namespace __detail
1008 : #endif // C++20
1009 :
1010 : #pragma GCC diagnostic pop
1011 :
1012 : _GLIBCXX_END_NAMESPACE_VERSION
1013 : } // namespace
1014 :
1015 : #endif // C++11
1016 :
1017 : #endif // _CHAR_TRAITS_H
|