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       return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
00187                                                     __n * sizeof(char_type)));
00188     }
00189 
00190   template<typename _CharT>
00191     typename char_traits<_CharT>::char_type*
00192     char_traits<_CharT>::
00193     copy(char_type* __s1, const char_type* __s2, std::size_t __n)
00194     {
00195       // NB: Inline std::copy so no recursive dependencies.
00196       std::copy(__s2, __s2 + __n, __s1);
00197       return __s1;
00198     }
00199 
00200   template<typename _CharT>
00201     typename char_traits<_CharT>::char_type*
00202     char_traits<_CharT>::
00203     assign(char_type* __s, std::size_t __n, char_type __a)
00204     {
00205       // NB: Inline std::fill_n so no recursive dependencies.
00206       std::fill_n(__s, __n, __a);
00207       return __s;
00208     }
00209 
00210 _GLIBCXX_END_NAMESPACE_VERSION
00211 } // namespace
00212 
00213 namespace std _GLIBCXX_VISIBILITY(default)
00214 {
00215 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00216 
00217 #if __cplusplus > 201402
00218 #define __cpp_lib_constexpr_char_traits 201611
00219 
00220   /**
00221    *  @brief Determine whether the characters of a NULL-terminated
00222    *  string are known at compile time.
00223    *  @param  __s  The string.
00224    *
00225    *  Assumes that _CharT is a built-in character type.
00226    */
00227   template<typename _CharT>
00228     static _GLIBCXX_ALWAYS_INLINE constexpr bool
00229     __constant_string_p(const _CharT* __s)
00230     {
00231       while (__builtin_constant_p(*__s) && *__s)
00232         __s++;
00233       return __builtin_constant_p(*__s);
00234     }
00235 
00236   /**
00237    *  @brief Determine whether the characters of a character array are
00238    *  known at compile time.
00239    *  @param  __a  The character array.
00240    *  @param  __n  Number of characters.
00241    *
00242    *  Assumes that _CharT is a built-in character type.
00243    */
00244   template<typename _CharT>
00245     static _GLIBCXX_ALWAYS_INLINE constexpr bool
00246     __constant_char_array_p(const _CharT* __a, size_t __n)
00247     {
00248       size_t __i = 0;
00249       while (__builtin_constant_p(__a[__i]) && __i < __n)
00250         __i++;
00251       return __i == __n;
00252     }
00253 #endif
00254 
00255   // 21.1
00256   /**
00257    *  @brief  Basis for explicit traits specializations.
00258    *
00259    *  @note  For any given actual character type, this definition is
00260    *  probably wrong.  Since this is just a thin wrapper around
00261    *  __gnu_cxx::char_traits, it is possible to achieve a more
00262    *  appropriate definition by specializing __gnu_cxx::char_traits.
00263    *
00264    *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
00265    *  for advice on how to make use of this class for @a unusual character
00266    *  types. Also, check out include/ext/pod_char_traits.h.
00267   */
00268   template<class _CharT>
00269     struct char_traits : public __gnu_cxx::char_traits<_CharT>
00270     { };
00271 
00272 
00273   /// 21.1.3.1  char_traits specializations
00274   template<>
00275     struct char_traits<char>
00276     {
00277       typedef char              char_type;
00278       typedef int               int_type;
00279       typedef streampos         pos_type;
00280       typedef streamoff         off_type;
00281       typedef mbstate_t         state_type;
00282 
00283       static _GLIBCXX17_CONSTEXPR void
00284       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00285       { __c1 = __c2; }
00286 
00287       static _GLIBCXX_CONSTEXPR bool
00288       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00289       { return __c1 == __c2; }
00290 
00291       static _GLIBCXX_CONSTEXPR bool
00292       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00293       {
00294         // LWG 467.
00295         return (static_cast<unsigned char>(__c1)
00296                 < static_cast<unsigned char>(__c2));
00297       }
00298 
00299       static _GLIBCXX17_CONSTEXPR int
00300       compare(const char_type* __s1, const char_type* __s2, size_t __n)
00301       {
00302 #if __cplusplus > 201402
00303         if (__builtin_constant_p(__n)
00304             && __constant_char_array_p(__s1, __n)
00305             && __constant_char_array_p(__s2, __n))
00306           return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
00307 #endif
00308         if (__n == 0)
00309           return 0;
00310         return __builtin_memcmp(__s1, __s2, __n);
00311       }
00312 
00313       static _GLIBCXX17_CONSTEXPR size_t
00314       length(const char_type* __s)
00315       {
00316 #if __cplusplus > 201402
00317         if (__constant_string_p(__s))
00318           return __gnu_cxx::char_traits<char_type>::length(__s);
00319 #endif
00320         return __builtin_strlen(__s);
00321       }
00322 
00323       static _GLIBCXX17_CONSTEXPR const char_type*
00324       find(const char_type* __s, size_t __n, const char_type& __a)
00325       {
00326 #if __cplusplus > 201402
00327         if (__builtin_constant_p(__n)
00328             && __builtin_constant_p(__a)
00329             && __constant_char_array_p(__s, __n))
00330           return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
00331 #endif
00332         if (__n == 0)
00333           return 0;
00334         return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
00335       }
00336 
00337       static char_type*
00338       move(char_type* __s1, const char_type* __s2, size_t __n)
00339       {
00340         if (__n == 0)
00341           return __s1;
00342         return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
00343       }
00344 
00345       static char_type*
00346       copy(char_type* __s1, const char_type* __s2, size_t __n)
00347       {
00348         if (__n == 0)
00349           return __s1;
00350         return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
00351       }
00352 
00353       static char_type*
00354       assign(char_type* __s, size_t __n, char_type __a)
00355       {
00356         if (__n == 0)
00357           return __s;
00358         return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
00359       }
00360 
00361       static _GLIBCXX_CONSTEXPR char_type
00362       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
00363       { return static_cast<char_type>(__c); }
00364 
00365       // To keep both the byte 0xff and the eof symbol 0xffffffff
00366       // from ending up as 0xffffffff.
00367       static _GLIBCXX_CONSTEXPR int_type
00368       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
00369       { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
00370 
00371       static _GLIBCXX_CONSTEXPR bool
00372       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
00373       { return __c1 == __c2; }
00374 
00375       static _GLIBCXX_CONSTEXPR int_type
00376       eof() _GLIBCXX_NOEXCEPT
00377       { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
00378 
00379       static _GLIBCXX_CONSTEXPR int_type
00380       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
00381       { return (__c == eof()) ? 0 : __c; }
00382   };
00383 
00384 
00385 #ifdef _GLIBCXX_USE_WCHAR_T
00386   /// 21.1.3.2  char_traits specializations
00387   template<>
00388     struct char_traits<wchar_t>
00389     {
00390       typedef wchar_t           char_type;
00391       typedef wint_t            int_type;
00392       typedef streamoff         off_type;
00393       typedef wstreampos        pos_type;
00394       typedef mbstate_t         state_type;
00395 
00396       static _GLIBCXX17_CONSTEXPR void
00397       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00398       { __c1 = __c2; }
00399 
00400       static _GLIBCXX_CONSTEXPR bool
00401       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00402       { return __c1 == __c2; }
00403 
00404       static _GLIBCXX_CONSTEXPR bool
00405       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
00406       { return __c1 < __c2; }
00407 
00408       static _GLIBCXX17_CONSTEXPR int
00409       compare(const char_type* __s1, const char_type* __s2, size_t __n)
00410       {
00411 #if __cplusplus > 201402
00412         if (__builtin_constant_p(__n)
00413             && __constant_char_array_p(__s1, __n)
00414             && __constant_char_array_p(__s2, __n))
00415           return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
00416 #endif
00417         if (__n == 0)
00418           return 0;
00419         else
00420           return wmemcmp(__s1, __s2, __n);
00421       }
00422 
00423       static _GLIBCXX17_CONSTEXPR size_t
00424       length(const char_type* __s)
00425       {
00426 #if __cplusplus > 201402
00427         if (__constant_string_p(__s))
00428           return __gnu_cxx::char_traits<char_type>::length(__s);
00429         else
00430 #endif
00431           return wcslen(__s);
00432       }
00433 
00434       static _GLIBCXX17_CONSTEXPR const char_type*
00435       find(const char_type* __s, size_t __n, const char_type& __a)
00436       {
00437 #if __cplusplus > 201402
00438         if (__builtin_constant_p(__n)
00439             && __builtin_constant_p(__a)
00440             && __constant_char_array_p(__s, __n))
00441           return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
00442 #endif
00443         if (__n == 0)
00444           return 0;
00445         else
00446           return wmemchr(__s, __a, __n);
00447       }
00448 
00449       static char_type*
00450       move(char_type* __s1, const char_type* __s2, size_t __n)
00451       {
00452         if (__n == 0)
00453           return __s1;
00454         return wmemmove(__s1, __s2, __n);
00455       }
00456 
00457       static char_type*
00458       copy(char_type* __s1, const char_type* __s2, size_t __n)
00459       {
00460         if (__n == 0)
00461           return __s1;
00462         return wmemcpy(__s1, __s2, __n);
00463       }
00464 
00465       static char_type*
00466       assign(char_type* __s, size_t __n, char_type __a)
00467       {
00468         if (__n == 0)
00469           return __s;
00470         return wmemset(__s, __a, __n);
00471       }
00472 
00473       static _GLIBCXX_CONSTEXPR char_type
00474       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
00475       { return char_type(__c); }
00476 
00477       static _GLIBCXX_CONSTEXPR int_type
00478       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
00479       { return int_type(__c); }
00480 
00481       static _GLIBCXX_CONSTEXPR bool
00482       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
00483       { return __c1 == __c2; }
00484 
00485       static _GLIBCXX_CONSTEXPR int_type
00486       eof() _GLIBCXX_NOEXCEPT
00487       { return static_cast<int_type>(WEOF); }
00488 
00489       static _GLIBCXX_CONSTEXPR int_type
00490       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
00491       { return eq_int_type(__c, eof()) ? 0 : __c; }
00492   };
00493 #endif //_GLIBCXX_USE_WCHAR_T
00494 
00495 _GLIBCXX_END_NAMESPACE_VERSION
00496 } // namespace
00497 
00498 #if ((__cplusplus >= 201103L) \
00499      && defined(_GLIBCXX_USE_C99_STDINT_TR1))
00500 
00501 #include <cstdint>
00502 
00503 namespace std _GLIBCXX_VISIBILITY(default)
00504 {
00505 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00506 
00507   template<>
00508     struct char_traits<char16_t>
00509     {
00510       typedef char16_t          char_type;
00511       typedef uint_least16_t    int_type;
00512       typedef streamoff         off_type;
00513       typedef u16streampos      pos_type;
00514       typedef mbstate_t         state_type;
00515 
00516       static _GLIBCXX17_CONSTEXPR void
00517       assign(char_type& __c1, const char_type& __c2) noexcept
00518       { __c1 = __c2; }
00519 
00520       static constexpr bool
00521       eq(const char_type& __c1, const char_type& __c2) noexcept
00522       { return __c1 == __c2; }
00523 
00524       static constexpr bool
00525       lt(const char_type& __c1, const char_type& __c2) noexcept
00526       { return __c1 < __c2; }
00527 
00528       static _GLIBCXX17_CONSTEXPR int
00529       compare(const char_type* __s1, const char_type* __s2, size_t __n)
00530       {
00531         for (size_t __i = 0; __i < __n; ++__i)
00532           if (lt(__s1[__i], __s2[__i]))
00533             return -1;
00534           else if (lt(__s2[__i], __s1[__i]))
00535             return 1;
00536         return 0;
00537       }
00538 
00539       static _GLIBCXX17_CONSTEXPR size_t
00540       length(const char_type* __s)
00541       {
00542         size_t __i = 0;
00543         while (!eq(__s[__i], char_type()))
00544           ++__i;
00545         return __i;
00546       }
00547 
00548       static _GLIBCXX17_CONSTEXPR const char_type*
00549       find(const char_type* __s, size_t __n, const char_type& __a)
00550       {
00551         for (size_t __i = 0; __i < __n; ++__i)
00552           if (eq(__s[__i], __a))
00553             return __s + __i;
00554         return 0;
00555       }
00556 
00557       static char_type*
00558       move(char_type* __s1, const char_type* __s2, size_t __n)
00559       {
00560         if (__n == 0)
00561           return __s1;
00562         return (static_cast<char_type*>
00563                 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
00564       }
00565 
00566       static char_type*
00567       copy(char_type* __s1, const char_type* __s2, size_t __n)
00568       {
00569         if (__n == 0)
00570           return __s1;
00571         return (static_cast<char_type*>
00572                 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
00573       }
00574 
00575       static char_type*
00576       assign(char_type* __s, size_t __n, char_type __a)
00577       {
00578         for (size_t __i = 0; __i < __n; ++__i)
00579           assign(__s[__i], __a);
00580         return __s;
00581       }
00582 
00583       static constexpr char_type
00584       to_char_type(const int_type& __c) noexcept
00585       { return char_type(__c); }
00586 
00587       static constexpr int_type
00588       to_int_type(const char_type& __c) noexcept
00589       { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
00590 
00591       static constexpr bool
00592       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
00593       { return __c1 == __c2; }
00594 
00595       static constexpr int_type
00596       eof() noexcept
00597       { return static_cast<int_type>(-1); }
00598 
00599       static constexpr int_type
00600       not_eof(const int_type& __c) noexcept
00601       { return eq_int_type(__c, eof()) ? 0 : __c; }
00602     };
00603 
00604   template<>
00605     struct char_traits<char32_t>
00606     {
00607       typedef char32_t          char_type;
00608       typedef uint_least32_t    int_type;
00609       typedef streamoff         off_type;
00610       typedef u32streampos      pos_type;
00611       typedef mbstate_t         state_type;
00612 
00613       static _GLIBCXX17_CONSTEXPR void
00614       assign(char_type& __c1, const char_type& __c2) noexcept
00615       { __c1 = __c2; }
00616 
00617       static constexpr bool
00618       eq(const char_type& __c1, const char_type& __c2) noexcept
00619       { return __c1 == __c2; }
00620 
00621       static constexpr bool
00622       lt(const char_type& __c1, const char_type& __c2) noexcept
00623       { return __c1 < __c2; }
00624 
00625       static _GLIBCXX17_CONSTEXPR int
00626       compare(const char_type* __s1, const char_type* __s2, size_t __n)
00627       {
00628         for (size_t __i = 0; __i < __n; ++__i)
00629           if (lt(__s1[__i], __s2[__i]))
00630             return -1;
00631           else if (lt(__s2[__i], __s1[__i]))
00632             return 1;
00633         return 0;
00634       }
00635 
00636       static _GLIBCXX17_CONSTEXPR size_t
00637       length(const char_type* __s)
00638       {
00639         size_t __i = 0;
00640         while (!eq(__s[__i], char_type()))
00641           ++__i;
00642         return __i;
00643       }
00644 
00645       static _GLIBCXX17_CONSTEXPR const char_type*
00646       find(const char_type* __s, size_t __n, const char_type& __a)
00647       {
00648         for (size_t __i = 0; __i < __n; ++__i)
00649           if (eq(__s[__i], __a))
00650             return __s + __i;
00651         return 0;
00652       }
00653 
00654       static char_type*
00655       move(char_type* __s1, const char_type* __s2, size_t __n)
00656       {
00657         if (__n == 0)
00658           return __s1;
00659         return (static_cast<char_type*>
00660                 (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
00661       }
00662 
00663       static char_type*
00664       copy(char_type* __s1, const char_type* __s2, size_t __n)
00665       { 
00666         if (__n == 0)
00667           return __s1;
00668         return (static_cast<char_type*>
00669                 (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
00670       }
00671 
00672       static char_type*
00673       assign(char_type* __s, size_t __n, char_type __a)
00674       {
00675         for (size_t __i = 0; __i < __n; ++__i)
00676           assign(__s[__i], __a);
00677         return __s;
00678       }
00679 
00680       static constexpr char_type
00681       to_char_type(const int_type& __c) noexcept
00682       { return char_type(__c); }
00683 
00684       static constexpr int_type
00685       to_int_type(const char_type& __c) noexcept
00686       { return int_type(__c); }
00687 
00688       static constexpr bool
00689       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
00690       { return __c1 == __c2; }
00691 
00692       static constexpr int_type
00693       eof() noexcept
00694       { return static_cast<int_type>(-1); }
00695 
00696       static constexpr int_type
00697       not_eof(const int_type& __c) noexcept
00698       { return eq_int_type(__c, eof()) ? 0 : __c; }
00699     };
00700 
00701 _GLIBCXX_END_NAMESPACE_VERSION
00702 } // namespace
00703 
00704 #endif 
00705 
00706 #endif // _CHAR_TRAITS_H