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