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-2026 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 #pragma GCC diagnostic push
288 #pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
289  if _GLIBCXX_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT))
290  {
291  if (__n)
292  {
293  unsigned char __c;
294  __builtin_memcpy(&__c, __builtin_addressof(__a), 1);
295  __builtin_memset(__s, __c, __n);
296  }
297  }
298  else
299  {
300  for (std::size_t __i = 0; __i < __n; ++__i)
301  __s[__i] = __a;
302  }
303 #pragma GCC diagnostic pop
304  return __s;
305  }
306 
307 _GLIBCXX_END_NAMESPACE_VERSION
308 } // namespace
309 
310 namespace std _GLIBCXX_VISIBILITY(default)
311 {
312 _GLIBCXX_BEGIN_NAMESPACE_VERSION
313 
314  // 21.1
315  /**
316  * @brief Basis for explicit traits specializations.
317  *
318  * @note For any given actual character type, this definition is
319  * probably wrong. Since this is just a thin wrapper around
320  * __gnu_cxx::char_traits, it is possible to achieve a more
321  * appropriate definition by specializing __gnu_cxx::char_traits.
322  *
323  * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
324  * for advice on how to make use of this class for @a unusual character
325  * types. Also, check out include/ext/pod_char_traits.h.
326  */
327  template<typename _CharT>
328  struct char_traits : public __gnu_cxx::char_traits<_CharT>
329  { };
330 
331 
332  /// 21.1.3.1 char_traits specializations
333  template<>
334  struct char_traits<char>
335  {
336  typedef char char_type;
337  typedef int int_type;
338 #if _GLIBCXX_HOSTED
339  typedef streampos pos_type;
340  typedef streamoff off_type;
341  typedef mbstate_t state_type;
342 #endif // HOSTED
343 #if __cpp_lib_three_way_comparison
344  using comparison_category = strong_ordering;
345 #endif
346 
347  static _GLIBCXX17_CONSTEXPR void
348  assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
349  {
350 #if __cpp_constexpr_dynamic_alloc
351  if (std::__is_constant_evaluated())
352  std::construct_at(__builtin_addressof(__c1), __c2);
353  else
354 #endif
355  __c1 = __c2;
356  }
357 
358  static _GLIBCXX_CONSTEXPR bool
359  eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
360  { return __c1 == __c2; }
361 
362  static _GLIBCXX_CONSTEXPR bool
363  lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
364  {
365  // LWG 467.
366  return (static_cast<unsigned char>(__c1)
367  < static_cast<unsigned char>(__c2));
368  }
369 
370  static _GLIBCXX17_CONSTEXPR int
371  compare(const char_type* __s1, const char_type* __s2, size_t __n)
372  {
373  if (__n == 0)
374  return 0;
375 #if __cplusplus >= 201703L
376  if (std::__is_constant_evaluated())
377  {
378  for (size_t __i = 0; __i < __n; ++__i)
379  if (lt(__s1[__i], __s2[__i]))
380  return -1;
381  else if (lt(__s2[__i], __s1[__i]))
382  return 1;
383  return 0;
384  }
385 #endif
386  return __builtin_memcmp(__s1, __s2, __n);
387  }
388 
389  static _GLIBCXX17_CONSTEXPR size_t
390  length(const char_type* __s)
391  {
392 #if __cplusplus >= 201703L
393  if (std::__is_constant_evaluated())
395 #endif
396  return __builtin_strlen(__s);
397  }
398 
399  static _GLIBCXX17_CONSTEXPR const char_type*
400  find(const char_type* __s, size_t __n, const char_type& __a)
401  {
402  if (__n == 0)
403  return 0;
404 #if __cplusplus >= 201703L
405  if (std::__is_constant_evaluated())
406  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
407 #endif
408  return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
409  }
410 
411  static _GLIBCXX20_CONSTEXPR char_type*
412  move(char_type* __s1, const char_type* __s2, size_t __n)
413  {
414  if (__n == 0)
415  return __s1;
416 #if __cplusplus >= 202002L
417  if (std::__is_constant_evaluated())
418  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
419 #endif
420  return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
421  }
422 
423  static _GLIBCXX20_CONSTEXPR char_type*
424  copy(char_type* __s1, const char_type* __s2, size_t __n)
425  {
426  if (__n == 0)
427  return __s1;
428 #if __cplusplus >= 202002L
429  if (std::__is_constant_evaluated())
430  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
431 #endif
432  return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
433  }
434 
435  static _GLIBCXX20_CONSTEXPR char_type*
436  assign(char_type* __s, size_t __n, char_type __a)
437  {
438  if (__n == 0)
439  return __s;
440 #if __cplusplus >= 202002L
441  if (std::__is_constant_evaluated())
442  return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
443 #endif
444  return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
445  }
446 
447  static _GLIBCXX_CONSTEXPR char_type
448  to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
449  { return static_cast<char_type>(__c); }
450 
451  // To keep both the byte 0xff and the eof symbol 0xffffffff
452  // from ending up as 0xffffffff.
453  static _GLIBCXX_CONSTEXPR int_type
454  to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
455  { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
456 
457  static _GLIBCXX_CONSTEXPR bool
458  eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
459  { return __c1 == __c2; }
460 
461 #ifdef _GLIBCXX_STDIO_EOF
462  static _GLIBCXX_CONSTEXPR int_type
463  eof() _GLIBCXX_NOEXCEPT
464  { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
465 
466  static _GLIBCXX_CONSTEXPR int_type
467  not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
468  { return (__c == eof()) ? 0 : __c; }
469 #endif // defined(_GLIBCXX_STDIO_EOF)
470  };
471 
472 
473 #ifdef _GLIBCXX_USE_WCHAR_T
474  /// 21.1.3.2 char_traits specializations
475  template<>
476  struct char_traits<wchar_t>
477  {
478  typedef wchar_t char_type;
479  typedef wint_t int_type;
480 #if _GLIBCXX_HOSTED
481  typedef streamoff off_type;
482  typedef wstreampos pos_type;
483  typedef mbstate_t state_type;
484 #endif // HOSTED
485 #if __cpp_lib_three_way_comparison
486  using comparison_category = strong_ordering;
487 #endif
488 
489  static _GLIBCXX17_CONSTEXPR void
490  assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
491  {
492 #if __cpp_constexpr_dynamic_alloc
493  if (std::__is_constant_evaluated())
494  std::construct_at(__builtin_addressof(__c1), __c2);
495  else
496 #endif
497  __c1 = __c2;
498  }
499 
500  static _GLIBCXX_CONSTEXPR bool
501  eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
502  { return __c1 == __c2; }
503 
504  static _GLIBCXX_CONSTEXPR bool
505  lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
506  { return __c1 < __c2; }
507 
508  static _GLIBCXX17_CONSTEXPR int
509  compare(const char_type* __s1, const char_type* __s2, size_t __n)
510  {
511  if (__n == 0)
512  return 0;
513 #if __cplusplus >= 201703L
514  if (std::__is_constant_evaluated())
515  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
516 #endif
517  return wmemcmp(__s1, __s2, __n);
518  }
519 
520  static _GLIBCXX17_CONSTEXPR size_t
521  length(const char_type* __s)
522  {
523 #if __cplusplus >= 201703L
524  if (std::__is_constant_evaluated())
526 #endif
527  return wcslen(__s);
528  }
529 
530  static _GLIBCXX17_CONSTEXPR const char_type*
531  find(const char_type* __s, size_t __n, const char_type& __a)
532  {
533  if (__n == 0)
534  return 0;
535 #if __cplusplus >= 201703L
536  if (std::__is_constant_evaluated())
537  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
538 #endif
539  return wmemchr(__s, __a, __n);
540  }
541 
542  static _GLIBCXX20_CONSTEXPR char_type*
543  move(char_type* __s1, const char_type* __s2, size_t __n)
544  {
545  if (__n == 0)
546  return __s1;
547 #if __cplusplus >= 202002L
548  if (std::__is_constant_evaluated())
549  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
550 #endif
551  return wmemmove(__s1, __s2, __n);
552  }
553 
554  static _GLIBCXX20_CONSTEXPR char_type*
555  copy(char_type* __s1, const char_type* __s2, size_t __n)
556  {
557  if (__n == 0)
558  return __s1;
559 #if __cplusplus >= 202002L
560  if (std::__is_constant_evaluated())
561  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
562 #endif
563  return wmemcpy(__s1, __s2, __n);
564  }
565 
566  static _GLIBCXX20_CONSTEXPR char_type*
567  assign(char_type* __s, size_t __n, char_type __a)
568  {
569  if (__n == 0)
570  return __s;
571 #if __cplusplus >= 202002L
572  if (std::__is_constant_evaluated())
573  return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
574 #endif
575  return wmemset(__s, __a, __n);
576  }
577 
578  static _GLIBCXX_CONSTEXPR char_type
579  to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
580  { return char_type(__c); }
581 
582  static _GLIBCXX_CONSTEXPR int_type
583  to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
584  { return int_type(__c); }
585 
586  static _GLIBCXX_CONSTEXPR bool
587  eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
588  { return __c1 == __c2; }
589 
590 #if _GLIBCXX_HOSTED
591  static _GLIBCXX_CONSTEXPR int_type
592  eof() _GLIBCXX_NOEXCEPT
593  { return static_cast<int_type>(WEOF); }
594 
595  static _GLIBCXX_CONSTEXPR int_type
596  not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
597  { return eq_int_type(__c, eof()) ? 0 : __c; }
598 #endif // HOSTED
599  };
600 #else // _GLIBCXX_USE_WCHAR_T
601  template<>
602  struct char_traits<wchar_t> : public __gnu_cxx::char_traits<wchar_t>
603  { };
604 #endif //_GLIBCXX_USE_WCHAR_T
605 
606 #ifdef _GLIBCXX_USE_CHAR8_T
607  template<>
608  struct char_traits<char8_t>
609  {
610  typedef char8_t char_type;
611  typedef unsigned int int_type;
612 #if _GLIBCXX_HOSTED
613  typedef u8streampos pos_type;
614  typedef streamoff off_type;
615  typedef mbstate_t state_type;
616 #endif // HOSTED
617 #if __cpp_lib_three_way_comparison
618  using comparison_category = strong_ordering;
619 #endif
620 
621  static _GLIBCXX17_CONSTEXPR void
622  assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
623  {
624 #if __cpp_constexpr_dynamic_alloc
625  if (std::__is_constant_evaluated())
626  std::construct_at(__builtin_addressof(__c1), __c2);
627  else
628 #endif
629  __c1 = __c2;
630  }
631 
632  static _GLIBCXX_CONSTEXPR bool
633  eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
634  { return __c1 == __c2; }
635 
636  static _GLIBCXX_CONSTEXPR bool
637  lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
638  { return __c1 < __c2; }
639 
640  static _GLIBCXX17_CONSTEXPR int
641  compare(const char_type* __s1, const char_type* __s2, size_t __n)
642  {
643  if (__n == 0)
644  return 0;
645 #if __cplusplus >= 201703L
646  if (std::__is_constant_evaluated())
647  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
648 #endif
649  return __builtin_memcmp(__s1, __s2, __n);
650  }
651 
652  static _GLIBCXX17_CONSTEXPR size_t
653  length(const char_type* __s)
654  {
655 #if __cplusplus >= 201703L
656  if (std::__is_constant_evaluated())
658 #endif
659  return __builtin_strlen((const char*)__s);
660  }
661 
662  static _GLIBCXX17_CONSTEXPR const char_type*
663  find(const char_type* __s, size_t __n, const char_type& __a)
664  {
665  if (__n == 0)
666  return 0;
667 #if __cplusplus >= 201703L
668  if (std::__is_constant_evaluated())
669  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
670 #endif
671  return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
672  }
673 
674  static _GLIBCXX20_CONSTEXPR char_type*
675  move(char_type* __s1, const char_type* __s2, size_t __n)
676  {
677  if (__n == 0)
678  return __s1;
679 #if __cplusplus >= 202002L
680  if (std::__is_constant_evaluated())
681  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
682 #endif
683  return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
684  }
685 
686  static _GLIBCXX20_CONSTEXPR char_type*
687  copy(char_type* __s1, const char_type* __s2, size_t __n)
688  {
689  if (__n == 0)
690  return __s1;
691 #if __cplusplus >= 202002L
692  if (std::__is_constant_evaluated())
693  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
694 #endif
695  return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
696  }
697 
698  static _GLIBCXX20_CONSTEXPR char_type*
699  assign(char_type* __s, size_t __n, char_type __a)
700  {
701  if (__n == 0)
702  return __s;
703 #if __cplusplus >= 202002L
704  if (std::__is_constant_evaluated())
705  return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
706 #endif
707  return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
708  }
709 
710  static _GLIBCXX_CONSTEXPR char_type
711  to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
712  { return char_type(__c); }
713 
714  static _GLIBCXX_CONSTEXPR int_type
715  to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
716  { return int_type(__c); }
717 
718  static _GLIBCXX_CONSTEXPR bool
719  eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
720  { return __c1 == __c2; }
721 
722 #if _GLIBCXX_HOSTED
723  static _GLIBCXX_CONSTEXPR int_type
724  eof() _GLIBCXX_NOEXCEPT
725  { return static_cast<int_type>(-1); }
726 
727  static _GLIBCXX_CONSTEXPR int_type
728  not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
729  { return eq_int_type(__c, eof()) ? 0 : __c; }
730 #endif // HOSTED
731  };
732 #endif //_GLIBCXX_USE_CHAR8_T
733 
734 _GLIBCXX_END_NAMESPACE_VERSION
735 } // namespace
736 
737 #if __cplusplus >= 201103L
738 
739 namespace std _GLIBCXX_VISIBILITY(default)
740 {
741 _GLIBCXX_BEGIN_NAMESPACE_VERSION
742 
743  template<>
744  struct char_traits<char16_t>
745  {
746  typedef char16_t char_type;
747 #ifdef __UINT_LEAST16_TYPE__
748  typedef __UINT_LEAST16_TYPE__ int_type;
749 #else
750  typedef uint_least16_t int_type;
751 #endif
752 #if _GLIBCXX_HOSTED
753  typedef streamoff off_type;
754  typedef u16streampos pos_type;
755  typedef mbstate_t state_type;
756 #endif // HOSTED
757 #if __cpp_lib_three_way_comparison
758  using comparison_category = strong_ordering;
759 #endif
760 
761  static _GLIBCXX17_CONSTEXPR void
762  assign(char_type& __c1, const char_type& __c2) noexcept
763  {
764 #if __cpp_constexpr_dynamic_alloc
765  if (std::__is_constant_evaluated())
766  std::construct_at(__builtin_addressof(__c1), __c2);
767  else
768 #endif
769  __c1 = __c2;
770  }
771 
772  static constexpr bool
773  eq(const char_type& __c1, const char_type& __c2) noexcept
774  { return __c1 == __c2; }
775 
776  static constexpr bool
777  lt(const char_type& __c1, const char_type& __c2) noexcept
778  { return __c1 < __c2; }
779 
780  static _GLIBCXX17_CONSTEXPR int
781  compare(const char_type* __s1, const char_type* __s2, size_t __n)
782  {
783  for (size_t __i = 0; __i < __n; ++__i)
784  if (lt(__s1[__i], __s2[__i]))
785  return -1;
786  else if (lt(__s2[__i], __s1[__i]))
787  return 1;
788  return 0;
789  }
790 
791  static _GLIBCXX17_CONSTEXPR size_t
792  length(const char_type* __s)
793  {
794  size_t __i = 0;
795  while (!eq(__s[__i], char_type()))
796  ++__i;
797  return __i;
798  }
799 
800  static _GLIBCXX17_CONSTEXPR const char_type*
801  find(const char_type* __s, size_t __n, const char_type& __a)
802  {
803  for (size_t __i = 0; __i < __n; ++__i)
804  if (eq(__s[__i], __a))
805  return __s + __i;
806  return 0;
807  }
808 
809  static _GLIBCXX20_CONSTEXPR char_type*
810  move(char_type* __s1, const char_type* __s2, size_t __n)
811  {
812  if (__n == 0)
813  return __s1;
814 #if __cplusplus >= 202002L
815  if (std::__is_constant_evaluated())
816  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
817 #endif
818  return (static_cast<char_type*>
819  (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
820  }
821 
822  static _GLIBCXX20_CONSTEXPR char_type*
823  copy(char_type* __s1, const char_type* __s2, size_t __n)
824  {
825  if (__n == 0)
826  return __s1;
827 #if __cplusplus >= 202002L
828  if (std::__is_constant_evaluated())
829  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
830 #endif
831  return (static_cast<char_type*>
832  (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
833  }
834 
835  static _GLIBCXX20_CONSTEXPR char_type*
836  assign(char_type* __s, size_t __n, char_type __a)
837  {
838  for (size_t __i = 0; __i < __n; ++__i)
839  assign(__s[__i], __a);
840  return __s;
841  }
842 
843  static constexpr char_type
844  to_char_type(const int_type& __c) noexcept
845  { return char_type(__c); }
846 
847  static constexpr bool
848  eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
849  { return __c1 == __c2; }
850 
851 #if _GLIBCXX_HOSTED
852  static constexpr int_type
853  to_int_type(const char_type& __c) noexcept
854  { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
855 
856  static constexpr int_type
857  eof() noexcept
858  { return static_cast<int_type>(-1); }
859 
860  static constexpr int_type
861  not_eof(const int_type& __c) noexcept
862  { return eq_int_type(__c, eof()) ? 0 : __c; }
863 #else // !HOSTED
864  static constexpr int_type
865  to_int_type(const char_type& __c) noexcept
866  { return int_type(__c); }
867 #endif // !HOSTED
868  };
869 
870  template<>
871  struct char_traits<char32_t>
872  {
873  typedef char32_t char_type;
874 #ifdef __UINT_LEAST32_TYPE__
875  typedef __UINT_LEAST32_TYPE__ int_type;
876 #else
877  typedef uint_least32_t int_type;
878 #endif
879 #if _GLIBCXX_HOSTED
880  typedef streamoff off_type;
881  typedef u32streampos pos_type;
882  typedef mbstate_t state_type;
883 #endif // HOSTED
884 #if __cpp_lib_three_way_comparison
885  using comparison_category = strong_ordering;
886 #endif
887 
888  static _GLIBCXX17_CONSTEXPR void
889  assign(char_type& __c1, const char_type& __c2) noexcept
890  {
891 #if __cpp_constexpr_dynamic_alloc
892  if (std::__is_constant_evaluated())
893  std::construct_at(__builtin_addressof(__c1), __c2);
894  else
895 #endif
896  __c1 = __c2;
897  }
898 
899  static constexpr bool
900  eq(const char_type& __c1, const char_type& __c2) noexcept
901  { return __c1 == __c2; }
902 
903  static constexpr bool
904  lt(const char_type& __c1, const char_type& __c2) noexcept
905  { return __c1 < __c2; }
906 
907  static _GLIBCXX17_CONSTEXPR int
908  compare(const char_type* __s1, const char_type* __s2, size_t __n)
909  {
910  for (size_t __i = 0; __i < __n; ++__i)
911  if (lt(__s1[__i], __s2[__i]))
912  return -1;
913  else if (lt(__s2[__i], __s1[__i]))
914  return 1;
915  return 0;
916  }
917 
918  static _GLIBCXX17_CONSTEXPR size_t
919  length(const char_type* __s)
920  {
921  size_t __i = 0;
922  while (!eq(__s[__i], char_type()))
923  ++__i;
924  return __i;
925  }
926 
927  static _GLIBCXX17_CONSTEXPR const char_type*
928  find(const char_type* __s, size_t __n, const char_type& __a)
929  {
930  for (size_t __i = 0; __i < __n; ++__i)
931  if (eq(__s[__i], __a))
932  return __s + __i;
933  return 0;
934  }
935 
936  static _GLIBCXX20_CONSTEXPR char_type*
937  move(char_type* __s1, const char_type* __s2, size_t __n)
938  {
939  if (__n == 0)
940  return __s1;
941 #if __cplusplus >= 202002L
942  if (std::__is_constant_evaluated())
943  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
944 #endif
945  return (static_cast<char_type*>
946  (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
947  }
948 
949  static _GLIBCXX20_CONSTEXPR char_type*
950  copy(char_type* __s1, const char_type* __s2, size_t __n)
951  {
952  if (__n == 0)
953  return __s1;
954 #if __cplusplus >= 202002L
955  if (std::__is_constant_evaluated())
956  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
957 #endif
958  return (static_cast<char_type*>
959  (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
960  }
961 
962  static _GLIBCXX20_CONSTEXPR char_type*
963  assign(char_type* __s, size_t __n, char_type __a)
964  {
965  for (size_t __i = 0; __i < __n; ++__i)
966  assign(__s[__i], __a);
967  return __s;
968  }
969 
970  static constexpr char_type
971  to_char_type(const int_type& __c) noexcept
972  { return char_type(__c); }
973 
974  static constexpr int_type
975  to_int_type(const char_type& __c) noexcept
976  { return int_type(__c); }
977 
978  static constexpr bool
979  eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
980  { return __c1 == __c2; }
981 
982 #if _GLIBCXX_HOSTED
983  static constexpr int_type
984  eof() noexcept
985  { return static_cast<int_type>(-1); }
986 
987  static constexpr int_type
988  not_eof(const int_type& __c) noexcept
989  { return eq_int_type(__c, eof()) ? 0 : __c; }
990 #endif // HOSTED
991  };
992 
993 #if __cpp_lib_three_way_comparison
994  namespace __detail
995  {
996  template<typename _ChTraits>
997  constexpr auto
998  __char_traits_cmp_cat(int __cmp) noexcept
999  {
1000  if constexpr (requires { typename _ChTraits::comparison_category; })
1001  {
1002  using _Cat = typename _ChTraits::comparison_category;
1003  static_assert( !is_void_v<common_comparison_category_t<_Cat>> );
1004  return static_cast<_Cat>(__cmp <=> 0);
1005  }
1006  else
1007  return static_cast<weak_ordering>(__cmp <=> 0);
1008  }
1009  } // namespace __detail
1010 #endif // C++20
1011 
1012 #pragma GCC diagnostic pop
1013 
1014 _GLIBCXX_END_NAMESPACE_VERSION
1015 } // namespace
1016 
1017 #endif // C++11
1018 
1019 #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:329
Class representing stream positions.
Definition: postypes.h:88