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