1 | // Character Traits for use by standard string and iostream -*- C++ -*- |
2 | |
3 | // Copyright (C) 1997-2019 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file bits/char_traits.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{string} |
28 | */ |
29 | |
30 | // |
31 | // ISO C++ 14882: 21 Strings library |
32 | // |
33 | |
34 | #ifndef _CHAR_TRAITS_H |
35 | #define _CHAR_TRAITS_H 1 |
36 | |
37 | #pragma GCC system_header |
38 | |
39 | #include <bits/stl_algobase.h> // std::copy, std::fill_n |
40 | #include <bits/postypes.h> // For streampos |
41 | #include <cwchar> // For WEOF, wmemmove, wmemset, etc. |
42 | |
43 | #ifndef _GLIBCXX_ALWAYS_INLINE |
44 | # define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) |
45 | #endif |
46 | |
47 | namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) |
48 | { |
49 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
50 | |
51 | /** |
52 | * @brief Mapping from character type to associated types. |
53 | * |
54 | * @note This is an implementation class for the generic version |
55 | * of char_traits. It defines int_type, off_type, pos_type, and |
56 | * state_type. By default these are unsigned long, streamoff, |
57 | * streampos, and mbstate_t. Users who need a different set of |
58 | * types, but who don't need to change the definitions of any function |
59 | * defined in char_traits, can specialize __gnu_cxx::_Char_types |
60 | * while leaving __gnu_cxx::char_traits alone. */ |
61 | template<typename _CharT> |
62 | struct _Char_types |
63 | { |
64 | typedef unsigned long int_type; |
65 | typedef std::streampos pos_type; |
66 | typedef std::streamoff off_type; |
67 | typedef std::mbstate_t state_type; |
68 | }; |
69 | |
70 | |
71 | /** |
72 | * @brief Base class used to implement std::char_traits. |
73 | * |
74 | * @note For any given actual character type, this definition is |
75 | * probably wrong. (Most of the member functions are likely to be |
76 | * right, but the int_type and state_type typedefs, and the eof() |
77 | * member function, are likely to be wrong.) The reason this class |
78 | * exists is so users can specialize it. Classes in namespace std |
79 | * may not be specialized for fundamental types, but classes in |
80 | * namespace __gnu_cxx may be. |
81 | * |
82 | * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types |
83 | * for advice on how to make use of this class for @a unusual character |
84 | * types. Also, check out include/ext/pod_char_traits.h. |
85 | */ |
86 | template<typename _CharT> |
87 | struct char_traits |
88 | { |
89 | typedef _CharT char_type; |
90 | typedef typename _Char_types<_CharT>::int_type int_type; |
91 | typedef typename _Char_types<_CharT>::pos_type pos_type; |
92 | typedef typename _Char_types<_CharT>::off_type off_type; |
93 | typedef typename _Char_types<_CharT>::state_type state_type; |
94 | |
95 | static _GLIBCXX14_CONSTEXPR void |
96 | assign(char_type& __c1, const char_type& __c2) |
97 | { __c1 = __c2; } |
98 | |
99 | static _GLIBCXX_CONSTEXPR bool |
100 | eq(const char_type& __c1, const char_type& __c2) |
101 | { return __c1 == __c2; } |
102 | |
103 | static _GLIBCXX_CONSTEXPR bool |
104 | lt(const char_type& __c1, const char_type& __c2) |
105 | { return __c1 < __c2; } |
106 | |
107 | static _GLIBCXX14_CONSTEXPR int |
108 | compare(const char_type* __s1, const char_type* __s2, std::size_t __n); |
109 | |
110 | static _GLIBCXX14_CONSTEXPR std::size_t |
111 | length(const char_type* __s); |
112 | |
113 | static _GLIBCXX14_CONSTEXPR const char_type* |
114 | find(const char_type* __s, std::size_t __n, const char_type& __a); |
115 | |
116 | static char_type* |
117 | move(char_type* __s1, const char_type* __s2, std::size_t __n); |
118 | |
119 | static char_type* |
120 | copy(char_type* __s1, const char_type* __s2, std::size_t __n); |
121 | |
122 | static char_type* |
123 | assign(char_type* __s, std::size_t __n, char_type __a); |
124 | |
125 | static _GLIBCXX_CONSTEXPR char_type |
126 | to_char_type(const int_type& __c) |
127 | { return static_cast<char_type>(__c); } |
128 | |
129 | static _GLIBCXX_CONSTEXPR int_type |
130 | to_int_type(const char_type& __c) |
131 | { return static_cast<int_type>(__c); } |
132 | |
133 | static _GLIBCXX_CONSTEXPR bool |
134 | eq_int_type(const int_type& __c1, const int_type& __c2) |
135 | { return __c1 == __c2; } |
136 | |
137 | static _GLIBCXX_CONSTEXPR int_type |
138 | eof() |
139 | { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); } |
140 | |
141 | static _GLIBCXX_CONSTEXPR int_type |
142 | not_eof(const int_type& __c) |
143 | { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } |
144 | }; |
145 | |
146 | template<typename _CharT> |
147 | _GLIBCXX14_CONSTEXPR int |
148 | char_traits<_CharT>:: |
149 | compare(const char_type* __s1, const char_type* __s2, std::size_t __n) |
150 | { |
151 | for (std::size_t __i = 0; __i < __n; ++__i) |
152 | if (lt(__s1[__i], __s2[__i])) |
153 | return -1; |
154 | else if (lt(__s2[__i], __s1[__i])) |
155 | return 1; |
156 | return 0; |
157 | } |
158 | |
159 | template<typename _CharT> |
160 | _GLIBCXX14_CONSTEXPR std::size_t |
161 | char_traits<_CharT>:: |
162 | length(const char_type* __p) |
163 | { |
164 | std::size_t __i = 0; |
165 | while (!eq(__p[__i], char_type())) |
166 | ++__i; |
167 | return __i; |
168 | } |
169 | |
170 | template<typename _CharT> |
171 | _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type* |
172 | char_traits<_CharT>:: |
173 | find(const char_type* __s, std::size_t __n, const char_type& __a) |
174 | { |
175 | for (std::size_t __i = 0; __i < __n; ++__i) |
176 | if (eq(__s[__i], __a)) |
177 | return __s + __i; |
178 | return 0; |
179 | } |
180 | |
181 | template<typename _CharT> |
182 | typename char_traits<_CharT>::char_type* |
183 | char_traits<_CharT>:: |
184 | move(char_type* __s1, const char_type* __s2, std::size_t __n) |
185 | { |
186 | if (__n == 0) |
187 | return __s1; |
188 | return static_cast<_CharT*>(__builtin_memmove(__s1, __s2, |
189 | __n * sizeof(char_type))); |
190 | } |
191 | |
192 | template<typename _CharT> |
193 | typename char_traits<_CharT>::char_type* |
194 | char_traits<_CharT>:: |
195 | copy(char_type* __s1, const char_type* __s2, std::size_t __n) |
196 | { |
197 | // NB: Inline std::copy so no recursive dependencies. |
198 | std::copy(__s2, __s2 + __n, __s1); |
199 | return __s1; |
200 | } |
201 | |
202 | template<typename _CharT> |
203 | typename char_traits<_CharT>::char_type* |
204 | char_traits<_CharT>:: |
205 | assign(char_type* __s, std::size_t __n, char_type __a) |
206 | { |
207 | // NB: Inline std::fill_n so no recursive dependencies. |
208 | std::fill_n(__s, __n, __a); |
209 | return __s; |
210 | } |
211 | |
212 | _GLIBCXX_END_NAMESPACE_VERSION |
213 | } // namespace |
214 | |
215 | namespace std _GLIBCXX_VISIBILITY(default) |
216 | { |
217 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
218 | |
219 | #if __cplusplus >= 201703L |
220 | #define __cpp_lib_constexpr_char_traits 201611 |
221 | |
222 | /** |
223 | * @brief Determine whether the characters of a NULL-terminated |
224 | * string are known at compile time. |
225 | * @param __s The string. |
226 | * |
227 | * Assumes that _CharT is a built-in character type. |
228 | */ |
229 | template<typename _CharT> |
230 | static _GLIBCXX_ALWAYS_INLINE constexpr bool |
231 | __constant_string_p(const _CharT* __s) |
232 | { |
233 | #ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED |
234 | (void) __s; |
235 | // In constexpr contexts all strings should be constant. |
236 | return __builtin_is_constant_evaluated(); |
237 | #else |
238 | while (__builtin_constant_p(*__s) && *__s) |
239 | __s++; |
240 | return __builtin_constant_p(*__s); |
241 | #endif |
242 | } |
243 | |
244 | /** |
245 | * @brief Determine whether the characters of a character array are |
246 | * known at compile time. |
247 | * @param __a The character array. |
248 | * @param __n Number of characters. |
249 | * |
250 | * Assumes that _CharT is a built-in character type. |
251 | */ |
252 | template<typename _CharT> |
253 | static _GLIBCXX_ALWAYS_INLINE constexpr bool |
254 | __constant_char_array_p(const _CharT* __a, size_t __n) |
255 | { |
256 | #ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED |
257 | (void) __a; |
258 | (void) __n; |
259 | // In constexpr contexts all character arrays should be constant. |
260 | return __builtin_is_constant_evaluated(); |
261 | #else |
262 | size_t __i = 0; |
263 | while (__i < __n && __builtin_constant_p(__a[__i])) |
264 | __i++; |
265 | return __i == __n; |
266 | #endif |
267 | } |
268 | #endif |
269 | |
270 | // 21.1 |
271 | /** |
272 | * @brief Basis for explicit traits specializations. |
273 | * |
274 | * @note For any given actual character type, this definition is |
275 | * probably wrong. Since this is just a thin wrapper around |
276 | * __gnu_cxx::char_traits, it is possible to achieve a more |
277 | * appropriate definition by specializing __gnu_cxx::char_traits. |
278 | * |
279 | * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types |
280 | * for advice on how to make use of this class for @a unusual character |
281 | * types. Also, check out include/ext/pod_char_traits.h. |
282 | */ |
283 | template<class _CharT> |
284 | struct char_traits : public __gnu_cxx::char_traits<_CharT> |
285 | { }; |
286 | |
287 | |
288 | /// 21.1.3.1 char_traits specializations |
289 | template<> |
290 | struct char_traits<char> |
291 | { |
292 | typedef char char_type; |
293 | typedef int int_type; |
294 | typedef streampos pos_type; |
295 | typedef streamoff off_type; |
296 | typedef mbstate_t state_type; |
297 | |
298 | static _GLIBCXX17_CONSTEXPR void |
299 | assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
300 | { __c1 = __c2; } |
301 | |
302 | static _GLIBCXX_CONSTEXPR bool |
303 | eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
304 | { return __c1 == __c2; } |
305 | |
306 | static _GLIBCXX_CONSTEXPR bool |
307 | lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
308 | { |
309 | // LWG 467. |
310 | return (static_cast<unsigned char>(__c1) |
311 | < static_cast<unsigned char>(__c2)); |
312 | } |
313 | |
314 | static _GLIBCXX17_CONSTEXPR int |
315 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
316 | { |
317 | if (__n == 0) |
318 | return 0; |
319 | #if __cplusplus >= 201703L |
320 | if (__builtin_constant_p(__n) |
321 | && __constant_char_array_p(__s1, __n) |
322 | && __constant_char_array_p(__s2, __n)) |
323 | return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); |
324 | #endif |
325 | return __builtin_memcmp(__s1, __s2, __n); |
326 | } |
327 | |
328 | static _GLIBCXX17_CONSTEXPR size_t |
329 | length(const char_type* __s) |
330 | { |
331 | #if __cplusplus >= 201703L |
332 | if (__constant_string_p(__s)) |
333 | return __gnu_cxx::char_traits<char_type>::length(__s); |
334 | #endif |
335 | return __builtin_strlen(__s); |
336 | } |
337 | |
338 | static _GLIBCXX17_CONSTEXPR const char_type* |
339 | find(const char_type* __s, size_t __n, const char_type& __a) |
340 | { |
341 | if (__n == 0) |
342 | return 0; |
343 | #if __cplusplus >= 201703L |
344 | if (__builtin_constant_p(__n) |
345 | && __builtin_constant_p(__a) |
346 | && __constant_char_array_p(__s, __n)) |
347 | return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); |
348 | #endif |
349 | return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); |
350 | } |
351 | |
352 | static char_type* |
353 | move(char_type* __s1, const char_type* __s2, size_t __n) |
354 | { |
355 | if (__n == 0) |
356 | return __s1; |
357 | return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); |
358 | } |
359 | |
360 | static char_type* |
361 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
362 | { |
363 | if (__n == 0) |
364 | return __s1; |
365 | return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); |
366 | } |
367 | |
368 | static char_type* |
369 | assign(char_type* __s, size_t __n, char_type __a) |
370 | { |
371 | if (__n == 0) |
372 | return __s; |
373 | return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); |
374 | } |
375 | |
376 | static _GLIBCXX_CONSTEXPR char_type |
377 | to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT |
378 | { return static_cast<char_type>(__c); } |
379 | |
380 | // To keep both the byte 0xff and the eof symbol 0xffffffff |
381 | // from ending up as 0xffffffff. |
382 | static _GLIBCXX_CONSTEXPR int_type |
383 | to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT |
384 | { return static_cast<int_type>(static_cast<unsigned char>(__c)); } |
385 | |
386 | static _GLIBCXX_CONSTEXPR bool |
387 | eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT |
388 | { return __c1 == __c2; } |
389 | |
390 | static _GLIBCXX_CONSTEXPR int_type |
391 | eof() _GLIBCXX_NOEXCEPT |
392 | { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); } |
393 | |
394 | static _GLIBCXX_CONSTEXPR int_type |
395 | not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT |
396 | { return (__c == eof()) ? 0 : __c; } |
397 | }; |
398 | |
399 | |
400 | #ifdef _GLIBCXX_USE_WCHAR_T |
401 | /// 21.1.3.2 char_traits specializations |
402 | template<> |
403 | struct char_traits<wchar_t> |
404 | { |
405 | typedef wchar_t char_type; |
406 | typedef wint_t int_type; |
407 | typedef streamoff off_type; |
408 | typedef wstreampos pos_type; |
409 | typedef mbstate_t state_type; |
410 | |
411 | static _GLIBCXX17_CONSTEXPR void |
412 | assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
413 | { __c1 = __c2; } |
414 | |
415 | static _GLIBCXX_CONSTEXPR bool |
416 | eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
417 | { return __c1 == __c2; } |
418 | |
419 | static _GLIBCXX_CONSTEXPR bool |
420 | lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
421 | { return __c1 < __c2; } |
422 | |
423 | static _GLIBCXX17_CONSTEXPR int |
424 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
425 | { |
426 | if (__n == 0) |
427 | return 0; |
428 | #if __cplusplus >= 201703L |
429 | if (__builtin_constant_p(__n) |
430 | && __constant_char_array_p(__s1, __n) |
431 | && __constant_char_array_p(__s2, __n)) |
432 | return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); |
433 | #endif |
434 | return wmemcmp(__s1, __s2, __n); |
435 | } |
436 | |
437 | static _GLIBCXX17_CONSTEXPR size_t |
438 | length(const char_type* __s) |
439 | { |
440 | #if __cplusplus >= 201703L |
441 | if (__constant_string_p(__s)) |
442 | return __gnu_cxx::char_traits<char_type>::length(__s); |
443 | #endif |
444 | return wcslen(__s); |
445 | } |
446 | |
447 | static _GLIBCXX17_CONSTEXPR const char_type* |
448 | find(const char_type* __s, size_t __n, const char_type& __a) |
449 | { |
450 | if (__n == 0) |
451 | return 0; |
452 | #if __cplusplus >= 201703L |
453 | if (__builtin_constant_p(__n) |
454 | && __builtin_constant_p(__a) |
455 | && __constant_char_array_p(__s, __n)) |
456 | return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); |
457 | #endif |
458 | return wmemchr(__s, __a, __n); |
459 | } |
460 | |
461 | static char_type* |
462 | move(char_type* __s1, const char_type* __s2, size_t __n) |
463 | { |
464 | if (__n == 0) |
465 | return __s1; |
466 | return wmemmove(__s1, __s2, __n); |
467 | } |
468 | |
469 | static char_type* |
470 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
471 | { |
472 | if (__n == 0) |
473 | return __s1; |
474 | return wmemcpy(__s1, __s2, __n); |
475 | } |
476 | |
477 | static char_type* |
478 | assign(char_type* __s, size_t __n, char_type __a) |
479 | { |
480 | if (__n == 0) |
481 | return __s; |
482 | return wmemset(__s, __a, __n); |
483 | } |
484 | |
485 | static _GLIBCXX_CONSTEXPR char_type |
486 | to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT |
487 | { return char_type(__c); } |
488 | |
489 | static _GLIBCXX_CONSTEXPR int_type |
490 | to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT |
491 | { return int_type(__c); } |
492 | |
493 | static _GLIBCXX_CONSTEXPR bool |
494 | eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT |
495 | { return __c1 == __c2; } |
496 | |
497 | static _GLIBCXX_CONSTEXPR int_type |
498 | eof() _GLIBCXX_NOEXCEPT |
499 | { return static_cast<int_type>(WEOF); } |
500 | |
501 | static _GLIBCXX_CONSTEXPR int_type |
502 | not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT |
503 | { return eq_int_type(__c, eof()) ? 0 : __c; } |
504 | }; |
505 | #endif //_GLIBCXX_USE_WCHAR_T |
506 | |
507 | #ifdef _GLIBCXX_USE_CHAR8_T |
508 | template<> |
509 | struct char_traits<char8_t> |
510 | { |
511 | typedef char8_t char_type; |
512 | typedef unsigned int int_type; |
513 | typedef u8streampos pos_type; |
514 | typedef streamoff off_type; |
515 | typedef mbstate_t state_type; |
516 | |
517 | static _GLIBCXX17_CONSTEXPR void |
518 | assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
519 | { __c1 = __c2; } |
520 | |
521 | static _GLIBCXX_CONSTEXPR bool |
522 | eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
523 | { return __c1 == __c2; } |
524 | |
525 | static _GLIBCXX_CONSTEXPR bool |
526 | lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
527 | { return __c1 < __c2; } |
528 | |
529 | static _GLIBCXX17_CONSTEXPR int |
530 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
531 | { |
532 | if (__n == 0) |
533 | return 0; |
534 | #if __cplusplus > 201402 |
535 | if (__builtin_constant_p(__n) |
536 | && __constant_char_array_p(__s1, __n) |
537 | && __constant_char_array_p(__s2, __n)) |
538 | return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n); |
539 | #endif |
540 | return __builtin_memcmp(__s1, __s2, __n); |
541 | } |
542 | |
543 | static _GLIBCXX17_CONSTEXPR size_t |
544 | length(const char_type* __s) |
545 | { |
546 | #if __cplusplus > 201402 |
547 | if (__constant_string_p(__s)) |
548 | return __gnu_cxx::char_traits<char_type>::length(__s); |
549 | #endif |
550 | size_t __i = 0; |
551 | while (!eq(__s[__i], char_type())) |
552 | ++__i; |
553 | return __i; |
554 | } |
555 | |
556 | static _GLIBCXX17_CONSTEXPR const char_type* |
557 | find(const char_type* __s, size_t __n, const char_type& __a) |
558 | { |
559 | if (__n == 0) |
560 | return 0; |
561 | #if __cplusplus > 201402 |
562 | if (__builtin_constant_p(__n) |
563 | && __builtin_constant_p(__a) |
564 | && __constant_char_array_p(__s, __n)) |
565 | return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a); |
566 | #endif |
567 | return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); |
568 | } |
569 | |
570 | static char_type* |
571 | move(char_type* __s1, const char_type* __s2, size_t __n) |
572 | { |
573 | if (__n == 0) |
574 | return __s1; |
575 | return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); |
576 | } |
577 | |
578 | static char_type* |
579 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
580 | { |
581 | if (__n == 0) |
582 | return __s1; |
583 | return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); |
584 | } |
585 | |
586 | static char_type* |
587 | assign(char_type* __s, size_t __n, char_type __a) |
588 | { |
589 | if (__n == 0) |
590 | return __s; |
591 | return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); |
592 | } |
593 | |
594 | static _GLIBCXX_CONSTEXPR char_type |
595 | to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT |
596 | { return char_type(__c); } |
597 | |
598 | static _GLIBCXX_CONSTEXPR int_type |
599 | to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT |
600 | { return int_type(__c); } |
601 | |
602 | static _GLIBCXX_CONSTEXPR bool |
603 | eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT |
604 | { return __c1 == __c2; } |
605 | |
606 | static _GLIBCXX_CONSTEXPR int_type |
607 | eof() _GLIBCXX_NOEXCEPT |
608 | { return static_cast<int_type>(-1); } |
609 | |
610 | static _GLIBCXX_CONSTEXPR int_type |
611 | not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT |
612 | { return eq_int_type(__c, eof()) ? 0 : __c; } |
613 | }; |
614 | #endif //_GLIBCXX_USE_CHAR8_T |
615 | |
616 | _GLIBCXX_END_NAMESPACE_VERSION |
617 | } // namespace |
618 | |
619 | #if __cplusplus >= 201103L |
620 | |
621 | #include <cstdint> |
622 | |
623 | namespace std _GLIBCXX_VISIBILITY(default) |
624 | { |
625 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
626 | |
627 | template<> |
628 | struct char_traits<char16_t> |
629 | { |
630 | typedef char16_t char_type; |
631 | #ifdef _GLIBCXX_USE_C99_STDINT_TR1 |
632 | typedef uint_least16_t int_type; |
633 | #elif defined __UINT_LEAST16_TYPE__ |
634 | typedef __UINT_LEAST16_TYPE__ int_type; |
635 | #else |
636 | typedef make_unsigned<char16_t>::type int_type; |
637 | #endif |
638 | typedef streamoff off_type; |
639 | typedef u16streampos pos_type; |
640 | typedef mbstate_t state_type; |
641 | |
642 | static _GLIBCXX17_CONSTEXPR void |
643 | assign(char_type& __c1, const char_type& __c2) noexcept |
644 | { __c1 = __c2; } |
645 | |
646 | static constexpr bool |
647 | eq(const char_type& __c1, const char_type& __c2) noexcept |
648 | { return __c1 == __c2; } |
649 | |
650 | static constexpr bool |
651 | lt(const char_type& __c1, const char_type& __c2) noexcept |
652 | { return __c1 < __c2; } |
653 | |
654 | static _GLIBCXX17_CONSTEXPR int |
655 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
656 | { |
657 | for (size_t __i = 0; __i < __n; ++__i) |
658 | if (lt(__s1[__i], __s2[__i])) |
659 | return -1; |
660 | else if (lt(__s2[__i], __s1[__i])) |
661 | return 1; |
662 | return 0; |
663 | } |
664 | |
665 | static _GLIBCXX17_CONSTEXPR size_t |
666 | length(const char_type* __s) |
667 | { |
668 | size_t __i = 0; |
669 | while (!eq(__s[__i], char_type())) |
670 | ++__i; |
671 | return __i; |
672 | } |
673 | |
674 | static _GLIBCXX17_CONSTEXPR const char_type* |
675 | find(const char_type* __s, size_t __n, const char_type& __a) |
676 | { |
677 | for (size_t __i = 0; __i < __n; ++__i) |
678 | if (eq(__s[__i], __a)) |
679 | return __s + __i; |
680 | return 0; |
681 | } |
682 | |
683 | static char_type* |
684 | move(char_type* __s1, const char_type* __s2, size_t __n) |
685 | { |
686 | if (__n == 0) |
687 | return __s1; |
688 | return (static_cast<char_type*> |
689 | (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); |
690 | } |
691 | |
692 | static char_type* |
693 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
694 | { |
695 | if (__n == 0) |
696 | return __s1; |
697 | return (static_cast<char_type*> |
698 | (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); |
699 | } |
700 | |
701 | static char_type* |
702 | assign(char_type* __s, size_t __n, char_type __a) |
703 | { |
704 | for (size_t __i = 0; __i < __n; ++__i) |
705 | assign(__s[__i], __a); |
706 | return __s; |
707 | } |
708 | |
709 | static constexpr char_type |
710 | to_char_type(const int_type& __c) noexcept |
711 | { return char_type(__c); } |
712 | |
713 | static constexpr int_type |
714 | to_int_type(const char_type& __c) noexcept |
715 | { return __c == eof() ? int_type(0xfffd) : int_type(__c); } |
716 | |
717 | static constexpr bool |
718 | eq_int_type(const int_type& __c1, const int_type& __c2) noexcept |
719 | { return __c1 == __c2; } |
720 | |
721 | static constexpr int_type |
722 | eof() noexcept |
723 | { return static_cast<int_type>(-1); } |
724 | |
725 | static constexpr int_type |
726 | not_eof(const int_type& __c) noexcept |
727 | { return eq_int_type(__c, eof()) ? 0 : __c; } |
728 | }; |
729 | |
730 | template<> |
731 | struct char_traits<char32_t> |
732 | { |
733 | typedef char32_t char_type; |
734 | #ifdef _GLIBCXX_USE_C99_STDINT_TR1 |
735 | typedef uint_least32_t int_type; |
736 | #elif defined __UINT_LEAST32_TYPE__ |
737 | typedef __UINT_LEAST32_TYPE__ int_type; |
738 | #else |
739 | typedef make_unsigned<char32_t>::type int_type; |
740 | #endif |
741 | typedef streamoff off_type; |
742 | typedef u32streampos pos_type; |
743 | typedef mbstate_t state_type; |
744 | |
745 | static _GLIBCXX17_CONSTEXPR void |
746 | assign(char_type& __c1, const char_type& __c2) noexcept |
747 | { __c1 = __c2; } |
748 | |
749 | static constexpr bool |
750 | eq(const char_type& __c1, const char_type& __c2) noexcept |
751 | { return __c1 == __c2; } |
752 | |
753 | static constexpr bool |
754 | lt(const char_type& __c1, const char_type& __c2) noexcept |
755 | { return __c1 < __c2; } |
756 | |
757 | static _GLIBCXX17_CONSTEXPR int |
758 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
759 | { |
760 | for (size_t __i = 0; __i < __n; ++__i) |
761 | if (lt(__s1[__i], __s2[__i])) |
762 | return -1; |
763 | else if (lt(__s2[__i], __s1[__i])) |
764 | return 1; |
765 | return 0; |
766 | } |
767 | |
768 | static _GLIBCXX17_CONSTEXPR size_t |
769 | length(const char_type* __s) |
770 | { |
771 | size_t __i = 0; |
772 | while (!eq(__s[__i], char_type())) |
773 | ++__i; |
774 | return __i; |
775 | } |
776 | |
777 | static _GLIBCXX17_CONSTEXPR const char_type* |
778 | find(const char_type* __s, size_t __n, const char_type& __a) |
779 | { |
780 | for (size_t __i = 0; __i < __n; ++__i) |
781 | if (eq(__s[__i], __a)) |
782 | return __s + __i; |
783 | return 0; |
784 | } |
785 | |
786 | static char_type* |
787 | move(char_type* __s1, const char_type* __s2, size_t __n) |
788 | { |
789 | if (__n == 0) |
790 | return __s1; |
791 | return (static_cast<char_type*> |
792 | (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); |
793 | } |
794 | |
795 | static char_type* |
796 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
797 | { |
798 | if (__n == 0) |
799 | return __s1; |
800 | return (static_cast<char_type*> |
801 | (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); |
802 | } |
803 | |
804 | static char_type* |
805 | assign(char_type* __s, size_t __n, char_type __a) |
806 | { |
807 | for (size_t __i = 0; __i < __n; ++__i) |
808 | assign(__s[__i], __a); |
809 | return __s; |
810 | } |
811 | |
812 | static constexpr char_type |
813 | to_char_type(const int_type& __c) noexcept |
814 | { return char_type(__c); } |
815 | |
816 | static constexpr int_type |
817 | to_int_type(const char_type& __c) noexcept |
818 | { return int_type(__c); } |
819 | |
820 | static constexpr bool |
821 | eq_int_type(const int_type& __c1, const int_type& __c2) noexcept |
822 | { return __c1 == __c2; } |
823 | |
824 | static constexpr int_type |
825 | eof() noexcept |
826 | { return static_cast<int_type>(-1); } |
827 | |
828 | static constexpr int_type |
829 | not_eof(const int_type& __c) noexcept |
830 | { return eq_int_type(__c, eof()) ? 0 : __c; } |
831 | }; |
832 | |
833 | _GLIBCXX_END_NAMESPACE_VERSION |
834 | } // namespace |
835 | |
836 | #endif // C++11 |
837 | |
838 | #endif // _CHAR_TRAITS_H |
839 | |