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