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
47namespace __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
215namespace 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
630namespace 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