libstdc++
char_traits.h
Go to the documentation of this file.
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  eq(const char_type& __c1, const char_type& __c2)
137  { 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
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  char_traits<_CharT>::
200  length(const char_type* __p)
201  {
202  std::size_t __i = 0;
203  while (!eq(__p[__i], char_type()))
204  ++__i;
205  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  length(const char_type* __s)
386  {
387 #if __cplusplus >= 201703L
388  if (std::__is_constant_evaluated())
390 #endif
391  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  copy(char_type* __s1, const char_type* __s2, size_t __n)
420  {
421  if (__n == 0)
422  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  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())
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())
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
ISO C++ entities toplevel namespace is std.
fpos< mbstate_t > u32streampos
File position for char32_t streams.
Definition: postypes.h:217
long long streamoff
Type used by fpos, char_traits<char>, and char_traits<wchar_t>.
Definition: postypes.h:64
fpos< mbstate_t > u16streampos
File position for char16_t streams.
Definition: postypes.h:215
GNU extensions for public use.
Mapping from character type to associated types.
Definition: char_traits.h:85
Base class used to implement std::char_traits.
Definition: char_traits.h:112
Basis for explicit traits specializations.
Definition: char_traits.h:324
Class representing stream positions.
Definition: postypes.h:83