libstdc++
char_traits.h
Go to the documentation of this file.
00001 // Character Traits for use by standard string and iostream -*- C++ -*-
00002 
00003 // Copyright (C) 1997-2018 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file bits/char_traits.h
00026  *  This is an internal header file, included by other library headers.
00027  *  Do not attempt to use it directly. @headername{string}
00028  */
00029 
00030 //
00031 // ISO C++ 14882: 21  Strings library
00032 //
00033 
00034 #ifndef _CHAR_TRAITS_H
00035 #define _CHAR_TRAITS_H 1
00036 
00037 #pragma GCC system_header
00038 
00039 #include <bits/stl_algobase.h>  // std::copy, std::fill_n
00040 #include <bits/postypes.h>      // For streampos
00041 #include <cwchar>               // For WEOF, wmemmove, wmemset, etc.
00042 
00043 #ifndef _GLIBCXX_ALWAYS_INLINE
00044 #define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
00045 #endif
00046 
00047 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
00048 {
00049 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00050 
00051   /**
00052    *  @brief  Mapping from character type to associated types.
00053    *
00054    *  @note This is an implementation class for the generic version
00055    *  of char_traits.  It defines int_type, off_type, pos_type, and
00056    *  state_type.  By default these are unsigned long, streamoff,
00057    *  streampos, and mbstate_t.  Users who need a different set of
00058    *  types, but who don't need to change the definitions of any function
00059    *  defined in char_traits, can specialize __gnu_cxx::_Char_types
00060    *  while leaving __gnu_cxx::char_traits alone. */
00061   template<typename _CharT>
00062     struct _Char_types
00063     {
00064       typedef unsigned long   int_type;
00065       typedef std::streampos  pos_type;
00066       typedef std::streamoff  off_type;
00067       typedef std::mbstate_t  state_type;
00068     };
00069 
00070 
00071   /**
00072    *  @brief  Base class used to implement std::char_traits.
00073    *
00074    *  @note For any given actual character type, this definition is
00075    *  probably wrong.  (Most of the member functions are likely to be
00076    *  right, but the int_type and state_type typedefs, and the eof()
00077    *  member function, are likely to be wrong.)  The reason this class
00078    *  exists is so users can specialize it.  Classes in namespace std
00079    *  may not be specialized for fundamental types, but classes in
00080    *  namespace __gnu_cxx may be.
00081    *
00082    *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
00083    *  for advice on how to make use of this class for @a unusual character
00084    *  types. Also, check out include/ext/pod_char_traits.h.  
00085    */
00086   template<typename _CharT>
00087     struct char_traits
00088     {
00089       typedef _CharT                                    char_type;
00090       typedef typename _Char_types<_CharT>::int_type    int_type;
00091       typedef typename _Char_types<_CharT>::pos_type    pos_type;
00092       typedef typename _Char_types<_CharT>::off_type    off_type;
00093       typedef typename _Char_types<_CharT>::state_type  state_type;
00094 
00095       static _GLIBCXX14_CONSTEXPR void
00096       assign(char_type& __c1, const char_type& __c2)
00097       { __c1 = __c2; }
00098 
00099       static _GLIBCXX_CONSTEXPR bool
00100       eq(const char_type& __c1, const char_type& __c2)
00101       { return __c1 == __c2; }
00102 
00103       static _GLIBCXX_CONSTEXPR bool
00104       lt(const char_type& __c1, const char_type& __c2)
00105       { return __c1 < __c2; }
00106 
00107       static _GLIBCXX14_CONSTEXPR int
00108       compare(const char_type* __s1, const char_type* __s2, std::size_t __n);
00109 
00110       static _GLIBCXX14_CONSTEXPR std::size_t
00111       length(const char_type* __s);
00112 
00113       static _GLIBCXX14_CONSTEXPR const char_type*
00114       find(const char_type* __s, std::size_t __n, const char_type& __a);
00115 
00116       static char_type*
00117       move(char_type* __s1, const char_type* __s2, std::size_t __n);
00118 
00119       static char_type*
00120       copy(char_type* __s1, const char_type* __s2, std::size_t __n);
00121 
00122       static char_type*
00123       assign(char_type* __s, std::size_t __n, char_type __a);
00124 
00125       static _GLIBCXX_CONSTEXPR char_type
00126       to_char_type(const int_type& __c)
00127       { return static_cast<char_type>(__c); }
00128 
00129       static _GLIBCXX_CONSTEXPR int_type
00130       to_int_type(const char_type& __c)
00131       { return static_cast<int_type>(__c); }
00132 
00133       static _GLIBCXX_CONSTEXPR bool
00134       eq_int_type(const int_type& __c1, const int_type& __c2)
00135       { return __c1 == __c2; }
00136 
00137       static _GLIBCXX_CONSTEXPR int_type
00138       eof()
00139       { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
00140 
00141       static _GLIBCXX_CONSTEXPR int_type
00142       not_eof(const int_type& __c)
00143       { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); }
00144     };
00145 
00146   template<typename _CharT>
00147     _GLIBCXX14_CONSTEXPR int
00148     char_traits<_CharT>::
00149     compare(const char_type* __s1, const char_type* __s2, std::size_t __n)
00150     {
00151       for (std::size_t __i = 0; __i < __n; ++__i)
00152         if (lt(__s1[__i], __s2[__i]))
00153           return -1;
00154         else if (lt(__s2[__i], __s1[__i]))
00155           return 1;
00156       return 0;
00157     }
00158 
00159   template<typename _CharT>
00160     _GLIBCXX14_CONSTEXPR std::size_t
00161     char_traits<_CharT>::
00162     length(const char_type* __p)
00163     {
00164       std::size_t __i = 0;
00165       while (!eq(__p[__i], char_type()))
00166         ++__i;
00167       return __i;
00168     }
00169 
00170   template<typename _CharT>
00171     _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type*
00172     char_traits<_CharT>::
00173     find(const char_type* __s, std::size_t __n, const char_type& __a)
00174     {
00175       for (std::size_t __i = 0; __i < __n; ++__i)
00176         if (eq(__s[__i], __a))
00177           return __s + __i;
00178       return 0;
00179     }
00180 
00181   template<typename _CharT>
00182     typename char_traits<_CharT>::char_type*
00183     char_traits<_CharT>::
00184     move(char_type* __s1, const char_type* __s2, std::size_t __n)
00185     {
00186       if (__n == 0)
00187         return __s1;
00188       return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
00189                                                     __n * sizeof(char_type)));
00190     }
00191 
00192   template<typename _CharT>
00193     typename char_traits<_CharT>::char_type*
00194     char_traits<_CharT>::
00195     copy(char_type* __s1, const char_type* __s2, std::size_t __n)
00196     {
00197       // NB: Inline std::copy so no recursive dependencies.
00198       std::copy(__s2, __s2 + __n, __s1);
00199       return __s1;
00200     }
00201 
00202   template<typename _CharT>
00203     typename char_traits<_CharT>::char_type*
00204     char_traits<_CharT>::
00205     assign(char_type* __s, std::size_t __n, char_type __a)
00206     {
00207       // NB: Inline std::fill_n so no recursive dependencies.
00208       std::fill_n(__s, __n, __a);
00209       return __s;
00210     }
00211 
00212 _GLIBCXX_END_NAMESPACE_VERSION
00213 } // namespace
00214 
00215 namespace std _GLIBCXX_VISIBILITY(default)
00216 {
00217 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00218 
00219 #if __cplusplus > 201402
00220 #define __cpp_lib_constexpr_char_traits 201611
00221 
00222   /**
00223    *  @brief Determine whether the characters of a NULL-terminated
00224    *  string are known at compile time.
00225    *  @param  __s  The string.
00226    *
00227    *  Assumes that _CharT is a built-in character type.
00228    */
00229   template<typename _CharT>
00230     static _GLIBCXX_ALWAYS_INLINE constexpr bool
00231     __constant_string_p(const _CharT* __s)
00232     {
00233       while (__builtin_constant_p(*__s) && *__s)
00234         __s++;
00235       return __builtin_constant_p(*__s);
00236     }
00237 
00238   /**
00239    *  @brief Determine whether the characters of a character array are
00240    *  known at compile time.
00241    *  @param  __a  The character array.
00242    *  @param  __n  Number of characters.
00243    *
00244    *  Assumes that _CharT is a built-in character type.
00245    */
00246   template<typename _CharT>
00247     static _GLIBCXX_ALWAYS_INLINE constexpr bool
00248     __constant_char_array_p(const _CharT* __a, size_t __n)
00249     {
00250       size_t __i = 0;
00251       while (__i < __n && __builtin_constant_p(__a[__i]))
00252         __i++;
00253       return __i == __n;
00254     }
00255 #endif
00256 
00257   // 21.1
00258   /**
00259    *  @brief  Basis for explicit traits specializations.
00260    *
00261    *  @note  For any given actual character type, this definition is
00262    *  probably wrong.  Since this is just a thin wrapper around
00263    *  __gnu_cxx::char_traits, it is possible to achieve a more
00264    *  appropriate definition by specializing __gnu_cxx::char_traits.
00265    *
00266    *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
00267    *  for advice on how to make use of this class for @a unusual character
00268    *  types. Also, check out include/ext/pod_char_traits.h.
00269   */
00270   template<class _CharT>
00271     struct char_traits : public __gnu_cxx::char_traits<_CharT>
00272     { };
00273 
00274 
00275   /// 21.1.3.1  char_traits specializations
00276   template<>
00277     struct char_traits<char>
00278     {
00279       typedef char              char_type;
00280       typedef int               int_type;
00281       typedef streampos         pos_type;
00282       typedef streamoff         off_type;
00283       typedef mbstate_t         state_type;
00284 
00285       static _GLIBCXX17_CONSTEXPR void
00286       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00287       { __c1 = __c2; }
00288 
00289       static _GLIBCXX_CONSTEXPR bool
00290       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00291       { return __c1 == __c2; }
00292 
00293       static _GLIBCXX_CONSTEXPR bool
00294       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00295       {
00296         // LWG 467.
00297         return (static_cast<unsigned char>(__c1)
00298                 < static_cast<unsigned char>(__c2));
00299       }
00300 
00301       static _GLIBCXX17_CONSTEXPR int
00302       compare(const char_type* __s1, const char_type* __s2, size_t __n)
00303       {
00304 #if __cplusplus > 201402
00305         if (__builtin_constant_p(__n)
00306             && __constant_char_array_p(__s1, __n)
00307             && __constant_char_array_p(__s2, __n))
00308           return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
00309 #endif
00310         if (__n == 0)
00311           return 0;
00312         return __builtin_memcmp(__s1, __s2, __n);
00313       }
00314 
00315       static _GLIBCXX17_CONSTEXPR size_t
00316       length(const char_type* __s)
00317       {
00318 #if __cplusplus > 201402
00319         if (__constant_string_p(__s))
00320           return __gnu_cxx::char_traits<char_type>::length(__s);
00321 #endif
00322         return __builtin_strlen(__s);
00323       }
00324 
00325       static _GLIBCXX17_CONSTEXPR const char_type*
00326       find(const char_type* __s, size_t __n, const char_type& __a)
00327       {
00328 #if __cplusplus > 201402
00329         if (__builtin_constant_p(__n)
00330             && __builtin_constant_p(__a)
00331             && __constant_char_array_p(__s, __n))
00332           return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
00333 #endif
00334         if (__n == 0)
00335           return 0;
00336         return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
00337       }
00338 
00339       static char_type*
00340       move(char_type* __s1, const char_type* __s2, size_t __n)
00341       {
00342         if (__n == 0)
00343           return __s1;
00344         return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
00345       }
00346 
00347       static char_type*
00348       copy(char_type* __s1, const char_type* __s2, size_t __n)
00349       {
00350         if (__n == 0)
00351           return __s1;
00352         return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
00353       }
00354 
00355       static char_type*
00356       assign(char_type* __s, size_t __n, char_type __a)
00357       {
00358         if (__n == 0)
00359           return __s;
00360         return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
00361       }
00362 
00363       static _GLIBCXX_CONSTEXPR char_type
00364       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
00365       { return static_cast<char_type>(__c); }
00366 
00367       // To keep both the byte 0xff and the eof symbol 0xffffffff
00368       // from ending up as 0xffffffff.
00369       static _GLIBCXX_CONSTEXPR int_type
00370       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
00371       { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
00372 
00373       static _GLIBCXX_CONSTEXPR bool
00374       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
00375       { return __c1 == __c2; }
00376 
00377       static _GLIBCXX_CONSTEXPR int_type
00378       eof() _GLIBCXX_NOEXCEPT
00379       { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
00380 
00381       static _GLIBCXX_CONSTEXPR int_type
00382       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
00383       { return (__c == eof()) ? 0 : __c; }
00384   };
00385 
00386 
00387 #ifdef _GLIBCXX_USE_WCHAR_T
00388   /// 21.1.3.2  char_traits specializations
00389   template<>
00390     struct char_traits<wchar_t>
00391     {
00392       typedef wchar_t           char_type;
00393       typedef wint_t            int_type;
00394       typedef streamoff         off_type;
00395       typedef wstreampos        pos_type;
00396       typedef mbstate_t         state_type;
00397 
00398       static _GLIBCXX17_CONSTEXPR void
00399       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00400       { __c1 = __c2; }
00401 
00402       static _GLIBCXX_CONSTEXPR bool
00403       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00404       { return __c1 == __c2; }
00405 
00406       static _GLIBCXX_CONSTEXPR bool
00407       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00408       { return __c1 < __c2; }
00409 
00410       static _GLIBCXX17_CONSTEXPR int
00411       compare(const char_type* __s1, const char_type* __s2, size_t __n)
00412       {
00413 #if __cplusplus > 201402
00414         if (__builtin_constant_p(__n)
00415             && __constant_char_array_p(__s1, __n)
00416             && __constant_char_array_p(__s2, __n))
00417           return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
00418 #endif
00419         if (__n == 0)
00420           return 0;
00421         else
00422           return wmemcmp(__s1, __s2, __n);
00423       }
00424 
00425       static _GLIBCXX17_CONSTEXPR size_t
00426       length(const char_type* __s)
00427       {
00428 #if __cplusplus > 201402
00429         if (__constant_string_p(__s))
00430           return __gnu_cxx::char_traits<char_type>::length(__s);
00431         else
00432 #endif
00433           return wcslen(__s);
00434       }
00435 
00436       static _GLIBCXX17_CONSTEXPR const char_type*
00437       find(const char_type* __s, size_t __n, const char_type& __a)
00438       {
00439 #if __cplusplus > 201402
00440         if (__builtin_constant_p(__n)
00441             && __builtin_constant_p(__a)
00442             && __constant_char_array_p(__s, __n))
00443           return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
00444 #endif
00445         if (__n == 0)
00446           return 0;
00447         else
00448           return wmemchr(__s, __a, __n);
00449       }
00450 
00451       static char_type*
00452       move(char_type* __s1, const char_type* __s2, size_t __n)
00453       {
00454         if (__n == 0)
00455           return __s1;
00456         return wmemmove(__s1, __s2, __n);
00457       }
00458 
00459       static char_type*
00460       copy(char_type* __s1, const char_type* __s2, size_t __n)
00461       {
00462         if (__n == 0)
00463           return __s1;
00464         return wmemcpy(__s1, __s2, __n);
00465       }
00466 
00467       static char_type*
00468       assign(char_type* __s, size_t __n, char_type __a)
00469       {
00470         if (__n == 0)
00471           return __s;
00472         return wmemset(__s, __a, __n);
00473       }
00474 
00475       static _GLIBCXX_CONSTEXPR char_type
00476       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
00477       { return char_type(__c); }
00478 
00479       static _GLIBCXX_CONSTEXPR int_type
00480       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
00481       { return int_type(__c); }
00482 
00483       static _GLIBCXX_CONSTEXPR bool
00484       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
00485       { return __c1 == __c2; }
00486 
00487       static _GLIBCXX_CONSTEXPR int_type
00488       eof() _GLIBCXX_NOEXCEPT
00489       { return static_cast<int_type>(WEOF); }
00490 
00491       static _GLIBCXX_CONSTEXPR int_type
00492       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
00493       { return eq_int_type(__c, eof()) ? 0 : __c; }
00494   };
00495 #endif //_GLIBCXX_USE_WCHAR_T
00496 
00497 _GLIBCXX_END_NAMESPACE_VERSION
00498 } // namespace
00499 
00500 #if ((__cplusplus >= 201103L) \
00501      && defined(_GLIBCXX_USE_C99_STDINT_TR1))
00502 
00503 #include <cstdint>
00504 
00505 namespace std _GLIBCXX_VISIBILITY(default)
00506 {
00507 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00508 
00509   template<>
00510     struct char_traits<char16_t>
00511     {
00512       typedef char16_t          char_type;
00513       typedef uint_least16_t    int_type;
00514       typedef streamoff         off_type;
00515       typedef u16streampos      pos_type;
00516       typedef mbstate_t         state_type;
00517 
00518       static _GLIBCXX17_CONSTEXPR void
00519       assign(char_type& __c1, const char_type& __c2) noexcept
00520       { __c1 = __c2; }
00521 
00522       static constexpr bool
00523       eq(const char_type& __c1, const char_type& __c2) noexcept
00524       { return __c1 == __c2; }
00525 
00526       static constexpr bool
00527       lt(const char_type& __c1, const char_type& __c2) noexcept
00528       { return __c1 < __c2; }
00529 
00530       static _GLIBCXX17_CONSTEXPR int
00531       compare(const char_type* __s1, const char_type* __s2, size_t __n)
00532       {
00533         for (size_t __i = 0; __i < __n; ++__i)
00534           if (lt(__s1[__i], __s2[__i]))
00535             return -1;
00536           else if (lt(__s2[__i], __s1[__i]))
00537             return 1;
00538         return 0;
00539       }
00540 
00541       static _GLIBCXX17_CONSTEXPR size_t
00542       length(const char_type* __s)
00543       {
00544         size_t __i = 0;
00545         while (!eq(__s[__i], char_type()))
00546           ++__i;
00547         return __i;
00548       }
00549 
00550       static _GLIBCXX17_CONSTEXPR const char_type*
00551       find(const char_type* __s, size_t __n, const char_type& __a)
00552       {
00553         for (size_t __i = 0; __i < __n; ++__i)
00554           if (eq(__s[__i], __a))
00555             return __s + __i;
00556         return 0;
00557       }
00558 
00559       static char_type*
00560       move(char_type* __s1, const char_type* __s2, size_t __n)
00561       {
00562         if (__n == 0)
00563           return __s1;
00564         return (static_cast<char_type*>
00565                 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
00566       }
00567 
00568       static char_type*
00569       copy(char_type* __s1, const char_type* __s2, size_t __n)
00570       {
00571         if (__n == 0)
00572           return __s1;
00573         return (static_cast<char_type*>
00574                 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
00575       }
00576 
00577       static char_type*
00578       assign(char_type* __s, size_t __n, char_type __a)
00579       {
00580         for (size_t __i = 0; __i < __n; ++__i)
00581           assign(__s[__i], __a);
00582         return __s;
00583       }
00584 
00585       static constexpr char_type
00586       to_char_type(const int_type& __c) noexcept
00587       { return char_type(__c); }
00588 
00589       static constexpr int_type
00590       to_int_type(const char_type& __c) noexcept
00591       { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
00592 
00593       static constexpr bool
00594       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
00595       { return __c1 == __c2; }
00596 
00597       static constexpr int_type
00598       eof() noexcept
00599       { return static_cast<int_type>(-1); }
00600 
00601       static constexpr int_type
00602       not_eof(const int_type& __c) noexcept
00603       { return eq_int_type(__c, eof()) ? 0 : __c; }
00604     };
00605 
00606   template<>
00607     struct char_traits<char32_t>
00608     {
00609       typedef char32_t          char_type;
00610       typedef uint_least32_t    int_type;
00611       typedef streamoff         off_type;
00612       typedef u32streampos      pos_type;
00613       typedef mbstate_t         state_type;
00614 
00615       static _GLIBCXX17_CONSTEXPR void
00616       assign(char_type& __c1, const char_type& __c2) noexcept
00617       { __c1 = __c2; }
00618 
00619       static constexpr bool
00620       eq(const char_type& __c1, const char_type& __c2) noexcept
00621       { return __c1 == __c2; }
00622 
00623       static constexpr bool
00624       lt(const char_type& __c1, const char_type& __c2) noexcept
00625       { return __c1 < __c2; }
00626 
00627       static _GLIBCXX17_CONSTEXPR int
00628       compare(const char_type* __s1, const char_type* __s2, size_t __n)
00629       {
00630         for (size_t __i = 0; __i < __n; ++__i)
00631           if (lt(__s1[__i], __s2[__i]))
00632             return -1;
00633           else if (lt(__s2[__i], __s1[__i]))
00634             return 1;
00635         return 0;
00636       }
00637 
00638       static _GLIBCXX17_CONSTEXPR size_t
00639       length(const char_type* __s)
00640       {
00641         size_t __i = 0;
00642         while (!eq(__s[__i], char_type()))
00643           ++__i;
00644         return __i;
00645       }
00646 
00647       static _GLIBCXX17_CONSTEXPR const char_type*
00648       find(const char_type* __s, size_t __n, const char_type& __a)
00649       {
00650         for (size_t __i = 0; __i < __n; ++__i)
00651           if (eq(__s[__i], __a))
00652             return __s + __i;
00653         return 0;
00654       }
00655 
00656       static char_type*
00657       move(char_type* __s1, const char_type* __s2, size_t __n)
00658       {
00659         if (__n == 0)
00660           return __s1;
00661         return (static_cast<char_type*>
00662                 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
00663       }
00664 
00665       static char_type*
00666       copy(char_type* __s1, const char_type* __s2, size_t __n)
00667       { 
00668         if (__n == 0)
00669           return __s1;
00670         return (static_cast<char_type*>
00671                 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
00672       }
00673 
00674       static char_type*
00675       assign(char_type* __s, size_t __n, char_type __a)
00676       {
00677         for (size_t __i = 0; __i < __n; ++__i)
00678           assign(__s[__i], __a);
00679         return __s;
00680       }
00681 
00682       static constexpr char_type
00683       to_char_type(const int_type& __c) noexcept
00684       { return char_type(__c); }
00685 
00686       static constexpr int_type
00687       to_int_type(const char_type& __c) noexcept
00688       { return int_type(__c); }
00689 
00690       static constexpr bool
00691       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
00692       { return __c1 == __c2; }
00693 
00694       static constexpr int_type
00695       eof() noexcept
00696       { return static_cast<int_type>(-1); }
00697 
00698       static constexpr int_type
00699       not_eof(const int_type& __c) noexcept
00700       { return eq_int_type(__c, eof()) ? 0 : __c; }
00701     };
00702 
00703 _GLIBCXX_END_NAMESPACE_VERSION
00704 } // namespace
00705 
00706 #endif 
00707 
00708 #endif // _CHAR_TRAITS_H