2005-04-26 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / libstdc++-v3 / testsuite / testsuite_character.h
blob2e1e433d9107b31efc0e1fb2b94d7eb626c1ca46
1 // -*- C++ -*-
3 // Testing character type and state type with char_traits and codecvt
4 // specializations for the C++ library testsuite.
5 //
6 // Copyright (C) 2003, 2005 Free Software Foundation, Inc.
7 //
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)
12 // any later version.
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,
22 // USA.
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
36 #include <climits>
37 #include <string> // for char_traits
38 #include <locale> // for codecvt
39 #include <ext/pod_char_traits.h>
41 namespace __gnu_test
43 struct pod_int
45 int value;
48 inline bool
49 operator==(const pod_int& lhs, const pod_int& rhs)
50 { return lhs.value == rhs.value; }
52 inline bool
53 operator<(const pod_int& lhs, const pod_int& rhs)
54 { return lhs.value < rhs.value; }
56 struct pod_state
58 unsigned long value;
61 inline bool
62 operator==(const pod_state& lhs, const pod_state& rhs)
63 { return lhs.value == rhs.value; }
65 inline bool
66 operator<(const pod_state& lhs, const pod_state& rhs)
67 { return lhs.value < rhs.value; }
69 // Alternate character types.
70 using __gnu_cxx::character;
71 typedef character<unsigned char, pod_int, pod_state> pod_char;
72 typedef character<unsigned char, unsigned int, pod_state> pod_uchar;
73 typedef character<unsigned short, unsigned int> pod_ushort;
75 // Specializations.
76 // pod_char
77 template<>
78 template<typename V2>
79 inline pod_char::char_type
80 pod_char::char_type::from(const V2& v)
82 char_type ret = { static_cast<value_type>(v.value) };
83 return ret;
86 template<>
87 template<typename V2>
88 inline V2
89 pod_char::char_type::to(const char_type& c)
91 V2 ret = { c.value };
92 return ret;
95 // pod_uchar
96 template<>
97 template<typename V2>
98 inline pod_uchar::char_type
99 pod_uchar::char_type::from(const V2& v)
101 char_type ret;
102 ret.value = (v >> 5);
103 return ret;
106 template<>
107 template<typename V2>
108 inline V2
109 pod_uchar::char_type::to(const char_type& c)
110 { return static_cast<V2>(c.value << 5); }
111 }; // namespace __gnu_test
113 namespace std
115 // codecvt specialization
117 // The conversion performed by the specialization is not supposed to
118 // be useful, rather it has been designed to demonstrate the
119 // essential features of stateful conversions:
120 // * Number and value of bytes for each internal character depends on the
121 // state in addition to the character itself.
122 // * Unshift produces an unshift sequence and resets the state. On input
123 // the unshift sequence causes the state to be reset.
125 // The conversion for output is as follows:
126 // 1. Calculate the value tmp by xor-ing the state and the internal
127 // character
128 // 2. Split tmp into either two or three bytes depending on the value of
129 // state. Output those bytes.
130 // 3. tmp becomes the new value of state.
131 template<>
132 class codecvt<__gnu_test::pod_uchar, char, __gnu_test::pod_state>
133 : public __codecvt_abstract_base<__gnu_test::pod_uchar, char,
134 __gnu_test::pod_state>
136 public:
137 typedef codecvt_base::result result;
138 typedef __gnu_test::pod_uchar intern_type;
139 typedef char extern_type;
140 typedef __gnu_test::pod_state state_type;
141 typedef __codecvt_abstract_base<intern_type, extern_type, state_type>
142 base_type;
144 explicit codecvt(size_t refs = 0) : base_type(refs)
147 static locale::id id;
149 protected:
150 ~codecvt()
153 virtual result
154 do_out(state_type& state, const intern_type* from,
155 const intern_type* from_end, const intern_type*& from_next,
156 extern_type* to, extern_type* to_limit,
157 extern_type*& to_next) const
159 while (from < from_end && to < to_limit)
161 unsigned char tmp = (state.value ^ from->value);
162 if (state.value & 0x8)
164 if (to >= to_limit - 2)
165 break;
166 *to++ = (tmp & 0x7);
167 *to++ = ((tmp >> 3) & 0x7);
168 *to++ = ((tmp >> 6) & 0x3);
170 else
172 if (to >= to_limit - 1)
173 break;
174 *to++ = (tmp & 0xf);
175 *to++ = ((tmp >> 4) & 0xf);
177 state.value = tmp;
178 ++from;
181 from_next = from;
182 to_next = to;
183 return (from < from_end) ? partial : ok;
186 virtual result
187 do_in(state_type& state, const extern_type* from,
188 const extern_type* from_end, const extern_type*& from_next,
189 intern_type* to, intern_type* to_limit,
190 intern_type*& to_next) const
192 while (from < from_end && to < to_limit)
194 unsigned char c = *from;
195 if (c & 0xc0)
197 // Unshift sequence
198 state.value &= c;
199 ++from;
200 continue;
203 unsigned char tmp;
204 if (state.value & 0x8)
206 if (from >= from_end - 2)
207 break;
208 tmp = (*from++ & 0x7);
209 tmp |= ((*from++ << 3) & 0x38);
210 tmp |= ((*from++ << 6) & 0xc0);
212 else
214 if (from >= from_end - 1)
215 break;
216 tmp = (*from++ & 0xf);
217 tmp |= ((*from++ << 4) & 0xf0);
219 to->value = (tmp ^ state.value);
220 state.value = tmp;
221 ++to;
224 from_next = from;
225 to_next = to;
226 return (from < from_end) ? partial : ok;
229 virtual result
230 do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
231 extern_type*& to_next) const
233 for (unsigned int i = 0; i < CHAR_BIT; ++i)
235 unsigned int mask = (1 << i);
236 if (state.value & mask)
238 if (to == to_limit)
240 to_next = to;
241 return partial;
244 state.value &= ~mask;
245 *to++ = static_cast<unsigned char>(~mask);
249 to_next = to;
250 return state.value == 0 ? ok : error;
253 virtual int
254 do_encoding() const throw()
255 { return -1; }
257 virtual bool
258 do_always_noconv() const throw()
259 { return false; }
261 virtual int
262 do_length(state_type& state, const extern_type* from,
263 const extern_type* end, size_t max) const
265 const extern_type* beg = from;
266 while (from < end && max)
268 unsigned char c = *from;
269 if (c & 0xc0)
271 // Unshift sequence
272 state.value &= c;
273 ++from;
274 continue;
277 unsigned char tmp;
278 if (state.value & 0x8)
280 if (from >= end - 2)
281 break;
282 tmp = (*from++ & 0x7);
283 tmp |= ((*from++ << 3) & 0x38);
284 tmp |= ((*from++ << 6) & 0xc0);
286 else
288 if (from >= end - 1)
289 break;
290 tmp = (*from++ & 0xf);
291 tmp |= ((*from++ << 4) & 0xf0);
293 state.value = tmp;
294 --max;
296 return from - beg;
299 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
300 // one character.
301 virtual int
302 do_max_length() const throw()
303 { return 11; }
306 template<>
307 class ctype<__gnu_test::pod_uchar>
308 : public __ctype_abstract_base<__gnu_test::pod_uchar>
310 public:
311 typedef __gnu_test::pod_uchar char_type;
313 explicit ctype(size_t refs = 0)
314 : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { }
316 static locale::id id;
318 protected:
319 ~ctype()
322 virtual bool
323 do_is(mask m, char_type c) const
324 { return false; }
326 virtual const char_type*
327 do_is(const char_type* low, const char_type* high, mask* vec) const
329 fill_n(vec, high - low, mask());
330 return high;
333 virtual const char_type*
334 do_scan_is(mask m, const char_type* low, const char_type* high) const
335 { return high; }
337 virtual const char_type*
338 do_scan_not(mask m, const char_type* low, const char_type* high) const
339 { return low; }
341 virtual char_type
342 do_toupper(char_type c) const
343 { return c; }
345 virtual const char_type*
346 do_toupper(char_type* low, const char_type* high) const
347 { return high; }
349 virtual char_type
350 do_tolower(char_type c) const
351 { return c; }
353 virtual const char_type*
354 do_tolower(char_type* low, const char_type* high) const
355 { return high; }
357 virtual char_type
358 do_widen(char c) const
359 { return __gnu_test::pod_uchar::from<char>(c); }
361 virtual const char*
362 do_widen(const char* low, const char* high, char_type* dest) const
364 transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
365 return high;
368 virtual char
369 do_narrow(char_type, char dfault) const
370 { return dfault; }
372 virtual const char_type*
373 do_narrow(const char_type* low, const char_type* high,
374 char dfault, char* dest) const
376 fill_n(dest, high - low, dfault);
377 return high;
380 } // namespace std
382 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H