1 // Character Traits for use by standard string and iostream -*- C++ -*-
2 
3 // Copyright (C) 1997-2019 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 
_GLIBCXX_VISIBILITY(default)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       if (__n == 0)
187 	return __s1;
188       return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
189 						    __n * sizeof(char_type)));
190     }
191 
192   template<typename _CharT>
193     typename char_traits<_CharT>::char_type*
194     char_traits<_CharT>::
195     copy(char_type* __s1, const char_type* __s2, std::size_t __n)
196     {
197       // NB: Inline std::copy so no recursive dependencies.
198       std::copy(__s2, __s2 + __n, __s1);
199       return __s1;
200     }
201 
202   template<typename _CharT>
203     typename char_traits<_CharT>::char_type*
204     char_traits<_CharT>::
205     assign(char_type* __s, std::size_t __n, char_type __a)
206     {
207       // NB: Inline std::fill_n so no recursive dependencies.
208       std::fill_n(__s, __n, __a);
209       return __s;
210     }
211 
212 _GLIBCXX_END_NAMESPACE_VERSION
213 } // namespace
214 
_GLIBCXX_VISIBILITY(default)215 namespace std _GLIBCXX_VISIBILITY(default)
216 {
217 _GLIBCXX_BEGIN_NAMESPACE_VERSION
218 
219 #if __cplusplus >= 201703L
220 #define __cpp_lib_constexpr_char_traits 201611
221 
222   /**
223    *  @brief Determine whether the characters of a NULL-terminated
224    *  string are known at compile time.
225    *  @param  __s  The string.
226    *
227    *  Assumes that _CharT is a built-in character type.
228    */
229   template<typename _CharT>
230     static _GLIBCXX_ALWAYS_INLINE constexpr bool
231     __constant_string_p(const _CharT* __s)
232     {
233 #ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
234       (void) __s;
235       // In constexpr contexts all strings should be constant.
236       return __builtin_is_constant_evaluated();
237 #else
238       while (__builtin_constant_p(*__s) && *__s)
239 	__s++;
240       return __builtin_constant_p(*__s);
241 #endif
242     }
243 
244   /**
245    *  @brief Determine whether the characters of a character array are
246    *  known at compile time.
247    *  @param  __a  The character array.
248    *  @param  __n  Number of characters.
249    *
250    *  Assumes that _CharT is a built-in character type.
251    */
252   template<typename _CharT>
253     static _GLIBCXX_ALWAYS_INLINE constexpr bool
254     __constant_char_array_p(const _CharT* __a, size_t __n)
255     {
256 #ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
257       (void) __a;
258       (void) __n;
259       // In constexpr contexts all character arrays should be constant.
260       return __builtin_is_constant_evaluated();
261 #else
262       size_t __i = 0;
263       while (__i < __n && __builtin_constant_p(__a[__i]))
264 	__i++;
265       return __i == __n;
266 #endif
267     }
268 #endif
269 
270   // 21.1
271   /**
272    *  @brief  Basis for explicit traits specializations.
273    *
274    *  @note  For any given actual character type, this definition is
275    *  probably wrong.  Since this is just a thin wrapper around
276    *  __gnu_cxx::char_traits, it is possible to achieve a more
277    *  appropriate definition by specializing __gnu_cxx::char_traits.
278    *
279    *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
280    *  for advice on how to make use of this class for @a unusual character
281    *  types. Also, check out include/ext/pod_char_traits.h.
282   */
283   template<class _CharT>
284     struct char_traits : public __gnu_cxx::char_traits<_CharT>
285     { };
286 
287 
288   /// 21.1.3.1  char_traits specializations
289   template<>
290     struct char_traits<char>
291     {
292       typedef char              char_type;
293       typedef int               int_type;
294       typedef streampos         pos_type;
295       typedef streamoff         off_type;
296       typedef mbstate_t         state_type;
297 
298       static _GLIBCXX17_CONSTEXPR void
299       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
300       { __c1 = __c2; }
301 
302       static _GLIBCXX_CONSTEXPR bool
303       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
304       { return __c1 == __c2; }
305 
306       static _GLIBCXX_CONSTEXPR bool
307       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
308       {
309 	// LWG 467.
310 	return (static_cast<unsigned char>(__c1)
311 		< static_cast<unsigned char>(__c2));
312       }
313 
314       static _GLIBCXX17_CONSTEXPR int
315       compare(const char_type* __s1, const char_type* __s2, size_t __n)
316       {
317 	if (__n == 0)
318 	  return 0;
319 #if __cplusplus >= 201703L
320 	if (__builtin_constant_p(__n)
321 	    && __constant_char_array_p(__s1, __n)
322 	    && __constant_char_array_p(__s2, __n))
323 	  {
324 	    for (size_t __i = 0; __i < __n; ++__i)
325 	      if (lt(__s1[__i], __s2[__i]))
326 		return -1;
327 	      else if (lt(__s2[__i], __s1[__i]))
328 		return 1;
329 	    return 0;
330 	  }
331 #endif
332 	return __builtin_memcmp(__s1, __s2, __n);
333       }
334 
335       static _GLIBCXX17_CONSTEXPR size_t
336       length(const char_type* __s)
337       {
338 #if __cplusplus >= 201703L
339 	if (__constant_string_p(__s))
340 	  return __gnu_cxx::char_traits<char_type>::length(__s);
341 #endif
342 	return __builtin_strlen(__s);
343       }
344 
345       static _GLIBCXX17_CONSTEXPR const char_type*
346       find(const char_type* __s, size_t __n, const char_type& __a)
347       {
348 	if (__n == 0)
349 	  return 0;
350 #if __cplusplus >= 201703L
351 	if (__builtin_constant_p(__n)
352 	    && __builtin_constant_p(__a)
353 	    && __constant_char_array_p(__s, __n))
354 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
355 #endif
356 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
357       }
358 
359       static char_type*
360       move(char_type* __s1, const char_type* __s2, size_t __n)
361       {
362 	if (__n == 0)
363 	  return __s1;
364 	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
365       }
366 
367       static char_type*
368       copy(char_type* __s1, const char_type* __s2, size_t __n)
369       {
370 	if (__n == 0)
371 	  return __s1;
372 	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
373       }
374 
375       static char_type*
376       assign(char_type* __s, size_t __n, char_type __a)
377       {
378 	if (__n == 0)
379 	  return __s;
380 	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
381       }
382 
383       static _GLIBCXX_CONSTEXPR char_type
384       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
385       { return static_cast<char_type>(__c); }
386 
387       // To keep both the byte 0xff and the eof symbol 0xffffffff
388       // from ending up as 0xffffffff.
389       static _GLIBCXX_CONSTEXPR int_type
390       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
391       { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
392 
393       static _GLIBCXX_CONSTEXPR bool
394       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
395       { return __c1 == __c2; }
396 
397       static _GLIBCXX_CONSTEXPR int_type
398       eof() _GLIBCXX_NOEXCEPT
399       { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
400 
401       static _GLIBCXX_CONSTEXPR int_type
402       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
403       { return (__c == eof()) ? 0 : __c; }
404   };
405 
406 
407 #ifdef _GLIBCXX_USE_WCHAR_T
408   /// 21.1.3.2  char_traits specializations
409   template<>
410     struct char_traits<wchar_t>
411     {
412       typedef wchar_t           char_type;
413       typedef wint_t            int_type;
414       typedef streamoff         off_type;
415       typedef wstreampos        pos_type;
416       typedef mbstate_t         state_type;
417 
418       static _GLIBCXX17_CONSTEXPR void
419       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
420       { __c1 = __c2; }
421 
422       static _GLIBCXX_CONSTEXPR bool
423       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
424       { return __c1 == __c2; }
425 
426       static _GLIBCXX_CONSTEXPR bool
427       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
428       { return __c1 < __c2; }
429 
430       static _GLIBCXX17_CONSTEXPR int
431       compare(const char_type* __s1, const char_type* __s2, size_t __n)
432       {
433 	if (__n == 0)
434 	  return 0;
435 #if __cplusplus >= 201703L
436 	if (__builtin_constant_p(__n)
437 	    && __constant_char_array_p(__s1, __n)
438 	    && __constant_char_array_p(__s2, __n))
439 	  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
440 #endif
441 	return wmemcmp(__s1, __s2, __n);
442       }
443 
444       static _GLIBCXX17_CONSTEXPR size_t
445       length(const char_type* __s)
446       {
447 #if __cplusplus >= 201703L
448 	if (__constant_string_p(__s))
449 	  return __gnu_cxx::char_traits<char_type>::length(__s);
450 #endif
451 	return wcslen(__s);
452       }
453 
454       static _GLIBCXX17_CONSTEXPR const char_type*
455       find(const char_type* __s, size_t __n, const char_type& __a)
456       {
457 	if (__n == 0)
458 	  return 0;
459 #if __cplusplus >= 201703L
460 	if (__builtin_constant_p(__n)
461 	    && __builtin_constant_p(__a)
462 	    && __constant_char_array_p(__s, __n))
463 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
464 #endif
465 	return wmemchr(__s, __a, __n);
466       }
467 
468       static char_type*
469       move(char_type* __s1, const char_type* __s2, size_t __n)
470       {
471 	if (__n == 0)
472 	  return __s1;
473 	return wmemmove(__s1, __s2, __n);
474       }
475 
476       static char_type*
477       copy(char_type* __s1, const char_type* __s2, size_t __n)
478       {
479 	if (__n == 0)
480 	  return __s1;
481 	return wmemcpy(__s1, __s2, __n);
482       }
483 
484       static char_type*
485       assign(char_type* __s, size_t __n, char_type __a)
486       {
487 	if (__n == 0)
488 	  return __s;
489 	return wmemset(__s, __a, __n);
490       }
491 
492       static _GLIBCXX_CONSTEXPR char_type
493       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
494       { return char_type(__c); }
495 
496       static _GLIBCXX_CONSTEXPR int_type
497       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
498       { return int_type(__c); }
499 
500       static _GLIBCXX_CONSTEXPR bool
501       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
502       { return __c1 == __c2; }
503 
504       static _GLIBCXX_CONSTEXPR int_type
505       eof() _GLIBCXX_NOEXCEPT
506       { return static_cast<int_type>(WEOF); }
507 
508       static _GLIBCXX_CONSTEXPR int_type
509       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
510       { return eq_int_type(__c, eof()) ? 0 : __c; }
511   };
512 #endif //_GLIBCXX_USE_WCHAR_T
513 
514 #ifdef _GLIBCXX_USE_CHAR8_T
515   template<>
516     struct char_traits<char8_t>
517     {
518       typedef char8_t           char_type;
519       typedef unsigned int      int_type;
520       typedef u8streampos       pos_type;
521       typedef streamoff         off_type;
522       typedef mbstate_t         state_type;
523 
524       static _GLIBCXX17_CONSTEXPR void
525       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
526       { __c1 = __c2; }
527 
528       static _GLIBCXX_CONSTEXPR bool
529       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
530       { return __c1 == __c2; }
531 
532       static _GLIBCXX_CONSTEXPR bool
533       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
534       { return __c1 < __c2; }
535 
536       static _GLIBCXX17_CONSTEXPR int
537       compare(const char_type* __s1, const char_type* __s2, size_t __n)
538       {
539 	if (__n == 0)
540 	  return 0;
541 #if __cplusplus > 201402
542 	if (__builtin_constant_p(__n)
543 	    && __constant_char_array_p(__s1, __n)
544 	    && __constant_char_array_p(__s2, __n))
545 	  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
546 #endif
547 	return __builtin_memcmp(__s1, __s2, __n);
548       }
549 
550       static _GLIBCXX17_CONSTEXPR size_t
551       length(const char_type* __s)
552       {
553 #if __cplusplus > 201402
554 	if (__constant_string_p(__s))
555 	  return __gnu_cxx::char_traits<char_type>::length(__s);
556 #endif
557 	size_t __i = 0;
558 	while (!eq(__s[__i], char_type()))
559 	  ++__i;
560 	return __i;
561       }
562 
563       static _GLIBCXX17_CONSTEXPR const char_type*
564       find(const char_type* __s, size_t __n, const char_type& __a)
565       {
566 	if (__n == 0)
567 	  return 0;
568 #if __cplusplus > 201402
569 	if (__builtin_constant_p(__n)
570 	    && __builtin_constant_p(__a)
571 	    && __constant_char_array_p(__s, __n))
572 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
573 #endif
574 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
575       }
576 
577       static char_type*
578       move(char_type* __s1, const char_type* __s2, size_t __n)
579       {
580 	if (__n == 0)
581 	  return __s1;
582 	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
583       }
584 
585       static char_type*
586       copy(char_type* __s1, const char_type* __s2, size_t __n)
587       {
588 	if (__n == 0)
589 	  return __s1;
590 	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
591       }
592 
593       static char_type*
594       assign(char_type* __s, size_t __n, char_type __a)
595       {
596 	if (__n == 0)
597 	  return __s;
598 	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
599       }
600 
601       static _GLIBCXX_CONSTEXPR char_type
602       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
603       { return char_type(__c); }
604 
605       static _GLIBCXX_CONSTEXPR int_type
606       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
607       { return int_type(__c); }
608 
609       static _GLIBCXX_CONSTEXPR bool
610       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
611       { return __c1 == __c2; }
612 
613       static _GLIBCXX_CONSTEXPR int_type
614       eof() _GLIBCXX_NOEXCEPT
615       { return static_cast<int_type>(-1); }
616 
617       static _GLIBCXX_CONSTEXPR int_type
618       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
619       { return eq_int_type(__c, eof()) ? 0 : __c; }
620     };
621 #endif //_GLIBCXX_USE_CHAR8_T
622 
623 _GLIBCXX_END_NAMESPACE_VERSION
624 } // namespace
625 
626 #if __cplusplus >= 201103L
627 
628 #include <cstdint>
629 
630 namespace std _GLIBCXX_VISIBILITY(default)
631 {
632 _GLIBCXX_BEGIN_NAMESPACE_VERSION
633 
634   template<>
635     struct char_traits<char16_t>
636     {
637       typedef char16_t          char_type;
638 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
639       typedef uint_least16_t    int_type;
640 #elif defined __UINT_LEAST16_TYPE__
641       typedef __UINT_LEAST16_TYPE__	    int_type;
642 #else
643       typedef make_unsigned<char16_t>::type int_type;
644 #endif
645       typedef streamoff         off_type;
646       typedef u16streampos      pos_type;
647       typedef mbstate_t         state_type;
648 
649       static _GLIBCXX17_CONSTEXPR void
650       assign(char_type& __c1, const char_type& __c2) noexcept
651       { __c1 = __c2; }
652 
653       static constexpr bool
654       eq(const char_type& __c1, const char_type& __c2) noexcept
655       { return __c1 == __c2; }
656 
657       static constexpr bool
658       lt(const char_type& __c1, const char_type& __c2) noexcept
659       { return __c1 < __c2; }
660 
661       static _GLIBCXX17_CONSTEXPR int
662       compare(const char_type* __s1, const char_type* __s2, size_t __n)
663       {
664 	for (size_t __i = 0; __i < __n; ++__i)
665 	  if (lt(__s1[__i], __s2[__i]))
666 	    return -1;
667 	  else if (lt(__s2[__i], __s1[__i]))
668 	    return 1;
669 	return 0;
670       }
671 
672       static _GLIBCXX17_CONSTEXPR size_t
673       length(const char_type* __s)
674       {
675 	size_t __i = 0;
676 	while (!eq(__s[__i], char_type()))
677 	  ++__i;
678 	return __i;
679       }
680 
681       static _GLIBCXX17_CONSTEXPR const char_type*
682       find(const char_type* __s, size_t __n, const char_type& __a)
683       {
684 	for (size_t __i = 0; __i < __n; ++__i)
685 	  if (eq(__s[__i], __a))
686 	    return __s + __i;
687 	return 0;
688       }
689 
690       static char_type*
691       move(char_type* __s1, const char_type* __s2, size_t __n)
692       {
693 	if (__n == 0)
694 	  return __s1;
695 	return (static_cast<char_type*>
696 		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
697       }
698 
699       static char_type*
700       copy(char_type* __s1, const char_type* __s2, size_t __n)
701       {
702 	if (__n == 0)
703 	  return __s1;
704 	return (static_cast<char_type*>
705 		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
706       }
707 
708       static char_type*
709       assign(char_type* __s, size_t __n, char_type __a)
710       {
711 	for (size_t __i = 0; __i < __n; ++__i)
712 	  assign(__s[__i], __a);
713 	return __s;
714       }
715 
716       static constexpr char_type
717       to_char_type(const int_type& __c) noexcept
718       { return char_type(__c); }
719 
720       static constexpr int_type
721       to_int_type(const char_type& __c) noexcept
722       { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
723 
724       static constexpr bool
725       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
726       { return __c1 == __c2; }
727 
728       static constexpr int_type
729       eof() noexcept
730       { return static_cast<int_type>(-1); }
731 
732       static constexpr int_type
733       not_eof(const int_type& __c) noexcept
734       { return eq_int_type(__c, eof()) ? 0 : __c; }
735     };
736 
737   template<>
738     struct char_traits<char32_t>
739     {
740       typedef char32_t          char_type;
741 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
742       typedef uint_least32_t    int_type;
743 #elif defined __UINT_LEAST32_TYPE__
744       typedef __UINT_LEAST32_TYPE__	    int_type;
745 #else
746       typedef make_unsigned<char32_t>::type int_type;
747 #endif
748       typedef streamoff         off_type;
749       typedef u32streampos      pos_type;
750       typedef mbstate_t         state_type;
751 
752       static _GLIBCXX17_CONSTEXPR void
753       assign(char_type& __c1, const char_type& __c2) noexcept
754       { __c1 = __c2; }
755 
756       static constexpr bool
757       eq(const char_type& __c1, const char_type& __c2) noexcept
758       { return __c1 == __c2; }
759 
760       static constexpr bool
761       lt(const char_type& __c1, const char_type& __c2) noexcept
762       { return __c1 < __c2; }
763 
764       static _GLIBCXX17_CONSTEXPR int
765       compare(const char_type* __s1, const char_type* __s2, size_t __n)
766       {
767 	for (size_t __i = 0; __i < __n; ++__i)
768 	  if (lt(__s1[__i], __s2[__i]))
769 	    return -1;
770 	  else if (lt(__s2[__i], __s1[__i]))
771 	    return 1;
772 	return 0;
773       }
774 
775       static _GLIBCXX17_CONSTEXPR size_t
776       length(const char_type* __s)
777       {
778 	size_t __i = 0;
779 	while (!eq(__s[__i], char_type()))
780 	  ++__i;
781 	return __i;
782       }
783 
784       static _GLIBCXX17_CONSTEXPR const char_type*
785       find(const char_type* __s, size_t __n, const char_type& __a)
786       {
787 	for (size_t __i = 0; __i < __n; ++__i)
788 	  if (eq(__s[__i], __a))
789 	    return __s + __i;
790 	return 0;
791       }
792 
793       static char_type*
794       move(char_type* __s1, const char_type* __s2, size_t __n)
795       {
796 	if (__n == 0)
797 	  return __s1;
798 	return (static_cast<char_type*>
799 		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
800       }
801 
802       static char_type*
803       copy(char_type* __s1, const char_type* __s2, size_t __n)
804       {
805 	if (__n == 0)
806 	  return __s1;
807 	return (static_cast<char_type*>
808 		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
809       }
810 
811       static char_type*
812       assign(char_type* __s, size_t __n, char_type __a)
813       {
814 	for (size_t __i = 0; __i < __n; ++__i)
815 	  assign(__s[__i], __a);
816 	return __s;
817       }
818 
819       static constexpr char_type
820       to_char_type(const int_type& __c) noexcept
821       { return char_type(__c); }
822 
823       static constexpr int_type
824       to_int_type(const char_type& __c) noexcept
825       { return int_type(__c); }
826 
827       static constexpr bool
828       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
829       { return __c1 == __c2; }
830 
831       static constexpr int_type
832       eof() noexcept
833       { return static_cast<int_type>(-1); }
834 
835       static constexpr int_type
836       not_eof(const int_type& __c) noexcept
837       { return eq_int_type(__c, eof()) ? 0 : __c; }
838     };
839 
840 _GLIBCXX_END_NAMESPACE_VERSION
841 } // namespace
842 
843 #endif  // C++11
844 
845 #endif // _CHAR_TRAITS_H
846