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