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 | 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 | __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 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
375 | { |
376 | if (__n == 0) |
377 | return 0; |
378 | #if __cplusplus >= 201703L |
379 | 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 | return __builtin_memcmp(__s1, __s2, __n); |
390 | } |
391 | |
392 | static _GLIBCXX17_CONSTEXPR size_t |
393 | length(const char_type* __s) |
394 | { |
395 | #if __cplusplus >= 201703L |
396 | if (std::__is_constant_evaluated()) |
397 | return __gnu_cxx::char_traits<char_type>::length(__s); |
398 | #endif |
399 | 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 |
1010 | |