3 // Testing character type and state type with char_traits and codecvt
4 // specializations for the C++ library testsuite.
6 // Copyright (C) 2003, 2005 Free Software Foundation, Inc.
8 // This file is part of the GNU ISO C++ Library. This library is free
9 // software; you can redistribute it and/or modify it under the
10 // terms of the GNU General Public License as published by the
11 // Free Software Foundation; either version 2, or (at your option)
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
19 // You should have received a copy of the GNU General Public License along
20 // with this library; see the file COPYING. If not, write to the Free
21 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
24 // As a special exception, you may use this file as part of a free software
25 // library without restriction. Specifically, if other files instantiate
26 // templates or use macros or inline functions from this file, or you compile
27 // this file and link it with other files to produce an executable, this
28 // file does not by itself cause the resulting executable to be covered by
29 // the GNU General Public License. This exception does not however
30 // invalidate any other reasons why the executable file might be covered by
31 // the GNU General Public License.
33 #ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
34 #define _GLIBCXX_TESTSUITE_CHARACTER_H
37 #include <string> // for char_traits
38 #include <locale> // for codecvt
39 #include <ext/pod_char_traits.h>
48 static character from_char(char c)
57 operator==(const character& lhs, const character& rhs)
58 { return lhs.val == rhs.val; }
61 struct conversion_state
73 operator==(const pod_char& lhs, const pod_char& rhs)
74 { return lhs.c == rhs.c; }
87 typedef unsigned short value_type;
88 typedef unsigned int int_type;
89 typedef __gnu_cxx::character<value_type, int_type> pod_type;
90 }; // namespace __gnu_test
94 // A std::char_traits specialization. Meets the additional
95 // requirements for basic_filebuf.
97 struct char_traits<__gnu_test::character>
99 typedef __gnu_test::character char_type;
100 typedef unsigned int int_type;
101 typedef __gnu_test::conversion_state state_type;
102 typedef streamoff off_type;
103 typedef fpos<state_type> pos_type;
106 assign(char_type& c1, const char_type& c2)
110 eq(const char_type& c1, const char_type& c2)
111 { return c1.val == c2.val; }
114 lt(const char_type& c1, const char_type& c2)
115 { return c1.val < c2.val; }
118 compare(const char_type* s1, const char_type* s2, size_t n)
120 for (size_t i = 0; i < n; ++i)
122 if (lt(s1[i], s2[i]))
124 else if (lt(s2[i], s1[i]))
131 length(const char_type* s)
134 while (!eq(s[n], char_type()))
139 static const char_type*
140 find(const char_type* s, size_t n, const char_type& a)
142 for (size_t i = 0; i < n; ++i)
151 move(char_type* s1, const char_type* s2, size_t n)
155 for (size_t i = 0; i < n; ++i)
156 assign(s1[n - i - 1], s2[n - i - 1]);
160 for (size_t i = 0; i < n; ++i)
161 assign(s1[i], s2[i]);
167 copy(char_type* s1, const char_type* s2, size_t n)
169 for (size_t i = 0; i < n; ++i)
170 assign(s1[i], s2[i]);
175 assign(char_type* s, size_t n, char_type a)
177 for (size_t i = 0; i < n; ++i)
183 not_eof(const int_type& c)
185 if (eq_int_type(c, eof()))
190 // Note non-trivial conversion to maximize chance of catching bugs
192 to_char_type(const int_type& c)
200 to_int_type(const char_type& c)
206 eq_int_type(const int_type& c1, const int_type& c2)
209 static int_type eof()
213 // codecvt specialization
215 // The conversion performed by the specialization is not supposed to
216 // be useful, rather it has been designed to demonstrate the
217 // essential features of stateful conversions:
218 // * Number and value of bytes for each internal character depends on the
219 // state in addition to the character itself.
220 // * Unshift produces an unshift sequence and resets the state. On input
221 // the unshift sequence causes the state to be reset.
223 // The conversion for output is as follows:
224 // 1. Calculate the value tmp by xor-ing the state and the internal
226 // 2. Split tmp into either two or three bytes depending on the value of
227 // state. Output those bytes.
228 // 3. tmp becomes the new value of state.
230 class codecvt<__gnu_test::character, char, __gnu_test::conversion_state>
231 : public locale::facet, public codecvt_base
234 typedef __gnu_test::character intern_type;
235 typedef char extern_type;
236 typedef __gnu_test::conversion_state state_type;
238 explicit codecvt(size_t refs = 0)
239 : locale::facet(refs)
243 out(state_type& state, const intern_type* from,
244 const intern_type* from_end, const intern_type*& from_next,
245 extern_type* to, extern_type* to_limit, extern_type*& to_next) const
247 return do_out(state, from, from_end, from_next,
248 to, to_limit, to_next);
252 unshift(state_type& state, extern_type* to, extern_type* to_limit,
253 extern_type*& to_next) const
254 { return do_unshift(state, to, to_limit, to_next); }
257 in(state_type& state, const extern_type* from,
258 const extern_type* from_end, const extern_type*& from_next,
259 intern_type* to, intern_type* to_limit, intern_type*& to_next) const
261 return do_in(state, from, from_end, from_next,
262 to, to_limit, to_next);
266 encoding() const throw()
267 { return do_encoding(); }
270 always_noconv() const throw()
271 { return do_always_noconv(); }
274 length(state_type& state, const extern_type* from,
275 const extern_type* end, size_t max) const
276 { return do_length(state, from, end, max); }
279 max_length() const throw()
280 { return do_max_length(); }
282 static locale::id id;
289 do_out(state_type& state, const intern_type* from,
290 const intern_type* from_end, const intern_type*& from_next,
291 extern_type* to, extern_type* to_limit,
292 extern_type*& to_next) const
294 while (from < from_end && to < to_limit)
296 unsigned char tmp = (state.state ^ from->val);
297 if (state.state & 0x8)
299 if (to >= to_limit - 2)
302 *to++ = ((tmp >> 3) & 0x7);
303 *to++ = ((tmp >> 6) & 0x3);
307 if (to >= to_limit - 1)
310 *to++ = ((tmp >> 4) & 0xf);
318 return (from < from_end) ? partial : ok;
322 do_in(state_type& state, const extern_type* from,
323 const extern_type* from_end, const extern_type*& from_next,
324 intern_type* to, intern_type* to_limit,
325 intern_type*& to_next) const
327 while (from < from_end && to < to_limit)
329 unsigned char c = *from;
339 if (state.state & 0x8)
341 if (from >= from_end - 2)
343 tmp = (*from++ & 0x7);
344 tmp |= ((*from++ << 3) & 0x38);
345 tmp |= ((*from++ << 6) & 0xc0);
349 if (from >= from_end - 1)
351 tmp = (*from++ & 0xf);
352 tmp |= ((*from++ << 4) & 0xf0);
354 to->val = (tmp ^ state.state);
361 return (from < from_end) ? partial : ok;
365 do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
366 extern_type*& to_next) const
368 for (unsigned int i = 0; i < CHAR_BIT; ++i)
370 unsigned int mask = (1 << i);
371 if (state.state & mask)
379 state.state &= ~mask;
380 *to++ = static_cast<unsigned char>(~mask);
385 return state.state == 0 ? ok : error;
389 do_encoding() const throw()
393 do_always_noconv() const throw()
397 do_length(state_type& state, const extern_type* from,
398 const extern_type* end, size_t max) const
400 const extern_type* beg = from;
401 while (from < end && max)
403 unsigned char c = *from;
413 if (state.state & 0x8)
417 tmp = (*from++ & 0x7);
418 tmp |= ((*from++ << 3) & 0x38);
419 tmp |= ((*from++ << 6) & 0xc0);
425 tmp = (*from++ & 0xf);
426 tmp |= ((*from++ << 4) & 0xf0);
434 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
437 do_max_length() const throw()
442 // A std::char_traits specialization with POD types for char_type,
443 // int_type, and state_type.
445 struct char_traits<__gnu_test::pod_char>
447 typedef __gnu_test::pod_char char_type;
448 typedef __gnu_test::pod_int int_type;
449 typedef __gnu_test::state state_type;
450 typedef fpos<state_type> pos_type;
451 typedef streamoff off_type;
454 assign(char_type& c1, const char_type& c2)
458 eq(const char_type& c1, const char_type& c2)
459 { return c1.c == c2.c; }
462 lt(const char_type& c1, const char_type& c2)
463 { return c1.c < c2.c; }
466 compare(const char_type* s1, const char_type* s2, size_t n)
467 { return memcmp(s1, s2, n); }
470 length(const char_type* s)
471 { return strlen(reinterpret_cast<const char*>(s)); }
473 static const char_type*
474 find(const char_type* s, size_t n, const char_type& a)
475 { return static_cast<const char_type*>(memchr(s, a.c, n)); }
478 move(char_type* s1, const char_type* s2, size_t n)
485 copy(char_type* s1, const char_type* s2, size_t n)
492 assign(char_type* s, size_t n, char_type a)
499 to_char_type(const int_type& c)
502 ret.c = static_cast<unsigned char>(c.i);
507 to_int_type(const char_type& c)
515 eq_int_type(const int_type& c1, const int_type& c2)
516 { return c1.i == c2.i; }
527 not_eof(const int_type& c)
529 if (eq_int_type(c, eof()))
536 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H