Line data Source code
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 (__n == 0)
259 : return __s1;
260 : #if __cplusplus >= 202002L
261 : if (std::__is_constant_evaluated())
262 : {
263 : for (std::size_t __i = 0; __i < __n; ++__i)
264 : std::construct_at(__s1 + __i, __s2[__i]);
265 : return __s1;
266 : }
267 : #endif
268 : __builtin_memcpy(__s1, __s2, __n * sizeof(char_type));
269 : return __s1;
270 : }
271 :
272 : template<typename _CharT>
273 : _GLIBCXX20_CONSTEXPR
274 : typename char_traits<_CharT>::char_type*
275 : char_traits<_CharT>::
276 : assign(char_type* __s, std::size_t __n, char_type __a)
277 : {
278 : #if __cplusplus >= 202002L
279 : if (std::__is_constant_evaluated())
280 : {
281 : for (std::size_t __i = 0; __i < __n; ++__i)
282 : std::construct_at(__s + __i, __a);
283 : return __s;
284 : }
285 : #endif
286 :
287 : if _GLIBCXX17_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT))
288 : {
289 : if (__n)
290 : {
291 : unsigned char __c;
292 : __builtin_memcpy(&__c, __builtin_addressof(__a), 1);
293 : __builtin_memset(__s, __c, __n);
294 : }
295 : }
296 : else
297 : {
298 : for (std::size_t __i = 0; __i < __n; ++__i)
299 : __s[__i] = __a;
300 : }
301 : return __s;
302 : }
303 :
304 : _GLIBCXX_END_NAMESPACE_VERSION
305 : } // namespace
306 :
307 : namespace std _GLIBCXX_VISIBILITY(default)
308 : {
309 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
310 :
311 : #ifdef __cpp_lib_is_constant_evaluated
312 : // Unofficial macro indicating P1032R1 support in C++20
313 : # define __cpp_lib_constexpr_char_traits 201811L
314 : #elif __cplusplus >= 201703L && _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED
315 : // Unofficial macro indicating P0426R1 support in C++17
316 : # define __cpp_lib_constexpr_char_traits 201611L
317 : #endif
318 :
319 : // 21.1
320 : /**
321 : * @brief Basis for explicit traits specializations.
322 : *
323 : * @note For any given actual character type, this definition is
324 : * probably wrong. Since this is just a thin wrapper around
325 : * __gnu_cxx::char_traits, it is possible to achieve a more
326 : * appropriate definition by specializing __gnu_cxx::char_traits.
327 : *
328 : * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
329 : * for advice on how to make use of this class for @a unusual character
330 : * types. Also, check out include/ext/pod_char_traits.h.
331 : */
332 : template<typename _CharT>
333 : struct char_traits : public __gnu_cxx::char_traits<_CharT>
334 : { };
335 :
336 :
337 : /// 21.1.3.1 char_traits specializations
338 : template<>
339 : struct char_traits<char>
340 : {
341 : typedef char char_type;
342 : typedef int int_type;
343 : typedef streampos pos_type;
344 : typedef streamoff off_type;
345 : typedef mbstate_t state_type;
346 : #if __cpp_lib_three_way_comparison
347 : using comparison_category = strong_ordering;
348 : #endif
349 :
350 : static _GLIBCXX17_CONSTEXPR void
351 82511 : assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
352 : {
353 : #if __cpp_constexpr_dynamic_alloc
354 : if (std::__is_constant_evaluated())
355 : std::construct_at(__builtin_addressof(__c1), __c2);
356 : else
357 : #endif
358 24248 : __c1 = __c2;
359 : }
360 :
361 : static _GLIBCXX_CONSTEXPR bool
362 : eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
363 : { return __c1 == __c2; }
364 :
365 : static _GLIBCXX_CONSTEXPR bool
366 : lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
367 : {
368 : // LWG 467.
369 : return (static_cast<unsigned char>(__c1)
370 : < static_cast<unsigned char>(__c2));
371 : }
372 :
373 : static _GLIBCXX17_CONSTEXPR int
374 0 : compare(const char_type* __s1, const char_type* __s2, size_t __n)
375 : {
376 0 : if (__n == 0)
377 : return 0;
378 : #if __cplusplus >= 201703L
379 0 : if (std::__is_constant_evaluated())
380 : {
381 : for (size_t __i = 0; __i < __n; ++__i)
382 : if (lt(__s1[__i], __s2[__i]))
383 : return -1;
384 : else if (lt(__s2[__i], __s1[__i]))
385 : return 1;
386 : return 0;
387 : }
388 : #endif
389 0 : return __builtin_memcmp(__s1, __s2, __n);
390 : }
391 :
392 : static _GLIBCXX17_CONSTEXPR size_t
393 5737 : length(const char_type* __s)
394 : {
395 : #if __cplusplus >= 201703L
396 5737 : if (std::__is_constant_evaluated())
397 : return __gnu_cxx::char_traits<char_type>::length(__s);
398 : #endif
399 5737 : return __builtin_strlen(__s);
400 : }
401 :
402 : static _GLIBCXX17_CONSTEXPR const char_type*
403 : find(const char_type* __s, size_t __n, const char_type& __a)
404 : {
405 : if (__n == 0)
406 : return 0;
407 : #if __cplusplus >= 201703L
408 : if (std::__is_constant_evaluated())
409 : return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
410 : #endif
411 : return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
412 : }
413 :
414 : static _GLIBCXX20_CONSTEXPR char_type*
415 : move(char_type* __s1, const char_type* __s2, size_t __n)
416 : {
417 : if (__n == 0)
418 : return __s1;
419 : #if __cplusplus >= 202002L
420 : if (std::__is_constant_evaluated())
421 : return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
422 : #endif
423 : return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
424 : }
425 :
426 : static _GLIBCXX20_CONSTEXPR char_type*
427 : copy(char_type* __s1, const char_type* __s2, size_t __n)
428 : {
429 : if (__n == 0)
430 : return __s1;
431 : #if __cplusplus >= 202002L
432 : if (std::__is_constant_evaluated())
433 : return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
434 : #endif
435 : return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
436 : }
437 :
438 : static _GLIBCXX20_CONSTEXPR char_type*
439 : assign(char_type* __s, size_t __n, char_type __a)
440 : {
441 : if (__n == 0)
442 : return __s;
443 : #if __cplusplus >= 202002L
444 : if (std::__is_constant_evaluated())
445 : return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
446 : #endif
447 : return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
448 : }
449 :
450 : static _GLIBCXX_CONSTEXPR char_type
451 : to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
452 : { return static_cast<char_type>(__c); }
453 :
454 : // To keep both the byte 0xff and the eof symbol 0xffffffff
455 : // from ending up as 0xffffffff.
456 : static _GLIBCXX_CONSTEXPR int_type
457 : to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
458 : { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
459 :
460 : static _GLIBCXX_CONSTEXPR bool
461 : eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
462 : { return __c1 == __c2; }
463 :
464 : static _GLIBCXX_CONSTEXPR int_type
465 : eof() _GLIBCXX_NOEXCEPT
466 : { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
467 :
468 : static _GLIBCXX_CONSTEXPR int_type
469 : not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
470 : { return (__c == eof()) ? 0 : __c; }
471 : };
472 :
473 :
474 : #ifdef _GLIBCXX_USE_WCHAR_T
475 : /// 21.1.3.2 char_traits specializations
476 : template<>
477 : struct char_traits<wchar_t>
478 : {
479 : typedef wchar_t char_type;
480 : typedef wint_t int_type;
481 : typedef streamoff off_type;
482 : typedef wstreampos pos_type;
483 : typedef mbstate_t state_type;
484 : #if __cpp_lib_three_way_comparison
485 : using comparison_category = strong_ordering;
486 : #endif
487 :
488 : static _GLIBCXX17_CONSTEXPR void
489 : assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
490 : {
491 : #if __cpp_constexpr_dynamic_alloc
492 : if (std::__is_constant_evaluated())
493 : std::construct_at(__builtin_addressof(__c1), __c2);
494 : else
495 : #endif
496 : __c1 = __c2;
497 : }
498 :
499 : static _GLIBCXX_CONSTEXPR bool
500 : eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
501 : { return __c1 == __c2; }
502 :
503 : static _GLIBCXX_CONSTEXPR bool
504 : lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
505 : { return __c1 < __c2; }
506 :
507 : static _GLIBCXX17_CONSTEXPR int
508 : compare(const char_type* __s1, const char_type* __s2, size_t __n)
509 : {
510 : if (__n == 0)
511 : return 0;
512 : #if __cplusplus >= 201703L
513 : if (std::__is_constant_evaluated())
514 : return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
515 : #endif
516 : return wmemcmp(__s1, __s2, __n);
517 : }
518 :
519 : static _GLIBCXX17_CONSTEXPR size_t
520 : length(const char_type* __s)
521 : {
522 : #if __cplusplus >= 201703L
523 : if (std::__is_constant_evaluated())
524 : return __gnu_cxx::char_traits<char_type>::length(__s);
525 : #endif
526 : return wcslen(__s);
527 : }
528 :
529 : static _GLIBCXX17_CONSTEXPR const char_type*
530 : find(const char_type* __s, size_t __n, const char_type& __a)
531 : {
532 : if (__n == 0)
533 : return 0;
534 : #if __cplusplus >= 201703L
535 : if (std::__is_constant_evaluated())
536 : return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
537 : #endif
538 : return wmemchr(__s, __a, __n);
539 : }
540 :
541 : static _GLIBCXX20_CONSTEXPR char_type*
542 : move(char_type* __s1, const char_type* __s2, size_t __n)
543 : {
544 : if (__n == 0)
545 : return __s1;
546 : #if __cplusplus >= 202002L
547 : if (std::__is_constant_evaluated())
548 : return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
549 : #endif
550 : return wmemmove(__s1, __s2, __n);
551 : }
552 :
553 : static _GLIBCXX20_CONSTEXPR char_type*
554 : copy(char_type* __s1, const char_type* __s2, size_t __n)
555 : {
556 : if (__n == 0)
557 : return __s1;
558 : #if __cplusplus >= 202002L
559 : if (std::__is_constant_evaluated())
560 : return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
561 : #endif
562 : return wmemcpy(__s1, __s2, __n);
563 : }
564 :
565 : static _GLIBCXX20_CONSTEXPR char_type*
566 : assign(char_type* __s, size_t __n, char_type __a)
567 : {
568 : if (__n == 0)
569 : return __s;
570 : #if __cplusplus >= 202002L
571 : if (std::__is_constant_evaluated())
572 : return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
573 : #endif
574 : return wmemset(__s, __a, __n);
575 : }
576 :
577 : static _GLIBCXX_CONSTEXPR char_type
578 : to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
579 : { return char_type(__c); }
580 :
581 : static _GLIBCXX_CONSTEXPR int_type
582 : to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
583 : { return int_type(__c); }
584 :
585 : static _GLIBCXX_CONSTEXPR bool
586 : eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
587 : { return __c1 == __c2; }
588 :
589 : static _GLIBCXX_CONSTEXPR int_type
590 : eof() _GLIBCXX_NOEXCEPT
591 : { return static_cast<int_type>(WEOF); }
592 :
593 : static _GLIBCXX_CONSTEXPR int_type
594 : not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
595 : { return eq_int_type(__c, eof()) ? 0 : __c; }
596 : };
597 : #else // _GLIBCXX_USE_WCHAR_T
598 : template<>
599 : struct char_traits<wchar_t> : public __gnu_cxx::char_traits<wchar_t>
600 : { };
601 : #endif //_GLIBCXX_USE_WCHAR_T
602 :
603 : #ifdef _GLIBCXX_USE_CHAR8_T
604 : template<>
605 : struct char_traits<char8_t>
606 : {
607 : typedef char8_t char_type;
608 : typedef unsigned int int_type;
609 : typedef u8streampos pos_type;
610 : typedef streamoff off_type;
611 : typedef mbstate_t state_type;
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 : static _GLIBCXX_CONSTEXPR int_type
721 : eof() _GLIBCXX_NOEXCEPT
722 : { return static_cast<int_type>(-1); }
723 :
724 : static _GLIBCXX_CONSTEXPR int_type
725 : not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
726 : { return eq_int_type(__c, eof()) ? 0 : __c; }
727 : };
728 : #endif //_GLIBCXX_USE_CHAR8_T
729 :
730 : _GLIBCXX_END_NAMESPACE_VERSION
731 : } // namespace
732 :
733 : #if __cplusplus >= 201103L
734 :
735 : #include <cstdint>
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 _GLIBCXX_USE_C99_STDINT_TR1
746 : typedef uint_least16_t int_type;
747 : #elif defined __UINT_LEAST16_TYPE__
748 : typedef __UINT_LEAST16_TYPE__ int_type;
749 : #else
750 : typedef make_unsigned<char16_t>::type int_type;
751 : #endif
752 : typedef streamoff off_type;
753 : typedef u16streampos pos_type;
754 : typedef mbstate_t state_type;
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 int_type
846 : to_int_type(const char_type& __c) noexcept
847 : { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
848 :
849 : static constexpr bool
850 : eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
851 : { return __c1 == __c2; }
852 :
853 : static constexpr int_type
854 : eof() noexcept
855 : { return static_cast<int_type>(-1); }
856 :
857 : static constexpr int_type
858 : not_eof(const int_type& __c) noexcept
859 : { return eq_int_type(__c, eof()) ? 0 : __c; }
860 : };
861 :
862 : template<>
863 : struct char_traits<char32_t>
864 : {
865 : typedef char32_t char_type;
866 : #ifdef _GLIBCXX_USE_C99_STDINT_TR1
867 : typedef uint_least32_t int_type;
868 : #elif defined __UINT_LEAST32_TYPE__
869 : typedef __UINT_LEAST32_TYPE__ int_type;
870 : #else
871 : typedef make_unsigned<char32_t>::type int_type;
872 : #endif
873 : typedef streamoff off_type;
874 : typedef u32streampos pos_type;
875 : typedef mbstate_t state_type;
876 : #if __cpp_lib_three_way_comparison
877 : using comparison_category = strong_ordering;
878 : #endif
879 :
880 : static _GLIBCXX17_CONSTEXPR void
881 : assign(char_type& __c1, const char_type& __c2) noexcept
882 : {
883 : #if __cpp_constexpr_dynamic_alloc
884 : if (std::__is_constant_evaluated())
885 : std::construct_at(__builtin_addressof(__c1), __c2);
886 : else
887 : #endif
888 : __c1 = __c2;
889 : }
890 :
891 : static constexpr bool
892 : eq(const char_type& __c1, const char_type& __c2) noexcept
893 : { return __c1 == __c2; }
894 :
895 : static constexpr bool
896 : lt(const char_type& __c1, const char_type& __c2) noexcept
897 : { return __c1 < __c2; }
898 :
899 : static _GLIBCXX17_CONSTEXPR int
900 : compare(const char_type* __s1, const char_type* __s2, size_t __n)
901 : {
902 : for (size_t __i = 0; __i < __n; ++__i)
903 : if (lt(__s1[__i], __s2[__i]))
904 : return -1;
905 : else if (lt(__s2[__i], __s1[__i]))
906 : return 1;
907 : return 0;
908 : }
909 :
910 : static _GLIBCXX17_CONSTEXPR size_t
911 : length(const char_type* __s)
912 : {
913 : size_t __i = 0;
914 : while (!eq(__s[__i], char_type()))
915 : ++__i;
916 : return __i;
917 : }
918 :
919 : static _GLIBCXX17_CONSTEXPR const char_type*
920 : find(const char_type* __s, size_t __n, const char_type& __a)
921 : {
922 : for (size_t __i = 0; __i < __n; ++__i)
923 : if (eq(__s[__i], __a))
924 : return __s + __i;
925 : return 0;
926 : }
927 :
928 : static _GLIBCXX20_CONSTEXPR char_type*
929 : move(char_type* __s1, const char_type* __s2, size_t __n)
930 : {
931 : if (__n == 0)
932 : return __s1;
933 : #if __cplusplus >= 202002L
934 : if (std::__is_constant_evaluated())
935 : return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
936 : #endif
937 : return (static_cast<char_type*>
938 : (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
939 : }
940 :
941 : static _GLIBCXX20_CONSTEXPR char_type*
942 : copy(char_type* __s1, const char_type* __s2, size_t __n)
943 : {
944 : if (__n == 0)
945 : return __s1;
946 : #if __cplusplus >= 202002L
947 : if (std::__is_constant_evaluated())
948 : return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
949 : #endif
950 : return (static_cast<char_type*>
951 : (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
952 : }
953 :
954 : static _GLIBCXX20_CONSTEXPR char_type*
955 : assign(char_type* __s, size_t __n, char_type __a)
956 : {
957 : for (size_t __i = 0; __i < __n; ++__i)
958 : assign(__s[__i], __a);
959 : return __s;
960 : }
961 :
962 : static constexpr char_type
963 : to_char_type(const int_type& __c) noexcept
964 : { return char_type(__c); }
965 :
966 : static constexpr int_type
967 : to_int_type(const char_type& __c) noexcept
968 : { return int_type(__c); }
969 :
970 : static constexpr bool
971 : eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
972 : { return __c1 == __c2; }
973 :
974 : static constexpr int_type
975 : eof() noexcept
976 : { return static_cast<int_type>(-1); }
977 :
978 : static constexpr int_type
979 : not_eof(const int_type& __c) noexcept
980 : { return eq_int_type(__c, eof()) ? 0 : __c; }
981 : };
982 :
983 : #if __cpp_lib_three_way_comparison
984 : namespace __detail
985 : {
986 : template<typename _ChTraits>
987 : constexpr auto
988 : __char_traits_cmp_cat(int __cmp) noexcept
989 : {
990 : if constexpr (requires { typename _ChTraits::comparison_category; })
991 : {
992 : using _Cat = typename _ChTraits::comparison_category;
993 : static_assert( !is_void_v<common_comparison_category_t<_Cat>> );
994 : return static_cast<_Cat>(__cmp <=> 0);
995 : }
996 : else
997 : return static_cast<weak_ordering>(__cmp <=> 0);
998 : }
999 : } // namespace __detail
1000 : #endif // C++20
1001 :
1002 : #pragma GCC diagnostic pop
1003 :
1004 : _GLIBCXX_END_NAMESPACE_VERSION
1005 : } // namespace
1006 :
1007 : #endif // C++11
1008 :
1009 : #endif // _CHAR_TRAITS_H
|