1    	// Character Traits for use by standard string and iostream -*- C++ -*-
2    	
3    	// Copyright (C) 1997-2017 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/stl_algobase.h>  // std::copy, std::fill_n
40   	#include <bits/postypes.h>      // For streampos
41   	#include <cwchar>               // For WEOF, wmemmove, wmemset, etc.
42   	
43   	#ifndef _GLIBCXX_ALWAYS_INLINE
44   	#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
45   	#endif
46   	
47   	namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
48   	{
49   	_GLIBCXX_BEGIN_NAMESPACE_VERSION
50   	
51   	  /**
52   	   *  @brief  Mapping from character type to associated types.
53   	   *
54   	   *  @note This is an implementation class for the generic version
55   	   *  of char_traits.  It defines int_type, off_type, pos_type, and
56   	   *  state_type.  By default these are unsigned long, streamoff,
57   	   *  streampos, and mbstate_t.  Users who need a different set of
58   	   *  types, but who don't need to change the definitions of any function
59   	   *  defined in char_traits, can specialize __gnu_cxx::_Char_types
60   	   *  while leaving __gnu_cxx::char_traits alone. */
61   	  template<typename _CharT>
62   	    struct _Char_types
63   	    {
64   	      typedef unsigned long   int_type;
65   	      typedef std::streampos  pos_type;
66   	      typedef std::streamoff  off_type;
67   	      typedef std::mbstate_t  state_type;
68   	    };
69   	
70   	
71   	  /**
72   	   *  @brief  Base class used to implement std::char_traits.
73   	   *
74   	   *  @note For any given actual character type, this definition is
75   	   *  probably wrong.  (Most of the member functions are likely to be
76   	   *  right, but the int_type and state_type typedefs, and the eof()
77   	   *  member function, are likely to be wrong.)  The reason this class
78   	   *  exists is so users can specialize it.  Classes in namespace std
79   	   *  may not be specialized for fundamental types, but classes in
80   	   *  namespace __gnu_cxx may be.
81   	   *
82   	   *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
83   	   *  for advice on how to make use of this class for @a unusual character
84   	   *  types. Also, check out include/ext/pod_char_traits.h.  
85   	   */
86   	  template<typename _CharT>
87   	    struct char_traits
88   	    {
89   	      typedef _CharT                                    char_type;
90   	      typedef typename _Char_types<_CharT>::int_type    int_type;
91   	      typedef typename _Char_types<_CharT>::pos_type    pos_type;
92   	      typedef typename _Char_types<_CharT>::off_type    off_type;
93   	      typedef typename _Char_types<_CharT>::state_type  state_type;
94   	
95   	      static _GLIBCXX14_CONSTEXPR void
96   	      assign(char_type& __c1, const char_type& __c2)
97   	      { __c1 = __c2; }
98   	
99   	      static _GLIBCXX_CONSTEXPR bool
100  	      eq(const char_type& __c1, const char_type& __c2)
101  	      { return __c1 == __c2; }
102  	
103  	      static _GLIBCXX_CONSTEXPR bool
104  	      lt(const char_type& __c1, const char_type& __c2)
105  	      { return __c1 < __c2; }
106  	
107  	      static _GLIBCXX14_CONSTEXPR int
108  	      compare(const char_type* __s1, const char_type* __s2, std::size_t __n);
109  	
110  	      static _GLIBCXX14_CONSTEXPR std::size_t
111  	      length(const char_type* __s);
112  	
113  	      static _GLIBCXX14_CONSTEXPR const char_type*
114  	      find(const char_type* __s, std::size_t __n, const char_type& __a);
115  	
116  	      static char_type*
117  	      move(char_type* __s1, const char_type* __s2, std::size_t __n);
118  	
119  	      static char_type*
120  	      copy(char_type* __s1, const char_type* __s2, std::size_t __n);
121  	
122  	      static char_type*
123  	      assign(char_type* __s, std::size_t __n, char_type __a);
124  	
125  	      static _GLIBCXX_CONSTEXPR char_type
126  	      to_char_type(const int_type& __c)
127  	      { return static_cast<char_type>(__c); }
128  	
129  	      static _GLIBCXX_CONSTEXPR int_type
130  	      to_int_type(const char_type& __c)
131  	      { return static_cast<int_type>(__c); }
132  	
133  	      static _GLIBCXX_CONSTEXPR bool
134  	      eq_int_type(const int_type& __c1, const int_type& __c2)
135  	      { return __c1 == __c2; }
136  	
137  	      static _GLIBCXX_CONSTEXPR int_type
138  	      eof()
139  	      { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
140  	
141  	      static _GLIBCXX_CONSTEXPR int_type
142  	      not_eof(const int_type& __c)
143  	      { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); }
144  	    };
145  	
146  	  template<typename _CharT>
147  	    _GLIBCXX14_CONSTEXPR int
148  	    char_traits<_CharT>::
149  	    compare(const char_type* __s1, const char_type* __s2, std::size_t __n)
150  	    {
151  	      for (std::size_t __i = 0; __i < __n; ++__i)
152  		if (lt(__s1[__i], __s2[__i]))
153  		  return -1;
154  		else if (lt(__s2[__i], __s1[__i]))
155  		  return 1;
156  	      return 0;
157  	    }
158  	
159  	  template<typename _CharT>
160  	    _GLIBCXX14_CONSTEXPR std::size_t
161  	    char_traits<_CharT>::
162  	    length(const char_type* __p)
163  	    {
164  	      std::size_t __i = 0;
165  	      while (!eq(__p[__i], char_type()))
166  	        ++__i;
167  	      return __i;
168  	    }
169  	
170  	  template<typename _CharT>
171  	    _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type*
172  	    char_traits<_CharT>::
173  	    find(const char_type* __s, std::size_t __n, const char_type& __a)
174  	    {
175  	      for (std::size_t __i = 0; __i < __n; ++__i)
176  	        if (eq(__s[__i], __a))
177  	          return __s + __i;
178  	      return 0;
179  	    }
180  	
181  	  template<typename _CharT>
182  	    typename char_traits<_CharT>::char_type*
183  	    char_traits<_CharT>::
184  	    move(char_type* __s1, const char_type* __s2, std::size_t __n)
185  	    {
186  	      return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
187  							    __n * sizeof(char_type)));
188  	    }
189  	
190  	  template<typename _CharT>
191  	    typename char_traits<_CharT>::char_type*
192  	    char_traits<_CharT>::
193  	    copy(char_type* __s1, const char_type* __s2, std::size_t __n)
194  	    {
195  	      // NB: Inline std::copy so no recursive dependencies.
196  	      std::copy(__s2, __s2 + __n, __s1);
197  	      return __s1;
198  	    }
199  	
200  	  template<typename _CharT>
201  	    typename char_traits<_CharT>::char_type*
202  	    char_traits<_CharT>::
203  	    assign(char_type* __s, std::size_t __n, char_type __a)
204  	    {
205  	      // NB: Inline std::fill_n so no recursive dependencies.
206  	      std::fill_n(__s, __n, __a);
207  	      return __s;
208  	    }
209  	
210  	_GLIBCXX_END_NAMESPACE_VERSION
211  	} // namespace
212  	
213  	namespace std _GLIBCXX_VISIBILITY(default)
214  	{
215  	_GLIBCXX_BEGIN_NAMESPACE_VERSION
216  	
217  	#if __cplusplus > 201402
218  	#define __cpp_lib_constexpr_char_traits 201611
219  	
220  	  /**
221  	   *  @brief Determine whether the characters of a NULL-terminated
222  	   *  string are known at compile time.
223  	   *  @param  __s  The string.
224  	   *
225  	   *  Assumes that _CharT is a built-in character type.
226  	   */
227  	  template<typename _CharT>
228  	    static _GLIBCXX_ALWAYS_INLINE constexpr bool
229  	    __constant_string_p(const _CharT* __s)
230  	    {
231  	      while (__builtin_constant_p(*__s) && *__s)
232  		__s++;
233  	      return __builtin_constant_p(*__s);
234  	    }
235  	
236  	  /**
237  	   *  @brief Determine whether the characters of a character array are
238  	   *  known at compile time.
239  	   *  @param  __a  The character array.
240  	   *  @param  __n  Number of characters.
241  	   *
242  	   *  Assumes that _CharT is a built-in character type.
243  	   */
244  	  template<typename _CharT>
245  	    static _GLIBCXX_ALWAYS_INLINE constexpr bool
246  	    __constant_char_array_p(const _CharT* __a, size_t __n)
247  	    {
248  	      size_t __i = 0;
249  	      while (__builtin_constant_p(__a[__i]) && __i < __n)
250  		__i++;
251  	      return __i == __n;
252  	    }
253  	#endif
254  	
255  	  // 21.1
256  	  /**
257  	   *  @brief  Basis for explicit traits specializations.
258  	   *
259  	   *  @note  For any given actual character type, this definition is
260  	   *  probably wrong.  Since this is just a thin wrapper around
261  	   *  __gnu_cxx::char_traits, it is possible to achieve a more
262  	   *  appropriate definition by specializing __gnu_cxx::char_traits.
263  	   *
264  	   *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
265  	   *  for advice on how to make use of this class for @a unusual character
266  	   *  types. Also, check out include/ext/pod_char_traits.h.
267  	  */
268  	  template<class _CharT>
269  	    struct char_traits : public __gnu_cxx::char_traits<_CharT>
270  	    { };
271  	
272  	
273  	  /// 21.1.3.1  char_traits specializations
274  	  template<>
275  	    struct char_traits<char>
276  	    {
277  	      typedef char              char_type;
278  	      typedef int               int_type;
279  	      typedef streampos         pos_type;
280  	      typedef streamoff         off_type;
281  	      typedef mbstate_t         state_type;
282  	
283  	      static _GLIBCXX17_CONSTEXPR void
284  	      assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
285  	      { __c1 = __c2; }
286  	
287  	      static _GLIBCXX_CONSTEXPR bool
288  	      eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
289  	      { return __c1 == __c2; }
290  	
291  	      static _GLIBCXX_CONSTEXPR bool
292  	      lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
293  	      {
294  		// LWG 467.
295  		return (static_cast<unsigned char>(__c1)
296  			< static_cast<unsigned char>(__c2));
297  	      }
298  	
299  	      static _GLIBCXX17_CONSTEXPR int
300  	      compare(const char_type* __s1, const char_type* __s2, size_t __n)
301  	      {
302  	#if __cplusplus > 201402
303  		if (__builtin_constant_p(__n)
304  		    && __constant_char_array_p(__s1, __n)
305  		    && __constant_char_array_p(__s2, __n))
306  		  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
307  	#endif
308  		if (__n == 0)
309  		  return 0;
310  		return __builtin_memcmp(__s1, __s2, __n);
311  	      }
312  	
313  	      static _GLIBCXX17_CONSTEXPR size_t
314  	      length(const char_type* __s)
315  	      {
316  	#if __cplusplus > 201402
317  		if (__constant_string_p(__s))
318  		  return __gnu_cxx::char_traits<char_type>::length(__s);
319  	#endif
320  		return __builtin_strlen(__s);
321  	      }
322  	
323  	      static _GLIBCXX17_CONSTEXPR const char_type*
324  	      find(const char_type* __s, size_t __n, const char_type& __a)
325  	      {
326  	#if __cplusplus > 201402
327  		if (__builtin_constant_p(__n)
328  		    && __builtin_constant_p(__a)
329  		    && __constant_char_array_p(__s, __n))
330  		  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
331  	#endif
332  		if (__n == 0)
333  		  return 0;
334  		return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
335  	      }
336  	
337  	      static char_type*
338  	      move(char_type* __s1, const char_type* __s2, size_t __n)
339  	      {
340  		if (__n == 0)
341  		  return __s1;
342  		return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
343  	      }
344  	
345  	      static char_type*
346  	      copy(char_type* __s1, const char_type* __s2, size_t __n)
347  	      {
348  		if (__n == 0)
349  		  return __s1;
350  		return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
351  	      }
352  	
353  	      static char_type*
354  	      assign(char_type* __s, size_t __n, char_type __a)
355  	      {
356  		if (__n == 0)
357  		  return __s;
358  		return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
359  	      }
360  	
361  	      static _GLIBCXX_CONSTEXPR char_type
362  	      to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
363  	      { return static_cast<char_type>(__c); }
364  	
365  	      // To keep both the byte 0xff and the eof symbol 0xffffffff
366  	      // from ending up as 0xffffffff.
367  	      static _GLIBCXX_CONSTEXPR int_type
368  	      to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
369  	      { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
370  	
371  	      static _GLIBCXX_CONSTEXPR bool
372  	      eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
373  	      { return __c1 == __c2; }
374  	
375  	      static _GLIBCXX_CONSTEXPR int_type
376  	      eof() _GLIBCXX_NOEXCEPT
377  	      { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
378  	
379  	      static _GLIBCXX_CONSTEXPR int_type
380  	      not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
381  	      { return (__c == eof()) ? 0 : __c; }
382  	  };
383  	
384  	
385  	#ifdef _GLIBCXX_USE_WCHAR_T
386  	  /// 21.1.3.2  char_traits specializations
387  	  template<>
388  	    struct char_traits<wchar_t>
389  	    {
390  	      typedef wchar_t           char_type;
391  	      typedef wint_t            int_type;
392  	      typedef streamoff         off_type;
393  	      typedef wstreampos        pos_type;
394  	      typedef mbstate_t         state_type;
395  	
396  	      static _GLIBCXX17_CONSTEXPR void
397  	      assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
398  	      { __c1 = __c2; }
399  	
400  	      static _GLIBCXX_CONSTEXPR bool
401  	      eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
402  	      { return __c1 == __c2; }
403  	
404  	      static _GLIBCXX_CONSTEXPR bool
405  	      lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
406  	      { return __c1 < __c2; }
407  	
408  	      static _GLIBCXX17_CONSTEXPR int
409  	      compare(const char_type* __s1, const char_type* __s2, size_t __n)
410  	      {
411  	#if __cplusplus > 201402
412  		if (__builtin_constant_p(__n)
413  		    && __constant_char_array_p(__s1, __n)
414  		    && __constant_char_array_p(__s2, __n))
415  		  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
416  	#endif
417  		if (__n == 0)
418  		  return 0;
419  		else
420  		  return wmemcmp(__s1, __s2, __n);
421  	      }
422  	
423  	      static _GLIBCXX17_CONSTEXPR size_t
424  	      length(const char_type* __s)
425  	      {
426  	#if __cplusplus > 201402
427  		if (__constant_string_p(__s))
428  		  return __gnu_cxx::char_traits<char_type>::length(__s);
429  		else
430  	#endif
431  		  return wcslen(__s);
432  	      }
433  	
434  	      static _GLIBCXX17_CONSTEXPR const char_type*
435  	      find(const char_type* __s, size_t __n, const char_type& __a)
436  	      {
437  	#if __cplusplus > 201402
438  		if (__builtin_constant_p(__n)
439  		    && __builtin_constant_p(__a)
440  		    && __constant_char_array_p(__s, __n))
441  		  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
442  	#endif
443  		if (__n == 0)
444  		  return 0;
445  		else
446  		  return wmemchr(__s, __a, __n);
447  	      }
448  	
449  	      static char_type*
450  	      move(char_type* __s1, const char_type* __s2, size_t __n)
451  	      {
452  		if (__n == 0)
453  		  return __s1;
454  		return wmemmove(__s1, __s2, __n);
455  	      }
456  	
457  	      static char_type*
458  	      copy(char_type* __s1, const char_type* __s2, size_t __n)
459  	      {
460  		if (__n == 0)
461  		  return __s1;
462  		return wmemcpy(__s1, __s2, __n);
463  	      }
464  	
465  	      static char_type*
466  	      assign(char_type* __s, size_t __n, char_type __a)
467  	      {
468  		if (__n == 0)
469  		  return __s;
470  		return wmemset(__s, __a, __n);
471  	      }
472  	
473  	      static _GLIBCXX_CONSTEXPR char_type
474  	      to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
475  	      { return char_type(__c); }
476  	
477  	      static _GLIBCXX_CONSTEXPR int_type
478  	      to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
479  	      { return int_type(__c); }
480  	
481  	      static _GLIBCXX_CONSTEXPR bool
482  	      eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
483  	      { return __c1 == __c2; }
484  	
485  	      static _GLIBCXX_CONSTEXPR int_type
486  	      eof() _GLIBCXX_NOEXCEPT
487  	      { return static_cast<int_type>(WEOF); }
488  	
489  	      static _GLIBCXX_CONSTEXPR int_type
490  	      not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
491  	      { return eq_int_type(__c, eof()) ? 0 : __c; }
492  	  };
493  	#endif //_GLIBCXX_USE_WCHAR_T
494  	
495  	_GLIBCXX_END_NAMESPACE_VERSION
496  	} // namespace
497  	
498  	#if ((__cplusplus >= 201103L) \
499  	     && defined(_GLIBCXX_USE_C99_STDINT_TR1))
500  	
501  	#include <cstdint>
502  	
503  	namespace std _GLIBCXX_VISIBILITY(default)
504  	{
505  	_GLIBCXX_BEGIN_NAMESPACE_VERSION
506  	
507  	  template<>
508  	    struct char_traits<char16_t>
509  	    {
510  	      typedef char16_t          char_type;
511  	      typedef uint_least16_t    int_type;
512  	      typedef streamoff         off_type;
513  	      typedef u16streampos      pos_type;
514  	      typedef mbstate_t         state_type;
515  	
516  	      static _GLIBCXX17_CONSTEXPR void
517  	      assign(char_type& __c1, const char_type& __c2) noexcept
518  	      { __c1 = __c2; }
519  	
520  	      static constexpr bool
521  	      eq(const char_type& __c1, const char_type& __c2) noexcept
522  	      { return __c1 == __c2; }
523  	
524  	      static constexpr bool
525  	      lt(const char_type& __c1, const char_type& __c2) noexcept
526  	      { return __c1 < __c2; }
527  	
528  	      static _GLIBCXX17_CONSTEXPR int
529  	      compare(const char_type* __s1, const char_type* __s2, size_t __n)
530  	      {
531  		for (size_t __i = 0; __i < __n; ++__i)
532  		  if (lt(__s1[__i], __s2[__i]))
533  		    return -1;
534  		  else if (lt(__s2[__i], __s1[__i]))
535  		    return 1;
536  		return 0;
537  	      }
538  	
539  	      static _GLIBCXX17_CONSTEXPR size_t
540  	      length(const char_type* __s)
541  	      {
542  		size_t __i = 0;
543  		while (!eq(__s[__i], char_type()))
544  		  ++__i;
545  		return __i;
546  	      }
547  	
548  	      static _GLIBCXX17_CONSTEXPR const char_type*
549  	      find(const char_type* __s, size_t __n, const char_type& __a)
550  	      {
551  		for (size_t __i = 0; __i < __n; ++__i)
552  		  if (eq(__s[__i], __a))
553  		    return __s + __i;
554  		return 0;
555  	      }
556  	
557  	      static char_type*
558  	      move(char_type* __s1, const char_type* __s2, size_t __n)
559  	      {
560  		if (__n == 0)
561  		  return __s1;
562  		return (static_cast<char_type*>
563  			(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
564  	      }
565  	
566  	      static char_type*
567  	      copy(char_type* __s1, const char_type* __s2, size_t __n)
568  	      {
569  		if (__n == 0)
570  		  return __s1;
571  		return (static_cast<char_type*>
572  			(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
573  	      }
574  	
575  	      static char_type*
576  	      assign(char_type* __s, size_t __n, char_type __a)
577  	      {
578  		for (size_t __i = 0; __i < __n; ++__i)
579  		  assign(__s[__i], __a);
580  		return __s;
581  	      }
582  	
583  	      static constexpr char_type
584  	      to_char_type(const int_type& __c) noexcept
585  	      { return char_type(__c); }
586  	
587  	      static constexpr int_type
588  	      to_int_type(const char_type& __c) noexcept
589  	      { return int_type(__c); }
590  	
591  	      static constexpr bool
592  	      eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
593  	      { return __c1 == __c2; }
594  	
595  	      static constexpr int_type
596  	      eof() noexcept
597  	      { return static_cast<int_type>(-1); }
598  	
599  	      static constexpr int_type
600  	      not_eof(const int_type& __c) noexcept
601  	      { return eq_int_type(__c, eof()) ? 0 : __c; }
602  	    };
603  	
604  	  template<>
605  	    struct char_traits<char32_t>
606  	    {
607  	      typedef char32_t          char_type;
608  	      typedef uint_least32_t    int_type;
609  	      typedef streamoff         off_type;
610  	      typedef u32streampos      pos_type;
611  	      typedef mbstate_t         state_type;
612  	
613  	      static _GLIBCXX17_CONSTEXPR void
614  	      assign(char_type& __c1, const char_type& __c2) noexcept
615  	      { __c1 = __c2; }
616  	
617  	      static constexpr bool
618  	      eq(const char_type& __c1, const char_type& __c2) noexcept
619  	      { return __c1 == __c2; }
620  	
621  	      static constexpr bool
622  	      lt(const char_type& __c1, const char_type& __c2) noexcept
623  	      { return __c1 < __c2; }
624  	
625  	      static _GLIBCXX17_CONSTEXPR int
626  	      compare(const char_type* __s1, const char_type* __s2, size_t __n)
627  	      {
628  		for (size_t __i = 0; __i < __n; ++__i)
629  		  if (lt(__s1[__i], __s2[__i]))
630  		    return -1;
631  		  else if (lt(__s2[__i], __s1[__i]))
632  		    return 1;
633  		return 0;
634  	      }
635  	
636  	      static _GLIBCXX17_CONSTEXPR size_t
637  	      length(const char_type* __s)
638  	      {
639  		size_t __i = 0;
640  		while (!eq(__s[__i], char_type()))
641  		  ++__i;
642  		return __i;
643  	      }
644  	
645  	      static _GLIBCXX17_CONSTEXPR const char_type*
646  	      find(const char_type* __s, size_t __n, const char_type& __a)
647  	      {
648  		for (size_t __i = 0; __i < __n; ++__i)
649  		  if (eq(__s[__i], __a))
650  		    return __s + __i;
651  		return 0;
652  	      }
653  	
654  	      static char_type*
655  	      move(char_type* __s1, const char_type* __s2, size_t __n)
656  	      {
657  		if (__n == 0)
658  		  return __s1;
659  		return (static_cast<char_type*>
660  			(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
661  	      }
662  	
663  	      static char_type*
664  	      copy(char_type* __s1, const char_type* __s2, size_t __n)
665  	      { 
666  		if (__n == 0)
667  		  return __s1;
668  		return (static_cast<char_type*>
669  			(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
670  	      }
671  	
672  	      static char_type*
673  	      assign(char_type* __s, size_t __n, char_type __a)
674  	      {
675  		for (size_t __i = 0; __i < __n; ++__i)
676  		  assign(__s[__i], __a);
677  		return __s;
678  	      }
679  	
680  	      static constexpr char_type
681  	      to_char_type(const int_type& __c) noexcept
682  	      { return char_type(__c); }
683  	
684  	      static constexpr int_type
685  	      to_int_type(const char_type& __c) noexcept
686  	      { return int_type(__c); }
687  	
688  	      static constexpr bool
689  	      eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
690  	      { return __c1 == __c2; }
691  	
692  	      static constexpr int_type
693  	      eof() noexcept
694  	      { return static_cast<int_type>(-1); }
695  	
696  	      static constexpr int_type
697  	      not_eof(const int_type& __c) noexcept
698  	      { return eq_int_type(__c, eof()) ? 0 : __c; }
699  	    };
700  	
701  	_GLIBCXX_END_NAMESPACE_VERSION
702  	} // namespace
703  	
704  	#endif 
705  	
706  	#endif // _CHAR_TRAITS_H
707