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