This commit was manufactured by cvs2svn to create branch
[official-gcc.git] / libstdc++-v3 / testsuite / testsuite_character.h
blob9442fe13341e6a9b4bfd10ab065d7a4df3e91466
1 // -*- C++ -*-
2 // Testing character type and state type with char_traits and codecvt
3 // specializations for the C++ library testsuite.
4 //
5 // Copyright (C) 2003 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 2, or (at your option)
11 // any later version.
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.
18 // You should have received a copy of the GNU General Public License along
19 // with this library; see the file COPYING. If not, write to the Free
20 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 // USA.
23 // As a special exception, you may use this file as part of a free software
24 // library without restriction. Specifically, if other files instantiate
25 // templates or use macros or inline functions from this file, or you compile
26 // this file and link it with other files to produce an executable, this
27 // file does not by itself cause the resulting executable to be covered by
28 // the GNU General Public License. This exception does not however
29 // invalidate any other reasons why the executable file might be covered by
30 // the GNU General Public License.
32 #ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
33 #define _GLIBCXX_TESTSUITE_CHARACTER_H
35 #include <string> // for char_traits
36 #include <locale> // for codecvt
37 #include <climits>
39 namespace __gnu_test
41 // Character type
42 struct character
44 unsigned char val;
46 static character from_char(char c)
48 character ret;
49 ret.val = c;
50 return ret;
54 inline bool
55 operator==(const character& lhs, const character& rhs)
56 { return lhs.val == rhs.val; }
58 // State type.
59 struct conversion_state
61 unsigned int state;
63 }; // namespace __gnu_test
65 namespace std
67 // char_traits specialization. Meets the additional requirements for
68 // basic_filebuf.
69 template<>
70 struct char_traits<__gnu_test::character>
72 typedef __gnu_test::character char_type;
73 typedef unsigned int int_type;
74 typedef __gnu_test::conversion_state state_type;
75 typedef streamoff off_type;
76 typedef fpos<state_type> pos_type;
78 static void
79 assign(char_type& c1, const char_type& c2)
80 { c1 = c2; }
82 static bool
83 eq(const char_type& c1, const char_type& c2)
84 { return c1.val == c2.val; }
86 static bool
87 lt(const char_type& c1, const char_type& c2)
88 { return c1.val < c2.val; }
90 static int
91 compare(const char_type* s1, const char_type* s2, size_t n)
93 for (size_t i = 0; i < n; ++i)
95 if (lt(s1[i], s2[i]))
96 return -1;
97 else if (lt(s2[i], s1[i]))
98 return 1;
100 return 0;
103 static size_t
104 length(const char_type* s)
106 size_t n = 0;
107 while (!eq(s[n], char_type()))
108 ++n;
109 return n;
112 static const char_type*
113 find(const char_type* s, size_t n, const char_type& a)
115 for (size_t i = 0; i < n; ++i)
117 if (eq(s[i], a))
118 return s + i;
120 return NULL;
123 static char_type*
124 move(char_type* s1, const char_type* s2, size_t n)
126 if (s1 > s2)
128 for (size_t i = 0; i < n; ++i)
129 assign(s1[n - i - 1], s2[n - i - 1]);
131 else
133 for (size_t i = 0; i < n; ++i)
134 assign(s1[i], s2[i]);
136 return s1;
139 static char_type*
140 copy(char_type* s1, const char_type* s2, size_t n)
142 for (size_t i = 0; i < n; ++i)
143 assign(s1[i], s2[i]);
144 return s1;
147 static char_type*
148 assign(char_type* s, size_t n, char_type a)
150 for (size_t i = 0; i < n; ++i)
151 assign(s[i], a);
152 return s;
155 static int_type
156 not_eof(const int_type& c)
158 if (eq_int_type(c, eof()))
159 return 0;
160 return c;
163 // Note non-trivial conversion to maximize chance of catching bugs
164 static char_type
165 to_char_type(const int_type& c)
167 char_type ret;
168 ret.val = (c >> 5);
169 return ret;
172 static int_type
173 to_int_type(const char_type& c)
175 return c.val << 5;
178 static bool
179 eq_int_type(const int_type& c1, const int_type& c2)
180 { return c1 == c2; }
182 static int_type eof()
183 { return 0xf; }
186 // codecvt specialization
188 // The conversion performed by the specialization is not supposed to
189 // be useful, rather it has been designed to demonstrate the
190 // essential features of stateful conversions:
191 // * Number and value of bytes for each internal character depends on the
192 // state in addition to the character itself.
193 // * Unshift produces an unshift sequence and resets the state. On input
194 // the unshift sequence causes the state to be reset.
196 // The conversion for output is as follows:
197 // 1. Calculate the value tmp by xor-ing the state and the internal
198 // character
199 // 2. Split tmp into either two or three bytes depending on the value of
200 // state. Output those bytes.
201 // 3. tmp becomes the new value of state.
202 template<>
203 class codecvt<__gnu_test::character, char, __gnu_test::conversion_state>
204 : public locale::facet, public codecvt_base
206 public:
207 typedef __gnu_test::character intern_type;
208 typedef char extern_type;
209 typedef __gnu_test::conversion_state state_type;
211 explicit codecvt(size_t refs = 0)
212 : locale::facet(refs)
215 result
216 out(state_type& state, const intern_type* from,
217 const intern_type* from_end, const intern_type*& from_next,
218 extern_type* to, extern_type* to_limit, extern_type*& to_next) const
220 return do_out(state, from, from_end, from_next,
221 to, to_limit, to_next);
224 result
225 unshift(state_type& state, extern_type* to, extern_type* to_limit,
226 extern_type*& to_next) const
227 { return do_unshift(state, to, to_limit, to_next); }
229 result
230 in(state_type& state, const extern_type* from,
231 const extern_type* from_end, const extern_type*& from_next,
232 intern_type* to, intern_type* to_limit, intern_type*& to_next) const
234 return do_in(state, from, from_end, from_next,
235 to, to_limit, to_next);
239 encoding() const throw()
240 { return do_encoding(); }
242 bool
243 always_noconv() const throw()
244 { return do_always_noconv(); }
247 length(state_type& state, const extern_type* from,
248 const extern_type* end, size_t max) const
249 { return do_length(state, from, end, max); }
252 max_length() const throw()
253 { return do_max_length(); }
255 static locale::id id;
257 protected:
258 ~codecvt()
261 virtual result
262 do_out(state_type& state, const intern_type* from,
263 const intern_type* from_end, const intern_type*& from_next,
264 extern_type* to, extern_type* to_limit,
265 extern_type*& to_next) const
267 while (from < from_end && to < to_limit)
269 unsigned char tmp = (state.state ^ from->val);
270 if (state.state & 0x8)
272 if (to >= to_limit - 2)
273 break;
274 *to++ = (tmp & 0x7);
275 *to++ = ((tmp >> 3) & 0x7);
276 *to++ = ((tmp >> 6) & 0x3);
278 else
280 if (to >= to_limit - 1)
281 break;
282 *to++ = (tmp & 0xf);
283 *to++ = ((tmp >> 4) & 0xf);
285 state.state = tmp;
286 ++from;
289 from_next = from;
290 to_next = to;
291 return (from < from_end) ? partial : ok;
294 virtual result
295 do_in(state_type& state, const extern_type* from,
296 const extern_type* from_end, const extern_type*& from_next,
297 intern_type* to, intern_type* to_limit,
298 intern_type*& to_next) const
300 while (from < from_end && to < to_limit)
302 unsigned char c = *from;
303 if (c & 0xc0)
305 // Unshift sequence
306 state.state &= c;
307 ++from;
308 continue;
311 unsigned char tmp;
312 if (state.state & 0x8)
314 if (from >= from_end - 2)
315 break;
316 tmp = (*from++ & 0x7);
317 tmp |= ((*from++ << 3) & 0x38);
318 tmp |= ((*from++ << 6) & 0xc0);
320 else
322 if (from >= from_end - 1)
323 break;
324 tmp = (*from++ & 0xf);
325 tmp |= ((*from++ << 4) & 0xf0);
327 to->val = (tmp ^ state.state);
328 state.state = tmp;
329 ++to;
332 from_next = from;
333 to_next = to;
334 return (from < from_end) ? partial : ok;
337 virtual result
338 do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
339 extern_type*& to_next) const
341 for (unsigned int i = 0; i < CHAR_BIT; ++i)
343 unsigned int mask = (1 << i);
344 if (state.state & mask)
346 if (to == to_limit)
348 to_next = to;
349 return partial;
352 state.state &= ~mask;
353 *to++ = static_cast<unsigned char>(~mask);
357 to_next = to;
358 return state.state == 0 ? ok : error;
361 virtual int
362 do_encoding() const throw()
363 { return -1; }
365 virtual bool
366 do_always_noconv() const throw()
367 { return false; }
369 virtual int
370 do_length(state_type& state, const extern_type* from,
371 const extern_type* end, size_t max) const
373 const extern_type* beg = from;
374 while (from < end && max)
376 unsigned char c = *from;
377 if (c & 0xc0)
379 // Unshift sequence
380 state.state &= c;
381 ++from;
382 continue;
385 unsigned char tmp;
386 if (state.state & 0x8)
388 if (from >= end - 2)
389 break;
390 tmp = (*from++ & 0x7);
391 tmp |= ((*from++ << 3) & 0x38);
392 tmp |= ((*from++ << 6) & 0xc0);
394 else
396 if (from >= end - 1)
397 break;
398 tmp = (*from++ & 0xf);
399 tmp |= ((*from++ << 4) & 0xf0);
401 state.state = tmp;
402 --max;
404 return from - beg;
407 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
408 // one character.
409 virtual int
410 do_max_length() const throw()
411 { return 11; }
414 locale::id
415 codecvt<__gnu_test::character, char, __gnu_test::conversion_state>::id;
416 } // namespace std
418 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H