1 | // Character Traits for use by standard string and iostream -*- C++ -*- |
2 | |
3 | // Copyright (C) 1997-2014 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 | namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) |
44 | { |
45 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
46 | |
47 | /** |
48 | * @brief Mapping from character type to associated types. |
49 | * |
50 | * @note This is an implementation class for the generic version |
51 | * of char_traits. It defines int_type, off_type, pos_type, and |
52 | * state_type. By default these are unsigned long, streamoff, |
53 | * streampos, and mbstate_t. Users who need a different set of |
54 | * types, but who don't need to change the definitions of any function |
55 | * defined in char_traits, can specialize __gnu_cxx::_Char_types |
56 | * while leaving __gnu_cxx::char_traits alone. */ |
57 | template<typename _CharT> |
58 | struct _Char_types |
59 | { |
60 | typedef unsigned long int_type; |
61 | typedef std::streampos pos_type; |
62 | typedef std::streamoff off_type; |
63 | typedef std::mbstate_t state_type; |
64 | }; |
65 | |
66 | |
67 | /** |
68 | * @brief Base class used to implement std::char_traits. |
69 | * |
70 | * @note For any given actual character type, this definition is |
71 | * probably wrong. (Most of the member functions are likely to be |
72 | * right, but the int_type and state_type typedefs, and the eof() |
73 | * member function, are likely to be wrong.) The reason this class |
74 | * exists is so users can specialize it. Classes in namespace std |
75 | * may not be specialized for fundamental types, but classes in |
76 | * namespace __gnu_cxx may be. |
77 | * |
78 | * See http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt05ch13s03.html |
79 | * for advice on how to make use of this class for @a unusual character |
80 | * types. Also, check out include/ext/pod_char_traits.h. |
81 | */ |
82 | template<typename _CharT> |
83 | struct char_traits |
84 | { |
85 | typedef _CharT char_type; |
86 | typedef typename _Char_types<_CharT>::int_type int_type; |
87 | typedef typename _Char_types<_CharT>::pos_type pos_type; |
88 | typedef typename _Char_types<_CharT>::off_type off_type; |
89 | typedef typename _Char_types<_CharT>::state_type state_type; |
90 | |
91 | static void |
92 | assign(char_type& __c1, const char_type& __c2) |
93 | { __c1 = __c2; } |
94 | |
95 | static _GLIBCXX_CONSTEXPR bool |
96 | eq(const char_type& __c1, const char_type& __c2) |
97 | { return __c1 == __c2; } |
98 | |
99 | static _GLIBCXX_CONSTEXPR bool |
100 | lt(const char_type& __c1, const char_type& __c2) |
101 | { return __c1 < __c2; } |
102 | |
103 | static int |
104 | compare(const char_type* __s1, const char_type* __s2, std::size_t __n); |
105 | |
106 | static std::size_t |
107 | length(const char_type* __s); |
108 | |
109 | static const char_type* |
110 | find(const char_type* __s, std::size_t __n, const char_type& __a); |
111 | |
112 | static char_type* |
113 | move(char_type* __s1, const char_type* __s2, std::size_t __n); |
114 | |
115 | static char_type* |
116 | copy(char_type* __s1, const char_type* __s2, std::size_t __n); |
117 | |
118 | static char_type* |
119 | assign(char_type* __s, std::size_t __n, char_type __a); |
120 | |
121 | static _GLIBCXX_CONSTEXPR char_type |
122 | to_char_type(const int_type& __c) |
123 | { return static_cast<char_type>(__c); } |
124 | |
125 | static _GLIBCXX_CONSTEXPR int_type |
126 | to_int_type(const char_type& __c) |
127 | { return static_cast<int_type>(__c); } |
128 | |
129 | static _GLIBCXX_CONSTEXPR bool |
130 | eq_int_type(const int_type& __c1, const int_type& __c2) |
131 | { return __c1 == __c2; } |
132 | |
133 | static _GLIBCXX_CONSTEXPR int_type |
134 | eof() |
135 | { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); } |
136 | |
137 | static _GLIBCXX_CONSTEXPR int_type |
138 | not_eof(const int_type& __c) |
139 | { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } |
140 | }; |
141 | |
142 | template<typename _CharT> |
143 | int |
144 | char_traits<_CharT>:: |
145 | compare(const char_type* __s1, const char_type* __s2, std::size_t __n) |
146 | { |
147 | for (std::size_t __i = 0; __i < __n; ++__i) |
148 | if (lt(__s1[__i], __s2[__i])) |
149 | return -1; |
150 | else if (lt(__s2[__i], __s1[__i])) |
151 | return 1; |
152 | return 0; |
153 | } |
154 | |
155 | template<typename _CharT> |
156 | std::size_t |
157 | char_traits<_CharT>:: |
158 | length(const char_type* __p) |
159 | { |
160 | std::size_t __i = 0; |
161 | while (!eq(__p[__i], char_type())) |
162 | ++__i; |
163 | return __i; |
164 | } |
165 | |
166 | template<typename _CharT> |
167 | const typename char_traits<_CharT>::char_type* |
168 | char_traits<_CharT>:: |
169 | find(const char_type* __s, std::size_t __n, const char_type& __a) |
170 | { |
171 | for (std::size_t __i = 0; __i < __n; ++__i) |
172 | if (eq(__s[__i], __a)) |
173 | return __s + __i; |
174 | return 0; |
175 | } |
176 | |
177 | template<typename _CharT> |
178 | typename char_traits<_CharT>::char_type* |
179 | char_traits<_CharT>:: |
180 | move(char_type* __s1, const char_type* __s2, std::size_t __n) |
181 | { |
182 | return static_cast<_CharT*>(__builtin_memmove(__s1, __s2, |
183 | __n * sizeof(char_type))); |
184 | } |
185 | |
186 | template<typename _CharT> |
187 | typename char_traits<_CharT>::char_type* |
188 | char_traits<_CharT>:: |
189 | copy(char_type* __s1, const char_type* __s2, std::size_t __n) |
190 | { |
191 | // NB: Inline std::copy so no recursive dependencies. |
192 | std::copy(__s2, __s2 + __n, __s1); |
193 | return __s1; |
194 | } |
195 | |
196 | template<typename _CharT> |
197 | typename char_traits<_CharT>::char_type* |
198 | char_traits<_CharT>:: |
199 | assign(char_type* __s, std::size_t __n, char_type __a) |
200 | { |
201 | // NB: Inline std::fill_n so no recursive dependencies. |
202 | std::fill_n(__s, __n, __a); |
203 | return __s; |
204 | } |
205 | |
206 | _GLIBCXX_END_NAMESPACE_VERSION |
207 | } // namespace |
208 | |
209 | namespace std _GLIBCXX_VISIBILITY(default) |
210 | { |
211 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
212 | |
213 | // 21.1 |
214 | /** |
215 | * @brief Basis for explicit traits specializations. |
216 | * |
217 | * @note For any given actual character type, this definition is |
218 | * probably wrong. Since this is just a thin wrapper around |
219 | * __gnu_cxx::char_traits, it is possible to achieve a more |
220 | * appropriate definition by specializing __gnu_cxx::char_traits. |
221 | * |
222 | * See http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt05ch13s03.html |
223 | * for advice on how to make use of this class for @a unusual character |
224 | * types. Also, check out include/ext/pod_char_traits.h. |
225 | */ |
226 | template<class _CharT> |
227 | struct char_traits : public __gnu_cxx::char_traits<_CharT> |
228 | { }; |
229 | |
230 | |
231 | /// 21.1.3.1 char_traits specializations |
232 | template<> |
233 | struct char_traits<char> |
234 | { |
235 | typedef char char_type; |
236 | typedef int int_type; |
237 | typedef streampos pos_type; |
238 | typedef streamoff off_type; |
239 | typedef mbstate_t state_type; |
240 | |
241 | static void |
242 | assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
243 | { __c1 = __c2; } |
244 | |
245 | static _GLIBCXX_CONSTEXPR bool |
246 | eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
247 | { return __c1 == __c2; } |
248 | |
249 | static _GLIBCXX_CONSTEXPR bool |
250 | lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
251 | { |
252 | // LWG 467. |
253 | return (static_cast<unsigned char>(__c1) |
254 | < static_cast<unsigned char>(__c2)); |
255 | } |
256 | |
257 | static int |
258 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
259 | { return __builtin_memcmp(__s1, __s2, __n); } |
260 | |
261 | static size_t |
262 | length(const char_type* __s) |
263 | { return __builtin_strlen(__s); } |
264 | |
265 | static const char_type* |
266 | find(const char_type* __s, size_t __n, const char_type& __a) |
267 | { return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n)); } |
268 | |
269 | static char_type* |
270 | move(char_type* __s1, const char_type* __s2, size_t __n) |
271 | { return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n)); } |
272 | |
273 | static char_type* |
274 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
275 | { return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n)); } |
276 | |
277 | static char_type* |
278 | assign(char_type* __s, size_t __n, char_type __a) |
279 | { return static_cast<char_type*>(__builtin_memset(__s, __a, __n)); } |
280 | |
281 | static _GLIBCXX_CONSTEXPR char_type |
282 | to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT |
283 | { return static_cast<char_type>(__c); } |
284 | |
285 | // To keep both the byte 0xff and the eof symbol 0xffffffff |
286 | // from ending up as 0xffffffff. |
287 | static _GLIBCXX_CONSTEXPR int_type |
288 | to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT |
289 | { return static_cast<int_type>(static_cast<unsigned char>(__c)); } |
290 | |
291 | static _GLIBCXX_CONSTEXPR bool |
292 | eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT |
293 | { return __c1 == __c2; } |
294 | |
295 | static _GLIBCXX_CONSTEXPR int_type |
296 | eof() _GLIBCXX_NOEXCEPT |
297 | { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); } |
298 | |
299 | static _GLIBCXX_CONSTEXPR int_type |
300 | not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT |
301 | { return (__c == eof()) ? 0 : __c; } |
302 | }; |
303 | |
304 | |
305 | #ifdef _GLIBCXX_USE_WCHAR_T |
306 | /// 21.1.3.2 char_traits specializations |
307 | template<> |
308 | struct char_traits<wchar_t> |
309 | { |
310 | typedef wchar_t char_type; |
311 | typedef wint_t int_type; |
312 | typedef streamoff off_type; |
313 | typedef wstreampos pos_type; |
314 | typedef mbstate_t state_type; |
315 | |
316 | static void |
317 | assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
318 | { __c1 = __c2; } |
319 | |
320 | static _GLIBCXX_CONSTEXPR bool |
321 | eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
322 | { return __c1 == __c2; } |
323 | |
324 | static _GLIBCXX_CONSTEXPR bool |
325 | lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT |
326 | { return __c1 < __c2; } |
327 | |
328 | static int |
329 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
330 | { return wmemcmp(__s1, __s2, __n); } |
331 | |
332 | static size_t |
333 | length(const char_type* __s) |
334 | { return wcslen(__s); } |
335 | |
336 | static const char_type* |
337 | find(const char_type* __s, size_t __n, const char_type& __a) |
338 | { return wmemchr(__s, __a, __n); } |
339 | |
340 | static char_type* |
341 | move(char_type* __s1, const char_type* __s2, size_t __n) |
342 | { return wmemmove(__s1, __s2, __n); } |
343 | |
344 | static char_type* |
345 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
346 | { return wmemcpy(__s1, __s2, __n); } |
347 | |
348 | static char_type* |
349 | assign(char_type* __s, size_t __n, char_type __a) |
350 | { return wmemset(__s, __a, __n); } |
351 | |
352 | static _GLIBCXX_CONSTEXPR char_type |
353 | to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT |
354 | { return char_type(__c); } |
355 | |
356 | static _GLIBCXX_CONSTEXPR int_type |
357 | to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT |
358 | { return int_type(__c); } |
359 | |
360 | static _GLIBCXX_CONSTEXPR bool |
361 | eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT |
362 | { return __c1 == __c2; } |
363 | |
364 | static _GLIBCXX_CONSTEXPR int_type |
365 | eof() _GLIBCXX_NOEXCEPT |
366 | { return static_cast<int_type>(WEOF); } |
367 | |
368 | static _GLIBCXX_CONSTEXPR int_type |
369 | not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT |
370 | { return eq_int_type(__c, eof()) ? 0 : __c; } |
371 | }; |
372 | #endif //_GLIBCXX_USE_WCHAR_T |
373 | |
374 | _GLIBCXX_END_NAMESPACE_VERSION |
375 | } // namespace |
376 | |
377 | #if ((__cplusplus >= 201103L) \ |
378 | && defined(_GLIBCXX_USE_C99_STDINT_TR1)) |
379 | |
380 | #include <cstdint> |
381 | |
382 | namespace std _GLIBCXX_VISIBILITY(default) |
383 | { |
384 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
385 | |
386 | template<> |
387 | struct char_traits<char16_t> |
388 | { |
389 | typedef char16_t char_type; |
390 | typedef uint_least16_t int_type; |
391 | typedef streamoff off_type; |
392 | typedef u16streampos pos_type; |
393 | typedef mbstate_t state_type; |
394 | |
395 | static void |
396 | assign(char_type& __c1, const char_type& __c2) noexcept |
397 | { __c1 = __c2; } |
398 | |
399 | static constexpr bool |
400 | eq(const char_type& __c1, const char_type& __c2) noexcept |
401 | { return __c1 == __c2; } |
402 | |
403 | static constexpr bool |
404 | lt(const char_type& __c1, const char_type& __c2) noexcept |
405 | { return __c1 < __c2; } |
406 | |
407 | static int |
408 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
409 | { |
410 | for (size_t __i = 0; __i < __n; ++__i) |
411 | if (lt(__s1[__i], __s2[__i])) |
412 | return -1; |
413 | else if (lt(__s2[__i], __s1[__i])) |
414 | return 1; |
415 | return 0; |
416 | } |
417 | |
418 | static size_t |
419 | length(const char_type* __s) |
420 | { |
421 | size_t __i = 0; |
422 | while (!eq(__s[__i], char_type())) |
423 | ++__i; |
424 | return __i; |
425 | } |
426 | |
427 | static const char_type* |
428 | find(const char_type* __s, size_t __n, const char_type& __a) |
429 | { |
430 | for (size_t __i = 0; __i < __n; ++__i) |
431 | if (eq(__s[__i], __a)) |
432 | return __s + __i; |
433 | return 0; |
434 | } |
435 | |
436 | static char_type* |
437 | move(char_type* __s1, const char_type* __s2, size_t __n) |
438 | { |
439 | return (static_cast<char_type*> |
440 | (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); |
441 | } |
442 | |
443 | static char_type* |
444 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
445 | { |
446 | return (static_cast<char_type*> |
447 | (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); |
448 | } |
449 | |
450 | static char_type* |
451 | assign(char_type* __s, size_t __n, char_type __a) |
452 | { |
453 | for (size_t __i = 0; __i < __n; ++__i) |
454 | assign(__s[__i], __a); |
455 | return __s; |
456 | } |
457 | |
458 | static constexpr char_type |
459 | to_char_type(const int_type& __c) noexcept |
460 | { return char_type(__c); } |
461 | |
462 | static constexpr int_type |
463 | to_int_type(const char_type& __c) noexcept |
464 | { return int_type(__c); } |
465 | |
466 | static constexpr bool |
467 | eq_int_type(const int_type& __c1, const int_type& __c2) noexcept |
468 | { return __c1 == __c2; } |
469 | |
470 | static constexpr int_type |
471 | eof() noexcept |
472 | { return static_cast<int_type>(-1); } |
473 | |
474 | static constexpr int_type |
475 | not_eof(const int_type& __c) noexcept |
476 | { return eq_int_type(__c, eof()) ? 0 : __c; } |
477 | }; |
478 | |
479 | template<> |
480 | struct char_traits<char32_t> |
481 | { |
482 | typedef char32_t char_type; |
483 | typedef uint_least32_t int_type; |
484 | typedef streamoff off_type; |
485 | typedef u32streampos pos_type; |
486 | typedef mbstate_t state_type; |
487 | |
488 | static void |
489 | assign(char_type& __c1, const char_type& __c2) noexcept |
490 | { __c1 = __c2; } |
491 | |
492 | static constexpr bool |
493 | eq(const char_type& __c1, const char_type& __c2) noexcept |
494 | { return __c1 == __c2; } |
495 | |
496 | static constexpr bool |
497 | lt(const char_type& __c1, const char_type& __c2) noexcept |
498 | { return __c1 < __c2; } |
499 | |
500 | static int |
501 | compare(const char_type* __s1, const char_type* __s2, size_t __n) |
502 | { |
503 | for (size_t __i = 0; __i < __n; ++__i) |
504 | if (lt(__s1[__i], __s2[__i])) |
505 | return -1; |
506 | else if (lt(__s2[__i], __s1[__i])) |
507 | return 1; |
508 | return 0; |
509 | } |
510 | |
511 | static size_t |
512 | length(const char_type* __s) |
513 | { |
514 | size_t __i = 0; |
515 | while (!eq(__s[__i], char_type())) |
516 | ++__i; |
517 | return __i; |
518 | } |
519 | |
520 | static const char_type* |
521 | find(const char_type* __s, size_t __n, const char_type& __a) |
522 | { |
523 | for (size_t __i = 0; __i < __n; ++__i) |
524 | if (eq(__s[__i], __a)) |
525 | return __s + __i; |
526 | return 0; |
527 | } |
528 | |
529 | static char_type* |
530 | move(char_type* __s1, const char_type* __s2, size_t __n) |
531 | { |
532 | return (static_cast<char_type*> |
533 | (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); |
534 | } |
535 | |
536 | static char_type* |
537 | copy(char_type* __s1, const char_type* __s2, size_t __n) |
538 | { |
539 | return (static_cast<char_type*> |
540 | (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); |
541 | } |
542 | |
543 | static char_type* |
544 | assign(char_type* __s, size_t __n, char_type __a) |
545 | { |
546 | for (size_t __i = 0; __i < __n; ++__i) |
547 | assign(__s[__i], __a); |
548 | return __s; |
549 | } |
550 | |
551 | static constexpr char_type |
552 | to_char_type(const int_type& __c) noexcept |
553 | { return char_type(__c); } |
554 | |
555 | static constexpr int_type |
556 | to_int_type(const char_type& __c) noexcept |
557 | { return int_type(__c); } |
558 | |
559 | static constexpr bool |
560 | eq_int_type(const int_type& __c1, const int_type& __c2) noexcept |
561 | { return __c1 == __c2; } |
562 | |
563 | static constexpr int_type |
564 | eof() noexcept |
565 | { return static_cast<int_type>(-1); } |
566 | |
567 | static constexpr int_type |
568 | not_eof(const int_type& __c) noexcept |
569 | { return eq_int_type(__c, eof()) ? 0 : __c; } |
570 | }; |
571 | |
572 | _GLIBCXX_END_NAMESPACE_VERSION |
573 | } // namespace |
574 | |
575 | #endif |
576 | |
577 | #endif // _CHAR_TRAITS_H |
578 | |