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 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
623namespace 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