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