Fix change log
[official-gcc.git] / libstdc++-v3 / testsuite / util / testsuite_character.h
blobceda1f5125e09b13df91feccbbbe4c73523598cc
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, 2004, 2005, 2006, 2007, 2008, 2009
7 // Free Software Foundation, Inc.
8 //
9 // This file is part of the GNU ISO C++ Library. This library is free
10 // software; you can redistribute it and/or modify it under the
11 // terms of the GNU General Public License as published by the
12 // Free Software Foundation; either version 3, or (at your option)
13 // any later version.
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
20 // You should have received a copy of the GNU General Public License along
21 // with this library; see the file COPYING3. If not see
22 // <http://www.gnu.org/licenses/>.
25 #ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
26 #define _GLIBCXX_TESTSUITE_CHARACTER_H
28 #include <climits>
29 #include <string> // for char_traits
30 #include <locale> // for codecvt
31 #include <algorithm> // for transform
32 #include <ext/pod_char_traits.h>
34 namespace __gnu_test
36 struct pod_int
38 int value;
40 #ifdef __GXX_EXPERIMENTAL_CXX0X__
41 // For std::iota.
42 pod_int&
43 operator++()
45 ++value;
46 return *this;
48 #endif
51 // For 20.1 requirements for instantiable type: equality comparable
52 // and less than comparable.
53 inline bool
54 operator==(const pod_int& lhs, const pod_int& rhs)
55 { return lhs.value == rhs.value; }
57 inline bool
58 operator<(const pod_int& lhs, const pod_int& rhs)
59 { return lhs.value < rhs.value; }
61 // For 26 numeric algorithms requirements, need addable,
62 // subtractable, multiplicable.
63 inline pod_int
64 operator+(const pod_int& lhs, const pod_int& rhs)
66 pod_int ret = { lhs.value + rhs.value };
67 return ret;
70 inline pod_int
71 operator-(const pod_int& lhs, const pod_int& rhs)
73 pod_int ret = { lhs.value - rhs.value };
74 return ret;
77 inline pod_int
78 operator*(const pod_int& lhs, const pod_int& rhs)
80 pod_int ret = { lhs.value * rhs.value };
81 return ret;
84 struct pod_state
86 unsigned long value;
89 inline bool
90 operator==(const pod_state& lhs, const pod_state& rhs)
91 { return lhs.value == rhs.value; }
93 inline bool
94 operator<(const pod_state& lhs, const pod_state& rhs)
95 { return lhs.value < rhs.value; }
97 // Alternate character types.
98 using __gnu_cxx::character;
99 typedef character<unsigned char, pod_int, pod_state> pod_char;
100 typedef character<unsigned char, unsigned int, pod_state> pod_uchar;
101 typedef character<unsigned short, unsigned int> pod_ushort;
102 typedef character<unsigned int, unsigned long> pod_uint;
105 namespace __gnu_cxx
107 // Specializations.
108 // pod_char
109 template<>
110 template<typename V2>
111 inline __gnu_test::pod_char::char_type
112 __gnu_test::pod_char::char_type::from(const V2& v)
114 char_type ret = { static_cast<value_type>(v.value) };
115 return ret;
118 template<>
119 template<typename V2>
120 inline V2
121 __gnu_test::pod_char::char_type::to(const char_type& c)
123 V2 ret = { c.value };
124 return ret;
127 template<>
128 template<typename V2>
129 inline __gnu_test::pod_uchar::char_type
130 __gnu_test::pod_uchar::char_type::from(const V2& v)
132 char_type ret;
133 ret.value = (v >> 5);
134 return ret;
137 template<>
138 template<typename V2>
139 inline V2
140 __gnu_test::pod_uchar::char_type::to(const char_type& c)
141 { return static_cast<V2>(c.value << 5); }
142 } // namespace __gnu_test
144 namespace std
146 // codecvt specialization
148 // The conversion performed by the specialization is not supposed to
149 // be useful, rather it has been designed to demonstrate the
150 // essential features of stateful conversions:
151 // * Number and value of bytes for each internal character depends on the
152 // state in addition to the character itself.
153 // * Unshift produces an unshift sequence and resets the state. On input
154 // the unshift sequence causes the state to be reset.
156 // The conversion for output is as follows:
157 // 1. Calculate the value tmp by xor-ing the state and the internal
158 // character
159 // 2. Split tmp into either two or three bytes depending on the value of
160 // state. Output those bytes.
161 // 3. tmp becomes the new value of state.
162 template<>
163 class codecvt<__gnu_test::pod_uchar, char, __gnu_test::pod_state>
164 : public __codecvt_abstract_base<__gnu_test::pod_uchar, char,
165 __gnu_test::pod_state>
167 public:
168 typedef codecvt_base::result result;
169 typedef __gnu_test::pod_uchar intern_type;
170 typedef char extern_type;
171 typedef __gnu_test::pod_state state_type;
172 typedef __codecvt_abstract_base<intern_type, extern_type, state_type>
173 base_type;
175 explicit codecvt(size_t refs = 0) : base_type(refs)
178 static locale::id id;
180 protected:
181 ~codecvt()
184 virtual result
185 do_out(state_type& state, const intern_type* from,
186 const intern_type* from_end, const intern_type*& from_next,
187 extern_type* to, extern_type* to_limit,
188 extern_type*& to_next) const
190 while (from < from_end && to < to_limit)
192 unsigned char tmp = (state.value ^ from->value);
193 if (state.value & 0x8)
195 if (to >= to_limit - 2)
196 break;
197 *to++ = (tmp & 0x7);
198 *to++ = ((tmp >> 3) & 0x7);
199 *to++ = ((tmp >> 6) & 0x3);
201 else
203 if (to >= to_limit - 1)
204 break;
205 *to++ = (tmp & 0xf);
206 *to++ = ((tmp >> 4) & 0xf);
208 state.value = tmp;
209 ++from;
212 from_next = from;
213 to_next = to;
214 return (from < from_end) ? partial : ok;
217 virtual result
218 do_in(state_type& state, const extern_type* from,
219 const extern_type* from_end, const extern_type*& from_next,
220 intern_type* to, intern_type* to_limit,
221 intern_type*& to_next) const
223 while (from < from_end && to < to_limit)
225 unsigned char c = *from;
226 if (c & 0xc0)
228 // Unshift sequence
229 state.value &= c;
230 ++from;
231 continue;
234 unsigned char tmp;
235 if (state.value & 0x8)
237 if (from >= from_end - 2)
238 break;
239 tmp = (*from++ & 0x7);
240 tmp |= ((*from++ << 3) & 0x38);
241 tmp |= ((*from++ << 6) & 0xc0);
243 else
245 if (from >= from_end - 1)
246 break;
247 tmp = (*from++ & 0xf);
248 tmp |= ((*from++ << 4) & 0xf0);
250 to->value = (tmp ^ state.value);
251 state.value = tmp;
252 ++to;
255 from_next = from;
256 to_next = to;
257 return (from < from_end) ? partial : ok;
260 virtual result
261 do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
262 extern_type*& to_next) const
264 for (unsigned int i = 0; i < CHAR_BIT; ++i)
266 unsigned int mask = (1 << i);
267 if (state.value & mask)
269 if (to == to_limit)
271 to_next = to;
272 return partial;
275 state.value &= ~mask;
276 *to++ = static_cast<unsigned char>(~mask);
280 to_next = to;
281 return state.value == 0 ? ok : error;
284 virtual int
285 do_encoding() const throw()
286 { return -1; }
288 virtual bool
289 do_always_noconv() const throw()
290 { return false; }
292 virtual int
293 do_length(state_type& state, const extern_type* from,
294 const extern_type* end, size_t max) const
296 const extern_type* beg = from;
297 while (from < end)
299 unsigned char c = *from;
300 if (c & 0xc0)
302 // Unshift sequence
303 state.value &= c;
304 ++from;
305 continue;
308 if (max == 0) break;
310 unsigned char tmp;
311 if (state.value & 0x8)
313 if (from >= end - 2)
314 break;
315 tmp = (*from++ & 0x7);
316 tmp |= ((*from++ << 3) & 0x38);
317 tmp |= ((*from++ << 6) & 0xc0);
319 else
321 if (from >= end - 1)
322 break;
323 tmp = (*from++ & 0xf);
324 tmp |= ((*from++ << 4) & 0xf0);
326 state.value = tmp;
327 --max;
329 return from - beg;
332 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
333 // one character.
334 virtual int
335 do_max_length() const throw()
336 { return 11; }
339 template<>
340 class ctype<__gnu_test::pod_uchar>
341 : public __ctype_abstract_base<__gnu_test::pod_uchar>
343 public:
344 typedef __gnu_test::pod_uchar char_type;
346 explicit ctype(size_t refs = 0)
347 : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { }
349 static locale::id id;
351 protected:
352 ~ctype()
355 virtual bool
356 do_is(mask, char_type) const
357 { return false; }
359 virtual const char_type*
360 do_is(const char_type* low, const char_type* high, mask* vec) const
362 fill_n(vec, high - low, mask());
363 return high;
366 virtual const char_type*
367 do_scan_is(mask, const char_type*, const char_type* high) const
368 { return high; }
370 virtual const char_type*
371 do_scan_not(mask, const char_type* low, const char_type*) const
372 { return low; }
374 virtual char_type
375 do_toupper(char_type c) const
376 { return c; }
378 virtual const char_type*
379 do_toupper(char_type*, const char_type* high) const
380 { return high; }
382 virtual char_type
383 do_tolower(char_type c) const
384 { return c; }
386 virtual const char_type*
387 do_tolower(char_type*, const char_type* high) const
388 { return high; }
390 virtual char_type
391 do_widen(char c) const
392 { return __gnu_test::pod_uchar::from<char>(c); }
394 virtual const char*
395 do_widen(const char* low, const char* high, char_type* dest) const
397 transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
398 return high;
401 virtual char
402 do_narrow(char_type, char dfault) const
403 { return dfault; }
405 virtual const char_type*
406 do_narrow(const char_type* low, const char_type* high,
407 char dfault, char* dest) const
409 fill_n(dest, high - low, dfault);
410 return high;
414 // numpunct specializations
415 template<>
416 class numpunct<__gnu_test::pod_uint>
417 : public locale::facet
419 public:
420 typedef __gnu_test::pod_uint char_type;
421 typedef basic_string<char_type> string_type;
423 static locale::id id;
425 explicit
426 numpunct(size_t refs = 0)
427 : locale::facet(refs)
428 { }
430 char_type
431 decimal_point() const
432 { return this->do_decimal_point(); }
434 char_type
435 thousands_sep() const
436 { return this->do_thousands_sep(); }
438 string
439 grouping() const
440 { return this->do_grouping(); }
442 string_type
443 truename() const
444 { return this->do_truename(); }
446 string_type
447 falsename() const
448 { return this->do_falsename(); }
450 protected:
451 ~numpunct()
452 { }
454 virtual char_type
455 do_decimal_point() const
456 { return char_type(); }
458 virtual char_type
459 do_thousands_sep() const
460 { return char_type(); }
462 virtual string
463 do_grouping() const
464 { return string(); }
466 virtual string_type
467 do_truename() const
468 { return string_type(); }
470 virtual string_type
471 do_falsename() const
472 { return string_type(); }
475 template<>
476 class moneypunct<__gnu_test::pod_uint>
477 : public locale::facet, public money_base
479 public:
480 typedef __gnu_test::pod_uint char_type;
481 typedef basic_string<char_type> string_type;
483 static locale::id id;
484 static const bool intl = false;
486 explicit
487 moneypunct(size_t refs = 0)
488 : locale::facet(refs)
491 char_type
492 decimal_point() const
493 { return this->do_decimal_point(); }
495 char_type
496 thousands_sep() const
497 { return this->do_thousands_sep(); }
499 string
500 grouping() const
501 { return this->do_grouping(); }
503 string_type
504 curr_symbol() const
505 { return this->do_curr_symbol(); }
507 string_type
508 positive_sign() const
509 { return this->do_positive_sign(); }
511 string_type
512 negative_sign() const
513 { return this->do_negative_sign(); }
516 frac_digits() const
517 { return this->do_frac_digits(); }
519 pattern
520 pos_format() const
521 { return this->do_pos_format(); }
523 pattern
524 neg_format() const
525 { return this->do_neg_format(); }
527 protected:
528 ~moneypunct()
529 { }
531 virtual char_type
532 do_decimal_point() const
533 { return char_type(); }
535 virtual char_type
536 do_thousands_sep() const
537 { return char_type(); }
539 virtual string
540 do_grouping() const
541 { return string(); }
543 virtual string_type
544 do_curr_symbol() const
545 { return string_type(); }
547 string_type
548 do_positive_sign() const
549 { return string_type(); }
551 string_type
552 do_negative_sign() const
553 { return string_type(); }
556 do_frac_digits() const
557 { return 0; }
559 pattern
560 do_pos_format() const
561 { return pattern(); }
563 pattern
564 do_neg_format() const
565 { return pattern(); }
567 } // namespace std
569 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H