xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/bits/char_traits.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
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 
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 
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 	  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
324 #endif
325 	return __builtin_memcmp(__s1, __s2, __n);
326       }
327 
328       static _GLIBCXX17_CONSTEXPR size_t
329       length(const char_type* __s)
330       {
331 #if __cplusplus >= 201703L
332 	if (__constant_string_p(__s))
333 	  return __gnu_cxx::char_traits<char_type>::length(__s);
334 #endif
335 	return __builtin_strlen(__s);
336       }
337 
338       static _GLIBCXX17_CONSTEXPR const char_type*
339       find(const char_type* __s, size_t __n, const char_type& __a)
340       {
341 	if (__n == 0)
342 	  return 0;
343 #if __cplusplus >= 201703L
344 	if (__builtin_constant_p(__n)
345 	    && __builtin_constant_p(__a)
346 	    && __constant_char_array_p(__s, __n))
347 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
348 #endif
349 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
350       }
351 
352       static char_type*
353       move(char_type* __s1, const char_type* __s2, size_t __n)
354       {
355 	if (__n == 0)
356 	  return __s1;
357 	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
358       }
359 
360       static char_type*
361       copy(char_type* __s1, const char_type* __s2, size_t __n)
362       {
363 	if (__n == 0)
364 	  return __s1;
365 	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
366       }
367 
368       static char_type*
369       assign(char_type* __s, size_t __n, char_type __a)
370       {
371 	if (__n == 0)
372 	  return __s;
373 	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
374       }
375 
376       static _GLIBCXX_CONSTEXPR char_type
377       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
378       { return static_cast<char_type>(__c); }
379 
380       // To keep both the byte 0xff and the eof symbol 0xffffffff
381       // from ending up as 0xffffffff.
382       static _GLIBCXX_CONSTEXPR int_type
383       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
384       { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
385 
386       static _GLIBCXX_CONSTEXPR bool
387       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
388       { return __c1 == __c2; }
389 
390       static _GLIBCXX_CONSTEXPR int_type
391       eof() _GLIBCXX_NOEXCEPT
392       { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
393 
394       static _GLIBCXX_CONSTEXPR int_type
395       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
396       { return (__c == eof()) ? 0 : __c; }
397   };
398 
399 
400 #ifdef _GLIBCXX_USE_WCHAR_T
401   /// 21.1.3.2  char_traits specializations
402   template<>
403     struct char_traits<wchar_t>
404     {
405       typedef wchar_t           char_type;
406       typedef wint_t            int_type;
407       typedef streamoff         off_type;
408       typedef wstreampos        pos_type;
409       typedef mbstate_t         state_type;
410 
411       static _GLIBCXX17_CONSTEXPR void
412       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
413       { __c1 = __c2; }
414 
415       static _GLIBCXX_CONSTEXPR bool
416       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
417       { return __c1 == __c2; }
418 
419       static _GLIBCXX_CONSTEXPR bool
420       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
421       { return __c1 < __c2; }
422 
423       static _GLIBCXX17_CONSTEXPR int
424       compare(const char_type* __s1, const char_type* __s2, size_t __n)
425       {
426 	if (__n == 0)
427 	  return 0;
428 #if __cplusplus >= 201703L
429 	if (__builtin_constant_p(__n)
430 	    && __constant_char_array_p(__s1, __n)
431 	    && __constant_char_array_p(__s2, __n))
432 	  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
433 #endif
434 	return wmemcmp(__s1, __s2, __n);
435       }
436 
437       static _GLIBCXX17_CONSTEXPR size_t
438       length(const char_type* __s)
439       {
440 #if __cplusplus >= 201703L
441 	if (__constant_string_p(__s))
442 	  return __gnu_cxx::char_traits<char_type>::length(__s);
443 #endif
444 	return wcslen(__s);
445       }
446 
447       static _GLIBCXX17_CONSTEXPR const char_type*
448       find(const char_type* __s, size_t __n, const char_type& __a)
449       {
450 	if (__n == 0)
451 	  return 0;
452 #if __cplusplus >= 201703L
453 	if (__builtin_constant_p(__n)
454 	    && __builtin_constant_p(__a)
455 	    && __constant_char_array_p(__s, __n))
456 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
457 #endif
458 	return wmemchr(__s, __a, __n);
459       }
460 
461       static char_type*
462       move(char_type* __s1, const char_type* __s2, size_t __n)
463       {
464 	if (__n == 0)
465 	  return __s1;
466 	return wmemmove(__s1, __s2, __n);
467       }
468 
469       static char_type*
470       copy(char_type* __s1, const char_type* __s2, size_t __n)
471       {
472 	if (__n == 0)
473 	  return __s1;
474 	return wmemcpy(__s1, __s2, __n);
475       }
476 
477       static char_type*
478       assign(char_type* __s, size_t __n, char_type __a)
479       {
480 	if (__n == 0)
481 	  return __s;
482 	return wmemset(__s, __a, __n);
483       }
484 
485       static _GLIBCXX_CONSTEXPR char_type
486       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
487       { return char_type(__c); }
488 
489       static _GLIBCXX_CONSTEXPR int_type
490       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
491       { return int_type(__c); }
492 
493       static _GLIBCXX_CONSTEXPR bool
494       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
495       { return __c1 == __c2; }
496 
497       static _GLIBCXX_CONSTEXPR int_type
498       eof() _GLIBCXX_NOEXCEPT
499       { return static_cast<int_type>(WEOF); }
500 
501       static _GLIBCXX_CONSTEXPR int_type
502       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
503       { return eq_int_type(__c, eof()) ? 0 : __c; }
504   };
505 #endif //_GLIBCXX_USE_WCHAR_T
506 
507 #ifdef _GLIBCXX_USE_CHAR8_T
508   template<>
509     struct char_traits<char8_t>
510     {
511       typedef char8_t           char_type;
512       typedef unsigned int      int_type;
513       typedef u8streampos       pos_type;
514       typedef streamoff         off_type;
515       typedef mbstate_t         state_type;
516 
517       static _GLIBCXX17_CONSTEXPR void
518       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
519       { __c1 = __c2; }
520 
521       static _GLIBCXX_CONSTEXPR bool
522       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
523       { return __c1 == __c2; }
524 
525       static _GLIBCXX_CONSTEXPR bool
526       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
527       { return __c1 < __c2; }
528 
529       static _GLIBCXX17_CONSTEXPR int
530       compare(const char_type* __s1, const char_type* __s2, size_t __n)
531       {
532 	if (__n == 0)
533 	  return 0;
534 #if __cplusplus > 201402
535 	if (__builtin_constant_p(__n)
536 	    && __constant_char_array_p(__s1, __n)
537 	    && __constant_char_array_p(__s2, __n))
538 	  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
539 #endif
540 	return __builtin_memcmp(__s1, __s2, __n);
541       }
542 
543       static _GLIBCXX17_CONSTEXPR size_t
544       length(const char_type* __s)
545       {
546 #if __cplusplus > 201402
547 	if (__constant_string_p(__s))
548 	  return __gnu_cxx::char_traits<char_type>::length(__s);
549 #endif
550 	size_t __i = 0;
551 	while (!eq(__s[__i], char_type()))
552 	  ++__i;
553 	return __i;
554       }
555 
556       static _GLIBCXX17_CONSTEXPR const char_type*
557       find(const char_type* __s, size_t __n, const char_type& __a)
558       {
559 	if (__n == 0)
560 	  return 0;
561 #if __cplusplus > 201402
562 	if (__builtin_constant_p(__n)
563 	    && __builtin_constant_p(__a)
564 	    && __constant_char_array_p(__s, __n))
565 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
566 #endif
567 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
568       }
569 
570       static char_type*
571       move(char_type* __s1, const char_type* __s2, size_t __n)
572       {
573 	if (__n == 0)
574 	  return __s1;
575 	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
576       }
577 
578       static char_type*
579       copy(char_type* __s1, const char_type* __s2, size_t __n)
580       {
581 	if (__n == 0)
582 	  return __s1;
583 	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
584       }
585 
586       static char_type*
587       assign(char_type* __s, size_t __n, char_type __a)
588       {
589 	if (__n == 0)
590 	  return __s;
591 	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
592       }
593 
594       static _GLIBCXX_CONSTEXPR char_type
595       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
596       { return char_type(__c); }
597 
598       static _GLIBCXX_CONSTEXPR int_type
599       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
600       { return int_type(__c); }
601 
602       static _GLIBCXX_CONSTEXPR bool
603       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
604       { return __c1 == __c2; }
605 
606       static _GLIBCXX_CONSTEXPR int_type
607       eof() _GLIBCXX_NOEXCEPT
608       { return static_cast<int_type>(-1); }
609 
610       static _GLIBCXX_CONSTEXPR int_type
611       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
612       { return eq_int_type(__c, eof()) ? 0 : __c; }
613     };
614 #endif //_GLIBCXX_USE_CHAR8_T
615 
616 _GLIBCXX_END_NAMESPACE_VERSION
617 } // namespace
618 
619 #if __cplusplus >= 201103L
620 
621 #include <cstdint>
622 
623 namespace std _GLIBCXX_VISIBILITY(default)
624 {
625 _GLIBCXX_BEGIN_NAMESPACE_VERSION
626 
627   template<>
628     struct char_traits<char16_t>
629     {
630       typedef char16_t          char_type;
631 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
632       typedef uint_least16_t    int_type;
633 #elif defined __UINT_LEAST16_TYPE__
634       typedef __UINT_LEAST16_TYPE__	    int_type;
635 #else
636       typedef make_unsigned<char16_t>::type int_type;
637 #endif
638       typedef streamoff         off_type;
639       typedef u16streampos      pos_type;
640       typedef mbstate_t         state_type;
641 
642       static _GLIBCXX17_CONSTEXPR void
643       assign(char_type& __c1, const char_type& __c2) noexcept
644       { __c1 = __c2; }
645 
646       static constexpr bool
647       eq(const char_type& __c1, const char_type& __c2) noexcept
648       { return __c1 == __c2; }
649 
650       static constexpr bool
651       lt(const char_type& __c1, const char_type& __c2) noexcept
652       { return __c1 < __c2; }
653 
654       static _GLIBCXX17_CONSTEXPR int
655       compare(const char_type* __s1, const char_type* __s2, size_t __n)
656       {
657 	for (size_t __i = 0; __i < __n; ++__i)
658 	  if (lt(__s1[__i], __s2[__i]))
659 	    return -1;
660 	  else if (lt(__s2[__i], __s1[__i]))
661 	    return 1;
662 	return 0;
663       }
664 
665       static _GLIBCXX17_CONSTEXPR size_t
666       length(const char_type* __s)
667       {
668 	size_t __i = 0;
669 	while (!eq(__s[__i], char_type()))
670 	  ++__i;
671 	return __i;
672       }
673 
674       static _GLIBCXX17_CONSTEXPR const char_type*
675       find(const char_type* __s, size_t __n, const char_type& __a)
676       {
677 	for (size_t __i = 0; __i < __n; ++__i)
678 	  if (eq(__s[__i], __a))
679 	    return __s + __i;
680 	return 0;
681       }
682 
683       static char_type*
684       move(char_type* __s1, const char_type* __s2, size_t __n)
685       {
686 	if (__n == 0)
687 	  return __s1;
688 	return (static_cast<char_type*>
689 		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
690       }
691 
692       static char_type*
693       copy(char_type* __s1, const char_type* __s2, size_t __n)
694       {
695 	if (__n == 0)
696 	  return __s1;
697 	return (static_cast<char_type*>
698 		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
699       }
700 
701       static char_type*
702       assign(char_type* __s, size_t __n, char_type __a)
703       {
704 	for (size_t __i = 0; __i < __n; ++__i)
705 	  assign(__s[__i], __a);
706 	return __s;
707       }
708 
709       static constexpr char_type
710       to_char_type(const int_type& __c) noexcept
711       { return char_type(__c); }
712 
713       static constexpr int_type
714       to_int_type(const char_type& __c) noexcept
715       { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
716 
717       static constexpr bool
718       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
719       { return __c1 == __c2; }
720 
721       static constexpr int_type
722       eof() noexcept
723       { return static_cast<int_type>(-1); }
724 
725       static constexpr int_type
726       not_eof(const int_type& __c) noexcept
727       { return eq_int_type(__c, eof()) ? 0 : __c; }
728     };
729 
730   template<>
731     struct char_traits<char32_t>
732     {
733       typedef char32_t          char_type;
734 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
735       typedef uint_least32_t    int_type;
736 #elif defined __UINT_LEAST32_TYPE__
737       typedef __UINT_LEAST32_TYPE__	    int_type;
738 #else
739       typedef make_unsigned<char32_t>::type int_type;
740 #endif
741       typedef streamoff         off_type;
742       typedef u32streampos      pos_type;
743       typedef mbstate_t         state_type;
744 
745       static _GLIBCXX17_CONSTEXPR void
746       assign(char_type& __c1, const char_type& __c2) noexcept
747       { __c1 = __c2; }
748 
749       static constexpr bool
750       eq(const char_type& __c1, const char_type& __c2) noexcept
751       { return __c1 == __c2; }
752 
753       static constexpr bool
754       lt(const char_type& __c1, const char_type& __c2) noexcept
755       { return __c1 < __c2; }
756 
757       static _GLIBCXX17_CONSTEXPR int
758       compare(const char_type* __s1, const char_type* __s2, size_t __n)
759       {
760 	for (size_t __i = 0; __i < __n; ++__i)
761 	  if (lt(__s1[__i], __s2[__i]))
762 	    return -1;
763 	  else if (lt(__s2[__i], __s1[__i]))
764 	    return 1;
765 	return 0;
766       }
767 
768       static _GLIBCXX17_CONSTEXPR size_t
769       length(const char_type* __s)
770       {
771 	size_t __i = 0;
772 	while (!eq(__s[__i], char_type()))
773 	  ++__i;
774 	return __i;
775       }
776 
777       static _GLIBCXX17_CONSTEXPR const char_type*
778       find(const char_type* __s, size_t __n, const char_type& __a)
779       {
780 	for (size_t __i = 0; __i < __n; ++__i)
781 	  if (eq(__s[__i], __a))
782 	    return __s + __i;
783 	return 0;
784       }
785 
786       static char_type*
787       move(char_type* __s1, const char_type* __s2, size_t __n)
788       {
789 	if (__n == 0)
790 	  return __s1;
791 	return (static_cast<char_type*>
792 		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
793       }
794 
795       static char_type*
796       copy(char_type* __s1, const char_type* __s2, size_t __n)
797       {
798 	if (__n == 0)
799 	  return __s1;
800 	return (static_cast<char_type*>
801 		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
802       }
803 
804       static char_type*
805       assign(char_type* __s, size_t __n, char_type __a)
806       {
807 	for (size_t __i = 0; __i < __n; ++__i)
808 	  assign(__s[__i], __a);
809 	return __s;
810       }
811 
812       static constexpr char_type
813       to_char_type(const int_type& __c) noexcept
814       { return char_type(__c); }
815 
816       static constexpr int_type
817       to_int_type(const char_type& __c) noexcept
818       { return int_type(__c); }
819 
820       static constexpr bool
821       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
822       { return __c1 == __c2; }
823 
824       static constexpr int_type
825       eof() noexcept
826       { return static_cast<int_type>(-1); }
827 
828       static constexpr int_type
829       not_eof(const int_type& __c) noexcept
830       { return eq_int_type(__c, eof()) ? 0 : __c; }
831     };
832 
833 _GLIBCXX_END_NAMESPACE_VERSION
834 } // namespace
835 
836 #endif  // C++11
837 
838 #endif // _CHAR_TRAITS_H
839