3 // Testing character type and state type with char_traits and codecvt
4 // specializations for the C++ library testsuite.
6 // Copyright (C) 2003, 2004, 2005, 2006, 2007 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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 <algorithm> // for transform
40 #include <ext/pod_char_traits.h>
50 operator==(const pod_int& lhs, const pod_int& rhs)
51 { return lhs.value == rhs.value; }
54 operator<(const pod_int& lhs, const pod_int& rhs)
55 { return lhs.value < rhs.value; }
63 operator==(const pod_state& lhs, const pod_state& rhs)
64 { return lhs.value == rhs.value; }
67 operator<(const pod_state& lhs, const pod_state& rhs)
68 { return lhs.value < rhs.value; }
70 // Alternate character types.
71 using __gnu_cxx::character;
72 typedef character<unsigned char, pod_int, pod_state> pod_char;
73 typedef character<unsigned char, unsigned int, pod_state> pod_uchar;
74 typedef character<unsigned short, unsigned int> pod_ushort;
75 typedef character<unsigned int, unsigned long> pod_uint;
84 inline __gnu_test::pod_char::char_type
85 __gnu_test::pod_char::char_type::from(const V2& v)
87 char_type ret = { static_cast<value_type>(v.value) };
94 __gnu_test::pod_char::char_type::to(const char_type& c)
101 template<typename V2>
102 inline __gnu_test::pod_uchar::char_type
103 __gnu_test::pod_uchar::char_type::from(const V2& v)
106 ret.value = (v >> 5);
111 template<typename V2>
113 __gnu_test::pod_uchar::char_type::to(const char_type& c)
114 { return static_cast<V2>(c.value << 5); }
115 }; // namespace __gnu_test
119 // codecvt specialization
121 // The conversion performed by the specialization is not supposed to
122 // be useful, rather it has been designed to demonstrate the
123 // essential features of stateful conversions:
124 // * Number and value of bytes for each internal character depends on the
125 // state in addition to the character itself.
126 // * Unshift produces an unshift sequence and resets the state. On input
127 // the unshift sequence causes the state to be reset.
129 // The conversion for output is as follows:
130 // 1. Calculate the value tmp by xor-ing the state and the internal
132 // 2. Split tmp into either two or three bytes depending on the value of
133 // state. Output those bytes.
134 // 3. tmp becomes the new value of state.
136 class codecvt<__gnu_test::pod_uchar, char, __gnu_test::pod_state>
137 : public __codecvt_abstract_base<__gnu_test::pod_uchar, char,
138 __gnu_test::pod_state>
141 typedef codecvt_base::result result;
142 typedef __gnu_test::pod_uchar intern_type;
143 typedef char extern_type;
144 typedef __gnu_test::pod_state state_type;
145 typedef __codecvt_abstract_base<intern_type, extern_type, state_type>
148 explicit codecvt(size_t refs = 0) : base_type(refs)
151 static locale::id id;
158 do_out(state_type& state, const intern_type* from,
159 const intern_type* from_end, const intern_type*& from_next,
160 extern_type* to, extern_type* to_limit,
161 extern_type*& to_next) const
163 while (from < from_end && to < to_limit)
165 unsigned char tmp = (state.value ^ from->value);
166 if (state.value & 0x8)
168 if (to >= to_limit - 2)
171 *to++ = ((tmp >> 3) & 0x7);
172 *to++ = ((tmp >> 6) & 0x3);
176 if (to >= to_limit - 1)
179 *to++ = ((tmp >> 4) & 0xf);
187 return (from < from_end) ? partial : ok;
191 do_in(state_type& state, const extern_type* from,
192 const extern_type* from_end, const extern_type*& from_next,
193 intern_type* to, intern_type* to_limit,
194 intern_type*& to_next) const
196 while (from < from_end && to < to_limit)
198 unsigned char c = *from;
208 if (state.value & 0x8)
210 if (from >= from_end - 2)
212 tmp = (*from++ & 0x7);
213 tmp |= ((*from++ << 3) & 0x38);
214 tmp |= ((*from++ << 6) & 0xc0);
218 if (from >= from_end - 1)
220 tmp = (*from++ & 0xf);
221 tmp |= ((*from++ << 4) & 0xf0);
223 to->value = (tmp ^ state.value);
230 return (from < from_end) ? partial : ok;
234 do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
235 extern_type*& to_next) const
237 for (unsigned int i = 0; i < CHAR_BIT; ++i)
239 unsigned int mask = (1 << i);
240 if (state.value & mask)
248 state.value &= ~mask;
249 *to++ = static_cast<unsigned char>(~mask);
254 return state.value == 0 ? ok : error;
258 do_encoding() const throw()
262 do_always_noconv() const throw()
266 do_length(state_type& state, const extern_type* from,
267 const extern_type* end, size_t max) const
269 const extern_type* beg = from;
270 while (from < end && max)
272 unsigned char c = *from;
282 if (state.value & 0x8)
286 tmp = (*from++ & 0x7);
287 tmp |= ((*from++ << 3) & 0x38);
288 tmp |= ((*from++ << 6) & 0xc0);
294 tmp = (*from++ & 0xf);
295 tmp |= ((*from++ << 4) & 0xf0);
303 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
306 do_max_length() const throw()
311 class ctype<__gnu_test::pod_uchar>
312 : public __ctype_abstract_base<__gnu_test::pod_uchar>
315 typedef __gnu_test::pod_uchar char_type;
317 explicit ctype(size_t refs = 0)
318 : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { }
320 static locale::id id;
327 do_is(mask, char_type) const
330 virtual const char_type*
331 do_is(const char_type* low, const char_type* high, mask* vec) const
333 fill_n(vec, high - low, mask());
337 virtual const char_type*
338 do_scan_is(mask, const char_type*, const char_type* high) const
341 virtual const char_type*
342 do_scan_not(mask, const char_type* low, const char_type*) const
346 do_toupper(char_type c) const
349 virtual const char_type*
350 do_toupper(char_type*, const char_type* high) const
354 do_tolower(char_type c) const
357 virtual const char_type*
358 do_tolower(char_type*, const char_type* high) const
362 do_widen(char c) const
363 { return __gnu_test::pod_uchar::from<char>(c); }
366 do_widen(const char* low, const char* high, char_type* dest) const
368 transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
373 do_narrow(char_type, char dfault) const
376 virtual const char_type*
377 do_narrow(const char_type* low, const char_type* high,
378 char dfault, char* dest) const
380 fill_n(dest, high - low, dfault);
385 // numpunct specializations
387 class numpunct<__gnu_test::pod_uint>
388 : public locale::facet
391 typedef __gnu_test::pod_uint char_type;
392 typedef basic_string<char_type> string_type;
394 static locale::id id;
397 numpunct(size_t refs = 0)
398 : locale::facet(refs)
402 decimal_point() const
403 { return this->do_decimal_point(); }
406 thousands_sep() const
407 { return this->do_thousands_sep(); }
411 { return this->do_grouping(); }
415 { return this->do_truename(); }
419 { return this->do_falsename(); }
426 do_decimal_point() const
427 { return char_type(); }
430 do_thousands_sep() const
431 { return char_type(); }
439 { return string_type(); }
443 { return string_type(); }
447 class moneypunct<__gnu_test::pod_uint>
448 : public locale::facet, public money_base
451 typedef __gnu_test::pod_uint char_type;
452 typedef basic_string<char_type> string_type;
454 static locale::id id;
455 static const bool intl = false;
458 moneypunct(size_t refs = 0)
459 : locale::facet(refs)
463 decimal_point() const
464 { return this->do_decimal_point(); }
467 thousands_sep() const
468 { return this->do_thousands_sep(); }
472 { return this->do_grouping(); }
476 { return this->do_curr_symbol(); }
479 positive_sign() const
480 { return this->do_positive_sign(); }
483 negative_sign() const
484 { return this->do_negative_sign(); }
488 { return this->do_frac_digits(); }
492 { return this->do_pos_format(); }
496 { return this->do_neg_format(); }
503 do_decimal_point() const
504 { return char_type(); }
507 do_thousands_sep() const
508 { return char_type(); }
515 do_curr_symbol() const
516 { return string_type(); }
519 do_positive_sign() const
520 { return string_type(); }
523 do_negative_sign() const
524 { return string_type(); }
527 do_frac_digits() const
531 do_pos_format() const
532 { return pattern(); }
535 do_neg_format() const
536 { return pattern(); }
540 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H