(root)/
gcc-13.2.0/
libstdc++-v3/
include/
bits/
char_traits.h
       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
     186      char_traits<_CharT>::
     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())
     407  	  return __gnu_cxx::char_traits<char_type>::length(__s);
     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())
     538  	  return __gnu_cxx::char_traits<char_type>::length(__s);
     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())
     670  	  return __gnu_cxx::char_traits<char_type>::length(__s);
     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