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