138fd1498Szrj // Character Traits for use by standard string and iostream -*- C++ -*-
238fd1498Szrj 
338fd1498Szrj // Copyright (C) 1997-2018 Free Software Foundation, Inc.
438fd1498Szrj //
538fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
638fd1498Szrj // software; you can redistribute it and/or modify it under the
738fd1498Szrj // terms of the GNU General Public License as published by the
838fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj // any later version.
1038fd1498Szrj 
1138fd1498Szrj // This library is distributed in the hope that it will be useful,
1238fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1438fd1498Szrj // GNU General Public License for more details.
1538fd1498Szrj 
1638fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj // 3.1, as published by the Free Software Foundation.
1938fd1498Szrj 
2038fd1498Szrj // You should have received a copy of the GNU General Public License and
2138fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2338fd1498Szrj // <http://www.gnu.org/licenses/>.
2438fd1498Szrj 
2538fd1498Szrj /** @file bits/char_traits.h
2638fd1498Szrj  *  This is an internal header file, included by other library headers.
2738fd1498Szrj  *  Do not attempt to use it directly. @headername{string}
2838fd1498Szrj  */
2938fd1498Szrj 
3038fd1498Szrj //
3138fd1498Szrj // ISO C++ 14882: 21  Strings library
3238fd1498Szrj //
3338fd1498Szrj 
3438fd1498Szrj #ifndef _CHAR_TRAITS_H
3538fd1498Szrj #define _CHAR_TRAITS_H 1
3638fd1498Szrj 
3738fd1498Szrj #pragma GCC system_header
3838fd1498Szrj 
3938fd1498Szrj #include <bits/stl_algobase.h>  // std::copy, std::fill_n
4038fd1498Szrj #include <bits/postypes.h>      // For streampos
4138fd1498Szrj #include <cwchar>               // For WEOF, wmemmove, wmemset, etc.
4238fd1498Szrj 
4338fd1498Szrj #ifndef _GLIBCXX_ALWAYS_INLINE
4438fd1498Szrj #define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
4538fd1498Szrj #endif
4638fd1498Szrj 
_GLIBCXX_VISIBILITY(default)4738fd1498Szrj namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
4838fd1498Szrj {
4938fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
5038fd1498Szrj 
5138fd1498Szrj   /**
5238fd1498Szrj    *  @brief  Mapping from character type to associated types.
5338fd1498Szrj    *
5438fd1498Szrj    *  @note This is an implementation class for the generic version
5538fd1498Szrj    *  of char_traits.  It defines int_type, off_type, pos_type, and
5638fd1498Szrj    *  state_type.  By default these are unsigned long, streamoff,
5738fd1498Szrj    *  streampos, and mbstate_t.  Users who need a different set of
5838fd1498Szrj    *  types, but who don't need to change the definitions of any function
5938fd1498Szrj    *  defined in char_traits, can specialize __gnu_cxx::_Char_types
6038fd1498Szrj    *  while leaving __gnu_cxx::char_traits alone. */
6138fd1498Szrj   template<typename _CharT>
6238fd1498Szrj     struct _Char_types
6338fd1498Szrj     {
6438fd1498Szrj       typedef unsigned long   int_type;
6538fd1498Szrj       typedef std::streampos  pos_type;
6638fd1498Szrj       typedef std::streamoff  off_type;
6738fd1498Szrj       typedef std::mbstate_t  state_type;
6838fd1498Szrj     };
6938fd1498Szrj 
7038fd1498Szrj 
7138fd1498Szrj   /**
7238fd1498Szrj    *  @brief  Base class used to implement std::char_traits.
7338fd1498Szrj    *
7438fd1498Szrj    *  @note For any given actual character type, this definition is
7538fd1498Szrj    *  probably wrong.  (Most of the member functions are likely to be
7638fd1498Szrj    *  right, but the int_type and state_type typedefs, and the eof()
7738fd1498Szrj    *  member function, are likely to be wrong.)  The reason this class
7838fd1498Szrj    *  exists is so users can specialize it.  Classes in namespace std
7938fd1498Szrj    *  may not be specialized for fundamental types, but classes in
8038fd1498Szrj    *  namespace __gnu_cxx may be.
8138fd1498Szrj    *
8238fd1498Szrj    *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
8338fd1498Szrj    *  for advice on how to make use of this class for @a unusual character
8438fd1498Szrj    *  types. Also, check out include/ext/pod_char_traits.h.
8538fd1498Szrj    */
8638fd1498Szrj   template<typename _CharT>
8738fd1498Szrj     struct char_traits
8838fd1498Szrj     {
8938fd1498Szrj       typedef _CharT                                    char_type;
9038fd1498Szrj       typedef typename _Char_types<_CharT>::int_type    int_type;
9138fd1498Szrj       typedef typename _Char_types<_CharT>::pos_type    pos_type;
9238fd1498Szrj       typedef typename _Char_types<_CharT>::off_type    off_type;
9338fd1498Szrj       typedef typename _Char_types<_CharT>::state_type  state_type;
9438fd1498Szrj 
9538fd1498Szrj       static _GLIBCXX14_CONSTEXPR void
9638fd1498Szrj       assign(char_type& __c1, const char_type& __c2)
9738fd1498Szrj       { __c1 = __c2; }
9838fd1498Szrj 
9938fd1498Szrj       static _GLIBCXX_CONSTEXPR bool
10038fd1498Szrj       eq(const char_type& __c1, const char_type& __c2)
10138fd1498Szrj       { return __c1 == __c2; }
10238fd1498Szrj 
10338fd1498Szrj       static _GLIBCXX_CONSTEXPR bool
10438fd1498Szrj       lt(const char_type& __c1, const char_type& __c2)
10538fd1498Szrj       { return __c1 < __c2; }
10638fd1498Szrj 
10738fd1498Szrj       static _GLIBCXX14_CONSTEXPR int
10838fd1498Szrj       compare(const char_type* __s1, const char_type* __s2, std::size_t __n);
10938fd1498Szrj 
11038fd1498Szrj       static _GLIBCXX14_CONSTEXPR std::size_t
11138fd1498Szrj       length(const char_type* __s);
11238fd1498Szrj 
11338fd1498Szrj       static _GLIBCXX14_CONSTEXPR const char_type*
11438fd1498Szrj       find(const char_type* __s, std::size_t __n, const char_type& __a);
11538fd1498Szrj 
11638fd1498Szrj       static char_type*
11738fd1498Szrj       move(char_type* __s1, const char_type* __s2, std::size_t __n);
11838fd1498Szrj 
11938fd1498Szrj       static char_type*
12038fd1498Szrj       copy(char_type* __s1, const char_type* __s2, std::size_t __n);
12138fd1498Szrj 
12238fd1498Szrj       static char_type*
12338fd1498Szrj       assign(char_type* __s, std::size_t __n, char_type __a);
12438fd1498Szrj 
12538fd1498Szrj       static _GLIBCXX_CONSTEXPR char_type
12638fd1498Szrj       to_char_type(const int_type& __c)
12738fd1498Szrj       { return static_cast<char_type>(__c); }
12838fd1498Szrj 
12938fd1498Szrj       static _GLIBCXX_CONSTEXPR int_type
13038fd1498Szrj       to_int_type(const char_type& __c)
13138fd1498Szrj       { return static_cast<int_type>(__c); }
13238fd1498Szrj 
13338fd1498Szrj       static _GLIBCXX_CONSTEXPR bool
13438fd1498Szrj       eq_int_type(const int_type& __c1, const int_type& __c2)
13538fd1498Szrj       { return __c1 == __c2; }
13638fd1498Szrj 
13738fd1498Szrj       static _GLIBCXX_CONSTEXPR int_type
13838fd1498Szrj       eof()
13938fd1498Szrj       { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
14038fd1498Szrj 
14138fd1498Szrj       static _GLIBCXX_CONSTEXPR int_type
14238fd1498Szrj       not_eof(const int_type& __c)
14338fd1498Szrj       { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); }
14438fd1498Szrj     };
14538fd1498Szrj 
14638fd1498Szrj   template<typename _CharT>
14738fd1498Szrj     _GLIBCXX14_CONSTEXPR int
14838fd1498Szrj     char_traits<_CharT>::
14938fd1498Szrj     compare(const char_type* __s1, const char_type* __s2, std::size_t __n)
15038fd1498Szrj     {
15138fd1498Szrj       for (std::size_t __i = 0; __i < __n; ++__i)
15238fd1498Szrj 	if (lt(__s1[__i], __s2[__i]))
15338fd1498Szrj 	  return -1;
15438fd1498Szrj 	else if (lt(__s2[__i], __s1[__i]))
15538fd1498Szrj 	  return 1;
15638fd1498Szrj       return 0;
15738fd1498Szrj     }
15838fd1498Szrj 
15938fd1498Szrj   template<typename _CharT>
16038fd1498Szrj     _GLIBCXX14_CONSTEXPR std::size_t
16138fd1498Szrj     char_traits<_CharT>::
16238fd1498Szrj     length(const char_type* __p)
16338fd1498Szrj     {
16438fd1498Szrj       std::size_t __i = 0;
16538fd1498Szrj       while (!eq(__p[__i], char_type()))
16638fd1498Szrj         ++__i;
16738fd1498Szrj       return __i;
16838fd1498Szrj     }
16938fd1498Szrj 
17038fd1498Szrj   template<typename _CharT>
17138fd1498Szrj     _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type*
17238fd1498Szrj     char_traits<_CharT>::
17338fd1498Szrj     find(const char_type* __s, std::size_t __n, const char_type& __a)
17438fd1498Szrj     {
17538fd1498Szrj       for (std::size_t __i = 0; __i < __n; ++__i)
17638fd1498Szrj         if (eq(__s[__i], __a))
17738fd1498Szrj           return __s + __i;
17838fd1498Szrj       return 0;
17938fd1498Szrj     }
18038fd1498Szrj 
18138fd1498Szrj   template<typename _CharT>
18238fd1498Szrj     typename char_traits<_CharT>::char_type*
18338fd1498Szrj     char_traits<_CharT>::
18438fd1498Szrj     move(char_type* __s1, const char_type* __s2, std::size_t __n)
18538fd1498Szrj     {
18658e805e6Szrj       if (__n == 0)
18758e805e6Szrj 	return __s1;
18838fd1498Szrj       return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
18938fd1498Szrj 						    __n * sizeof(char_type)));
19038fd1498Szrj     }
19138fd1498Szrj 
19238fd1498Szrj   template<typename _CharT>
19338fd1498Szrj     typename char_traits<_CharT>::char_type*
19438fd1498Szrj     char_traits<_CharT>::
19538fd1498Szrj     copy(char_type* __s1, const char_type* __s2, std::size_t __n)
19638fd1498Szrj     {
19738fd1498Szrj       // NB: Inline std::copy so no recursive dependencies.
19838fd1498Szrj       std::copy(__s2, __s2 + __n, __s1);
19938fd1498Szrj       return __s1;
20038fd1498Szrj     }
20138fd1498Szrj 
20238fd1498Szrj   template<typename _CharT>
20338fd1498Szrj     typename char_traits<_CharT>::char_type*
20438fd1498Szrj     char_traits<_CharT>::
20538fd1498Szrj     assign(char_type* __s, std::size_t __n, char_type __a)
20638fd1498Szrj     {
20738fd1498Szrj       // NB: Inline std::fill_n so no recursive dependencies.
20838fd1498Szrj       std::fill_n(__s, __n, __a);
20938fd1498Szrj       return __s;
21038fd1498Szrj     }
21138fd1498Szrj 
21238fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
21338fd1498Szrj } // namespace
21438fd1498Szrj 
_GLIBCXX_VISIBILITY(default)21538fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
21638fd1498Szrj {
21738fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
21838fd1498Szrj 
21938fd1498Szrj #if __cplusplus > 201402
22058e805e6Szrj #define __cpp_lib_constexpr_char_traits 201611
22158e805e6Szrj 
22238fd1498Szrj   /**
22338fd1498Szrj    *  @brief Determine whether the characters of a NULL-terminated
22438fd1498Szrj    *  string are known at compile time.
22538fd1498Szrj    *  @param  __s  The string.
22638fd1498Szrj    *
22738fd1498Szrj    *  Assumes that _CharT is a built-in character type.
22838fd1498Szrj    */
22938fd1498Szrj   template<typename _CharT>
23038fd1498Szrj     static _GLIBCXX_ALWAYS_INLINE constexpr bool
23138fd1498Szrj     __constant_string_p(const _CharT* __s)
23238fd1498Szrj     {
23338fd1498Szrj       while (__builtin_constant_p(*__s) && *__s)
23438fd1498Szrj 	__s++;
23538fd1498Szrj       return __builtin_constant_p(*__s);
23638fd1498Szrj     }
23738fd1498Szrj 
23838fd1498Szrj   /**
23938fd1498Szrj    *  @brief Determine whether the characters of a character array are
24038fd1498Szrj    *  known at compile time.
24138fd1498Szrj    *  @param  __a  The character array.
24238fd1498Szrj    *  @param  __n  Number of characters.
24338fd1498Szrj    *
24438fd1498Szrj    *  Assumes that _CharT is a built-in character type.
24538fd1498Szrj    */
24638fd1498Szrj   template<typename _CharT>
24738fd1498Szrj     static _GLIBCXX_ALWAYS_INLINE constexpr bool
24838fd1498Szrj     __constant_char_array_p(const _CharT* __a, size_t __n)
24938fd1498Szrj     {
25038fd1498Szrj       size_t __i = 0;
251*e215fc28Szrj       while (__i < __n && __builtin_constant_p(__a[__i]))
25238fd1498Szrj 	__i++;
25338fd1498Szrj       return __i == __n;
25438fd1498Szrj     }
25538fd1498Szrj #endif
25638fd1498Szrj 
25738fd1498Szrj   // 21.1
25838fd1498Szrj   /**
25938fd1498Szrj    *  @brief  Basis for explicit traits specializations.
26038fd1498Szrj    *
26138fd1498Szrj    *  @note  For any given actual character type, this definition is
26238fd1498Szrj    *  probably wrong.  Since this is just a thin wrapper around
26338fd1498Szrj    *  __gnu_cxx::char_traits, it is possible to achieve a more
26438fd1498Szrj    *  appropriate definition by specializing __gnu_cxx::char_traits.
26538fd1498Szrj    *
26638fd1498Szrj    *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
26738fd1498Szrj    *  for advice on how to make use of this class for @a unusual character
26838fd1498Szrj    *  types. Also, check out include/ext/pod_char_traits.h.
26938fd1498Szrj   */
27038fd1498Szrj   template<class _CharT>
27138fd1498Szrj     struct char_traits : public __gnu_cxx::char_traits<_CharT>
27238fd1498Szrj     { };
27338fd1498Szrj 
27438fd1498Szrj 
27538fd1498Szrj   /// 21.1.3.1  char_traits specializations
27638fd1498Szrj   template<>
27738fd1498Szrj     struct char_traits<char>
27838fd1498Szrj     {
27938fd1498Szrj       typedef char              char_type;
28038fd1498Szrj       typedef int               int_type;
28138fd1498Szrj       typedef streampos         pos_type;
28238fd1498Szrj       typedef streamoff         off_type;
28338fd1498Szrj       typedef mbstate_t         state_type;
28438fd1498Szrj 
28538fd1498Szrj       static _GLIBCXX17_CONSTEXPR void
28638fd1498Szrj       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
28738fd1498Szrj       { __c1 = __c2; }
28838fd1498Szrj 
28938fd1498Szrj       static _GLIBCXX_CONSTEXPR bool
29038fd1498Szrj       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
29138fd1498Szrj       { return __c1 == __c2; }
29238fd1498Szrj 
29338fd1498Szrj       static _GLIBCXX_CONSTEXPR bool
29438fd1498Szrj       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
29538fd1498Szrj       {
29638fd1498Szrj 	// LWG 467.
29738fd1498Szrj 	return (static_cast<unsigned char>(__c1)
29838fd1498Szrj 		< static_cast<unsigned char>(__c2));
29938fd1498Szrj       }
30038fd1498Szrj 
30138fd1498Szrj       static _GLIBCXX17_CONSTEXPR int
30238fd1498Szrj       compare(const char_type* __s1, const char_type* __s2, size_t __n)
30338fd1498Szrj       {
30438fd1498Szrj #if __cplusplus > 201402
30538fd1498Szrj 	if (__builtin_constant_p(__n)
30638fd1498Szrj 	    && __constant_char_array_p(__s1, __n)
30738fd1498Szrj 	    && __constant_char_array_p(__s2, __n))
30838fd1498Szrj 	  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
30938fd1498Szrj #endif
31038fd1498Szrj 	if (__n == 0)
31138fd1498Szrj 	  return 0;
31238fd1498Szrj 	return __builtin_memcmp(__s1, __s2, __n);
31338fd1498Szrj       }
31438fd1498Szrj 
31538fd1498Szrj       static _GLIBCXX17_CONSTEXPR size_t
31638fd1498Szrj       length(const char_type* __s)
31738fd1498Szrj       {
31838fd1498Szrj #if __cplusplus > 201402
31938fd1498Szrj 	if (__constant_string_p(__s))
32038fd1498Szrj 	  return __gnu_cxx::char_traits<char_type>::length(__s);
32138fd1498Szrj #endif
32238fd1498Szrj 	return __builtin_strlen(__s);
32338fd1498Szrj       }
32438fd1498Szrj 
32538fd1498Szrj       static _GLIBCXX17_CONSTEXPR const char_type*
32638fd1498Szrj       find(const char_type* __s, size_t __n, const char_type& __a)
32738fd1498Szrj       {
32838fd1498Szrj #if __cplusplus > 201402
32938fd1498Szrj 	if (__builtin_constant_p(__n)
33038fd1498Szrj 	    && __builtin_constant_p(__a)
33138fd1498Szrj 	    && __constant_char_array_p(__s, __n))
33238fd1498Szrj 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
33338fd1498Szrj #endif
33438fd1498Szrj 	if (__n == 0)
33538fd1498Szrj 	  return 0;
33638fd1498Szrj 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
33738fd1498Szrj       }
33838fd1498Szrj 
33938fd1498Szrj       static char_type*
34038fd1498Szrj       move(char_type* __s1, const char_type* __s2, size_t __n)
34138fd1498Szrj       {
34238fd1498Szrj 	if (__n == 0)
34338fd1498Szrj 	  return __s1;
34438fd1498Szrj 	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
34538fd1498Szrj       }
34638fd1498Szrj 
34738fd1498Szrj       static char_type*
34838fd1498Szrj       copy(char_type* __s1, const char_type* __s2, size_t __n)
34938fd1498Szrj       {
35038fd1498Szrj 	if (__n == 0)
35138fd1498Szrj 	  return __s1;
35238fd1498Szrj 	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
35338fd1498Szrj       }
35438fd1498Szrj 
35538fd1498Szrj       static char_type*
35638fd1498Szrj       assign(char_type* __s, size_t __n, char_type __a)
35738fd1498Szrj       {
35838fd1498Szrj 	if (__n == 0)
35938fd1498Szrj 	  return __s;
36038fd1498Szrj 	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
36138fd1498Szrj       }
36238fd1498Szrj 
36338fd1498Szrj       static _GLIBCXX_CONSTEXPR char_type
36438fd1498Szrj       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
36538fd1498Szrj       { return static_cast<char_type>(__c); }
36638fd1498Szrj 
36738fd1498Szrj       // To keep both the byte 0xff and the eof symbol 0xffffffff
36838fd1498Szrj       // from ending up as 0xffffffff.
36938fd1498Szrj       static _GLIBCXX_CONSTEXPR int_type
37038fd1498Szrj       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
37138fd1498Szrj       { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
37238fd1498Szrj 
37338fd1498Szrj       static _GLIBCXX_CONSTEXPR bool
37438fd1498Szrj       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
37538fd1498Szrj       { return __c1 == __c2; }
37638fd1498Szrj 
37738fd1498Szrj       static _GLIBCXX_CONSTEXPR int_type
37838fd1498Szrj       eof() _GLIBCXX_NOEXCEPT
37938fd1498Szrj       { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
38038fd1498Szrj 
38138fd1498Szrj       static _GLIBCXX_CONSTEXPR int_type
38238fd1498Szrj       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
38338fd1498Szrj       { return (__c == eof()) ? 0 : __c; }
38438fd1498Szrj   };
38538fd1498Szrj 
38638fd1498Szrj 
38738fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
38838fd1498Szrj   /// 21.1.3.2  char_traits specializations
38938fd1498Szrj   template<>
39038fd1498Szrj     struct char_traits<wchar_t>
39138fd1498Szrj     {
39238fd1498Szrj       typedef wchar_t           char_type;
39338fd1498Szrj       typedef wint_t            int_type;
39438fd1498Szrj       typedef streamoff         off_type;
39538fd1498Szrj       typedef wstreampos        pos_type;
39638fd1498Szrj       typedef mbstate_t         state_type;
39738fd1498Szrj 
39838fd1498Szrj       static _GLIBCXX17_CONSTEXPR void
39938fd1498Szrj       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
40038fd1498Szrj       { __c1 = __c2; }
40138fd1498Szrj 
40238fd1498Szrj       static _GLIBCXX_CONSTEXPR bool
40338fd1498Szrj       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
40438fd1498Szrj       { return __c1 == __c2; }
40538fd1498Szrj 
40638fd1498Szrj       static _GLIBCXX_CONSTEXPR bool
40738fd1498Szrj       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
40838fd1498Szrj       { return __c1 < __c2; }
40938fd1498Szrj 
41038fd1498Szrj       static _GLIBCXX17_CONSTEXPR int
41138fd1498Szrj       compare(const char_type* __s1, const char_type* __s2, size_t __n)
41238fd1498Szrj       {
41338fd1498Szrj #if __cplusplus > 201402
41438fd1498Szrj 	if (__builtin_constant_p(__n)
41538fd1498Szrj 	    && __constant_char_array_p(__s1, __n)
41638fd1498Szrj 	    && __constant_char_array_p(__s2, __n))
41738fd1498Szrj 	  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
41838fd1498Szrj #endif
41938fd1498Szrj 	if (__n == 0)
42038fd1498Szrj 	  return 0;
42138fd1498Szrj 	else
42238fd1498Szrj 	  return wmemcmp(__s1, __s2, __n);
42338fd1498Szrj       }
42438fd1498Szrj 
42538fd1498Szrj       static _GLIBCXX17_CONSTEXPR size_t
42638fd1498Szrj       length(const char_type* __s)
42738fd1498Szrj       {
42838fd1498Szrj #if __cplusplus > 201402
42938fd1498Szrj 	if (__constant_string_p(__s))
43038fd1498Szrj 	  return __gnu_cxx::char_traits<char_type>::length(__s);
43138fd1498Szrj 	else
43238fd1498Szrj #endif
43338fd1498Szrj 	  return wcslen(__s);
43438fd1498Szrj       }
43538fd1498Szrj 
43638fd1498Szrj       static _GLIBCXX17_CONSTEXPR const char_type*
43738fd1498Szrj       find(const char_type* __s, size_t __n, const char_type& __a)
43838fd1498Szrj       {
43938fd1498Szrj #if __cplusplus > 201402
44038fd1498Szrj 	if (__builtin_constant_p(__n)
44138fd1498Szrj 	    && __builtin_constant_p(__a)
44238fd1498Szrj 	    && __constant_char_array_p(__s, __n))
44338fd1498Szrj 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
44438fd1498Szrj #endif
44538fd1498Szrj 	if (__n == 0)
44638fd1498Szrj 	  return 0;
44738fd1498Szrj 	else
44838fd1498Szrj 	  return wmemchr(__s, __a, __n);
44938fd1498Szrj       }
45038fd1498Szrj 
45138fd1498Szrj       static char_type*
45238fd1498Szrj       move(char_type* __s1, const char_type* __s2, size_t __n)
45338fd1498Szrj       {
45438fd1498Szrj 	if (__n == 0)
45538fd1498Szrj 	  return __s1;
45638fd1498Szrj 	return wmemmove(__s1, __s2, __n);
45738fd1498Szrj       }
45838fd1498Szrj 
45938fd1498Szrj       static char_type*
46038fd1498Szrj       copy(char_type* __s1, const char_type* __s2, size_t __n)
46138fd1498Szrj       {
46238fd1498Szrj 	if (__n == 0)
46338fd1498Szrj 	  return __s1;
46438fd1498Szrj 	return wmemcpy(__s1, __s2, __n);
46538fd1498Szrj       }
46638fd1498Szrj 
46738fd1498Szrj       static char_type*
46838fd1498Szrj       assign(char_type* __s, size_t __n, char_type __a)
46938fd1498Szrj       {
47038fd1498Szrj 	if (__n == 0)
47138fd1498Szrj 	  return __s;
47238fd1498Szrj 	return wmemset(__s, __a, __n);
47338fd1498Szrj       }
47438fd1498Szrj 
47538fd1498Szrj       static _GLIBCXX_CONSTEXPR char_type
47638fd1498Szrj       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
47738fd1498Szrj       { return char_type(__c); }
47838fd1498Szrj 
47938fd1498Szrj       static _GLIBCXX_CONSTEXPR int_type
48038fd1498Szrj       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
48138fd1498Szrj       { return int_type(__c); }
48238fd1498Szrj 
48338fd1498Szrj       static _GLIBCXX_CONSTEXPR bool
48438fd1498Szrj       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
48538fd1498Szrj       { return __c1 == __c2; }
48638fd1498Szrj 
48738fd1498Szrj       static _GLIBCXX_CONSTEXPR int_type
48838fd1498Szrj       eof() _GLIBCXX_NOEXCEPT
48938fd1498Szrj       { return static_cast<int_type>(WEOF); }
49038fd1498Szrj 
49138fd1498Szrj       static _GLIBCXX_CONSTEXPR int_type
49238fd1498Szrj       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
49338fd1498Szrj       { return eq_int_type(__c, eof()) ? 0 : __c; }
49438fd1498Szrj   };
49538fd1498Szrj #endif //_GLIBCXX_USE_WCHAR_T
49638fd1498Szrj 
49738fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
49838fd1498Szrj } // namespace
49938fd1498Szrj 
50038fd1498Szrj #if ((__cplusplus >= 201103L) \
50138fd1498Szrj      && defined(_GLIBCXX_USE_C99_STDINT_TR1))
50238fd1498Szrj 
50338fd1498Szrj #include <cstdint>
50438fd1498Szrj 
50538fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
50638fd1498Szrj {
50738fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
50838fd1498Szrj 
50938fd1498Szrj   template<>
51038fd1498Szrj     struct char_traits<char16_t>
51138fd1498Szrj     {
51238fd1498Szrj       typedef char16_t          char_type;
51338fd1498Szrj       typedef uint_least16_t    int_type;
51438fd1498Szrj       typedef streamoff         off_type;
51538fd1498Szrj       typedef u16streampos      pos_type;
51638fd1498Szrj       typedef mbstate_t         state_type;
51738fd1498Szrj 
51838fd1498Szrj       static _GLIBCXX17_CONSTEXPR void
51938fd1498Szrj       assign(char_type& __c1, const char_type& __c2) noexcept
52038fd1498Szrj       { __c1 = __c2; }
52138fd1498Szrj 
52238fd1498Szrj       static constexpr bool
52338fd1498Szrj       eq(const char_type& __c1, const char_type& __c2) noexcept
52438fd1498Szrj       { return __c1 == __c2; }
52538fd1498Szrj 
52638fd1498Szrj       static constexpr bool
52738fd1498Szrj       lt(const char_type& __c1, const char_type& __c2) noexcept
52838fd1498Szrj       { return __c1 < __c2; }
52938fd1498Szrj 
53038fd1498Szrj       static _GLIBCXX17_CONSTEXPR int
53138fd1498Szrj       compare(const char_type* __s1, const char_type* __s2, size_t __n)
53238fd1498Szrj       {
53338fd1498Szrj 	for (size_t __i = 0; __i < __n; ++__i)
53438fd1498Szrj 	  if (lt(__s1[__i], __s2[__i]))
53538fd1498Szrj 	    return -1;
53638fd1498Szrj 	  else if (lt(__s2[__i], __s1[__i]))
53738fd1498Szrj 	    return 1;
53838fd1498Szrj 	return 0;
53938fd1498Szrj       }
54038fd1498Szrj 
54138fd1498Szrj       static _GLIBCXX17_CONSTEXPR size_t
54238fd1498Szrj       length(const char_type* __s)
54338fd1498Szrj       {
54438fd1498Szrj 	size_t __i = 0;
54538fd1498Szrj 	while (!eq(__s[__i], char_type()))
54638fd1498Szrj 	  ++__i;
54738fd1498Szrj 	return __i;
54838fd1498Szrj       }
54938fd1498Szrj 
55038fd1498Szrj       static _GLIBCXX17_CONSTEXPR const char_type*
55138fd1498Szrj       find(const char_type* __s, size_t __n, const char_type& __a)
55238fd1498Szrj       {
55338fd1498Szrj 	for (size_t __i = 0; __i < __n; ++__i)
55438fd1498Szrj 	  if (eq(__s[__i], __a))
55538fd1498Szrj 	    return __s + __i;
55638fd1498Szrj 	return 0;
55738fd1498Szrj       }
55838fd1498Szrj 
55938fd1498Szrj       static char_type*
56038fd1498Szrj       move(char_type* __s1, const char_type* __s2, size_t __n)
56138fd1498Szrj       {
56238fd1498Szrj 	if (__n == 0)
56338fd1498Szrj 	  return __s1;
56438fd1498Szrj 	return (static_cast<char_type*>
56538fd1498Szrj 		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
56638fd1498Szrj       }
56738fd1498Szrj 
56838fd1498Szrj       static char_type*
56938fd1498Szrj       copy(char_type* __s1, const char_type* __s2, size_t __n)
57038fd1498Szrj       {
57138fd1498Szrj 	if (__n == 0)
57238fd1498Szrj 	  return __s1;
57338fd1498Szrj 	return (static_cast<char_type*>
57438fd1498Szrj 		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
57538fd1498Szrj       }
57638fd1498Szrj 
57738fd1498Szrj       static char_type*
57838fd1498Szrj       assign(char_type* __s, size_t __n, char_type __a)
57938fd1498Szrj       {
58038fd1498Szrj 	for (size_t __i = 0; __i < __n; ++__i)
58138fd1498Szrj 	  assign(__s[__i], __a);
58238fd1498Szrj 	return __s;
58338fd1498Szrj       }
58438fd1498Szrj 
58538fd1498Szrj       static constexpr char_type
58638fd1498Szrj       to_char_type(const int_type& __c) noexcept
58738fd1498Szrj       { return char_type(__c); }
58838fd1498Szrj 
58938fd1498Szrj       static constexpr int_type
59038fd1498Szrj       to_int_type(const char_type& __c) noexcept
59138fd1498Szrj       { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
59238fd1498Szrj 
59338fd1498Szrj       static constexpr bool
59438fd1498Szrj       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
59538fd1498Szrj       { return __c1 == __c2; }
59638fd1498Szrj 
59738fd1498Szrj       static constexpr int_type
59838fd1498Szrj       eof() noexcept
59938fd1498Szrj       { return static_cast<int_type>(-1); }
60038fd1498Szrj 
60138fd1498Szrj       static constexpr int_type
60238fd1498Szrj       not_eof(const int_type& __c) noexcept
60338fd1498Szrj       { return eq_int_type(__c, eof()) ? 0 : __c; }
60438fd1498Szrj     };
60538fd1498Szrj 
60638fd1498Szrj   template<>
60738fd1498Szrj     struct char_traits<char32_t>
60838fd1498Szrj     {
60938fd1498Szrj       typedef char32_t          char_type;
61038fd1498Szrj       typedef uint_least32_t    int_type;
61138fd1498Szrj       typedef streamoff         off_type;
61238fd1498Szrj       typedef u32streampos      pos_type;
61338fd1498Szrj       typedef mbstate_t         state_type;
61438fd1498Szrj 
61538fd1498Szrj       static _GLIBCXX17_CONSTEXPR void
61638fd1498Szrj       assign(char_type& __c1, const char_type& __c2) noexcept
61738fd1498Szrj       { __c1 = __c2; }
61838fd1498Szrj 
61938fd1498Szrj       static constexpr bool
62038fd1498Szrj       eq(const char_type& __c1, const char_type& __c2) noexcept
62138fd1498Szrj       { return __c1 == __c2; }
62238fd1498Szrj 
62338fd1498Szrj       static constexpr bool
62438fd1498Szrj       lt(const char_type& __c1, const char_type& __c2) noexcept
62538fd1498Szrj       { return __c1 < __c2; }
62638fd1498Szrj 
62738fd1498Szrj       static _GLIBCXX17_CONSTEXPR int
62838fd1498Szrj       compare(const char_type* __s1, const char_type* __s2, size_t __n)
62938fd1498Szrj       {
63038fd1498Szrj 	for (size_t __i = 0; __i < __n; ++__i)
63138fd1498Szrj 	  if (lt(__s1[__i], __s2[__i]))
63238fd1498Szrj 	    return -1;
63338fd1498Szrj 	  else if (lt(__s2[__i], __s1[__i]))
63438fd1498Szrj 	    return 1;
63538fd1498Szrj 	return 0;
63638fd1498Szrj       }
63738fd1498Szrj 
63838fd1498Szrj       static _GLIBCXX17_CONSTEXPR size_t
63938fd1498Szrj       length(const char_type* __s)
64038fd1498Szrj       {
64138fd1498Szrj 	size_t __i = 0;
64238fd1498Szrj 	while (!eq(__s[__i], char_type()))
64338fd1498Szrj 	  ++__i;
64438fd1498Szrj 	return __i;
64538fd1498Szrj       }
64638fd1498Szrj 
64738fd1498Szrj       static _GLIBCXX17_CONSTEXPR const char_type*
64838fd1498Szrj       find(const char_type* __s, size_t __n, const char_type& __a)
64938fd1498Szrj       {
65038fd1498Szrj 	for (size_t __i = 0; __i < __n; ++__i)
65138fd1498Szrj 	  if (eq(__s[__i], __a))
65238fd1498Szrj 	    return __s + __i;
65338fd1498Szrj 	return 0;
65438fd1498Szrj       }
65538fd1498Szrj 
65638fd1498Szrj       static char_type*
65738fd1498Szrj       move(char_type* __s1, const char_type* __s2, size_t __n)
65838fd1498Szrj       {
65938fd1498Szrj 	if (__n == 0)
66038fd1498Szrj 	  return __s1;
66138fd1498Szrj 	return (static_cast<char_type*>
66238fd1498Szrj 		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
66338fd1498Szrj       }
66438fd1498Szrj 
66538fd1498Szrj       static char_type*
66638fd1498Szrj       copy(char_type* __s1, const char_type* __s2, size_t __n)
66738fd1498Szrj       {
66838fd1498Szrj 	if (__n == 0)
66938fd1498Szrj 	  return __s1;
67038fd1498Szrj 	return (static_cast<char_type*>
67138fd1498Szrj 		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
67238fd1498Szrj       }
67338fd1498Szrj 
67438fd1498Szrj       static char_type*
67538fd1498Szrj       assign(char_type* __s, size_t __n, char_type __a)
67638fd1498Szrj       {
67738fd1498Szrj 	for (size_t __i = 0; __i < __n; ++__i)
67838fd1498Szrj 	  assign(__s[__i], __a);
67938fd1498Szrj 	return __s;
68038fd1498Szrj       }
68138fd1498Szrj 
68238fd1498Szrj       static constexpr char_type
68338fd1498Szrj       to_char_type(const int_type& __c) noexcept
68438fd1498Szrj       { return char_type(__c); }
68538fd1498Szrj 
68638fd1498Szrj       static constexpr int_type
68738fd1498Szrj       to_int_type(const char_type& __c) noexcept
68838fd1498Szrj       { return int_type(__c); }
68938fd1498Szrj 
69038fd1498Szrj       static constexpr bool
69138fd1498Szrj       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
69238fd1498Szrj       { return __c1 == __c2; }
69338fd1498Szrj 
69438fd1498Szrj       static constexpr int_type
69538fd1498Szrj       eof() noexcept
69638fd1498Szrj       { return static_cast<int_type>(-1); }
69738fd1498Szrj 
69838fd1498Szrj       static constexpr int_type
69938fd1498Szrj       not_eof(const int_type& __c) noexcept
70038fd1498Szrj       { return eq_int_type(__c, eof()) ? 0 : __c; }
70138fd1498Szrj     };
70238fd1498Szrj 
70338fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
70438fd1498Szrj } // namespace
70538fd1498Szrj 
70638fd1498Szrj #endif
70738fd1498Szrj 
70838fd1498Szrj #endif // _CHAR_TRAITS_H
709