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, 2008, 2009
7 // Free Software Foundation, Inc.
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)
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
29 #include <string> // for char_traits
30 #include <locale> // for codecvt
31 #include <algorithm> // for transform
32 #include <ext/pod_char_traits.h>
40 #ifdef __GXX_EXPERIMENTAL_CXX0X__
51 // For 20.1 requirements for instantiable type: equality comparable
52 // and less than comparable.
54 operator==(const pod_int
& lhs
, const pod_int
& rhs
)
55 { return lhs
.value
== rhs
.value
; }
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.
64 operator+(const pod_int
& lhs
, const pod_int
& rhs
)
66 pod_int ret
= { lhs
.value
+ rhs
.value
};
71 operator-(const pod_int
& lhs
, const pod_int
& rhs
)
73 pod_int ret
= { lhs
.value
- rhs
.value
};
78 operator*(const pod_int
& lhs
, const pod_int
& rhs
)
80 pod_int ret
= { lhs
.value
* rhs
.value
};
90 operator==(const pod_state
& lhs
, const pod_state
& rhs
)
91 { return lhs
.value
== rhs
.value
; }
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
;
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
) };
119 template<typename V2
>
121 __gnu_test::pod_char::char_type::to(const char_type
& c
)
123 V2 ret
= { c
.value
};
128 template<typename V2
>
129 inline __gnu_test::pod_uchar::char_type
130 __gnu_test::pod_uchar::char_type::from(const V2
& v
)
133 ret
.value
= (v
>> 5);
138 template<typename 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
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
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.
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
>
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
>
175 explicit codecvt(size_t refs
= 0) : base_type(refs
)
178 static locale::id id
;
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)
198 *to
++ = ((tmp
>> 3) & 0x7);
199 *to
++ = ((tmp
>> 6) & 0x3);
203 if (to
>= to_limit
- 1)
206 *to
++ = ((tmp
>> 4) & 0xf);
214 return (from
< from_end
) ? partial
: ok
;
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
;
235 if (state
.value
& 0x8)
237 if (from
>= from_end
- 2)
239 tmp
= (*from
++ & 0x7);
240 tmp
|= ((*from
++ << 3) & 0x38);
241 tmp
|= ((*from
++ << 6) & 0xc0);
245 if (from
>= from_end
- 1)
247 tmp
= (*from
++ & 0xf);
248 tmp
|= ((*from
++ << 4) & 0xf0);
250 to
->value
= (tmp
^ state
.value
);
257 return (from
< from_end
) ? partial
: ok
;
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
)
275 state
.value
&= ~mask
;
276 *to
++ = static_cast<unsigned char>(~mask
);
281 return state
.value
== 0 ? ok
: error
;
285 do_encoding() const throw()
289 do_always_noconv() const throw()
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
;
299 unsigned char c
= *from
;
311 if (state
.value
& 0x8)
315 tmp
= (*from
++ & 0x7);
316 tmp
|= ((*from
++ << 3) & 0x38);
317 tmp
|= ((*from
++ << 6) & 0xc0);
323 tmp
= (*from
++ & 0xf);
324 tmp
|= ((*from
++ << 4) & 0xf0);
332 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
335 do_max_length() const throw()
340 class ctype
<__gnu_test::pod_uchar
>
341 : public __ctype_abstract_base
<__gnu_test::pod_uchar
>
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
;
356 do_is(mask
, char_type
) const
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());
366 virtual const char_type
*
367 do_scan_is(mask
, const char_type
*, const char_type
* high
) const
370 virtual const char_type
*
371 do_scan_not(mask
, const char_type
* low
, const char_type
*) const
375 do_toupper(char_type c
) const
378 virtual const char_type
*
379 do_toupper(char_type
*, const char_type
* high
) const
383 do_tolower(char_type c
) const
386 virtual const char_type
*
387 do_tolower(char_type
*, const char_type
* high
) const
391 do_widen(char c
) const
392 { return __gnu_test::pod_uchar::from
<char>(c
); }
395 do_widen(const char* low
, const char* high
, char_type
* dest
) const
397 transform(low
, high
, dest
, &__gnu_test::pod_uchar::from
<char>);
402 do_narrow(char_type
, char dfault
) const
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
);
414 // numpunct specializations
416 class numpunct
<__gnu_test::pod_uint
>
417 : public locale::facet
420 typedef __gnu_test::pod_uint char_type
;
421 typedef basic_string
<char_type
> string_type
;
423 static locale::id id
;
426 numpunct(size_t refs
= 0)
427 : locale::facet(refs
)
431 decimal_point() const
432 { return this->do_decimal_point(); }
435 thousands_sep() const
436 { return this->do_thousands_sep(); }
440 { return this->do_grouping(); }
444 { return this->do_truename(); }
448 { return this->do_falsename(); }
455 do_decimal_point() const
456 { return char_type(); }
459 do_thousands_sep() const
460 { return char_type(); }
468 { return string_type(); }
472 { return string_type(); }
476 class moneypunct
<__gnu_test::pod_uint
>
477 : public locale::facet
, public money_base
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;
487 moneypunct(size_t refs
= 0)
488 : locale::facet(refs
)
492 decimal_point() const
493 { return this->do_decimal_point(); }
496 thousands_sep() const
497 { return this->do_thousands_sep(); }
501 { return this->do_grouping(); }
505 { return this->do_curr_symbol(); }
508 positive_sign() const
509 { return this->do_positive_sign(); }
512 negative_sign() const
513 { return this->do_negative_sign(); }
517 { return this->do_frac_digits(); }
521 { return this->do_pos_format(); }
525 { return this->do_neg_format(); }
532 do_decimal_point() const
533 { return char_type(); }
536 do_thousands_sep() const
537 { return char_type(); }
544 do_curr_symbol() const
545 { return string_type(); }
548 do_positive_sign() const
549 { return string_type(); }
552 do_negative_sign() const
553 { return string_type(); }
556 do_frac_digits() const
560 do_pos_format() const
561 { return pattern(); }
564 do_neg_format() const
565 { return pattern(); }
569 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H