1 // Character Traits for use by standard string and iostream -*- C++ -*-
2 
3 // Copyright (C) 1997-2018 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 #define __cpp_lib_constexpr_char_traits 201611
147 
148   template<typename _CharT>
149     _GLIBCXX14_CONSTEXPR int
150     char_traits<_CharT>::
151     compare(const char_type* __s1, const char_type* __s2, std::size_t __n)
152     {
153       for (std::size_t __i = 0; __i < __n; ++__i)
154 	if (lt(__s1[__i], __s2[__i]))
155 	  return -1;
156 	else if (lt(__s2[__i], __s1[__i]))
157 	  return 1;
158       return 0;
159     }
160 
161   template<typename _CharT>
162     _GLIBCXX14_CONSTEXPR std::size_t
163     char_traits<_CharT>::
164     length(const char_type* __p)
165     {
166       std::size_t __i = 0;
167       while (!eq(__p[__i], char_type()))
168         ++__i;
169       return __i;
170     }
171 
172   template<typename _CharT>
173     _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type*
174     char_traits<_CharT>::
175     find(const char_type* __s, std::size_t __n, const char_type& __a)
176     {
177       for (std::size_t __i = 0; __i < __n; ++__i)
178         if (eq(__s[__i], __a))
179           return __s + __i;
180       return 0;
181     }
182 
183   template<typename _CharT>
184     typename char_traits<_CharT>::char_type*
185     char_traits<_CharT>::
186     move(char_type* __s1, const char_type* __s2, std::size_t __n)
187     {
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 > 201402
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 __c == eof() ? int_type(0xfffd) : 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