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