3 // Testing character type and state type with char_traits and codecvt
4 // specializations for the C++ library testsuite.
6 // Copyright (C) 2003-2013 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 3, 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 COPYING3. If not see
21 // <http://www.gnu.org/licenses/>.
24 #ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
25 #define _GLIBCXX_TESTSUITE_CHARACTER_H
28 #include <string> // for char_traits
29 #include <locale> // for codecvt
30 #include <algorithm> // for transform
31 #include <ext/pod_char_traits.h>
39 #if __cplusplus >= 201103L
50 // For 20.1 requirements for instantiable type: equality comparable
51 // and less than comparable.
53 operator==(const pod_int& lhs, const pod_int& rhs)
54 { return lhs.value == rhs.value; }
57 operator<(const pod_int& lhs, const pod_int& rhs)
58 { return lhs.value < rhs.value; }
60 // For 26 numeric algorithms requirements, need addable,
61 // subtractable, multiplicable.
63 operator+(const pod_int& lhs, const pod_int& rhs)
65 pod_int ret = { lhs.value + rhs.value };
70 operator-(const pod_int& lhs, const pod_int& rhs)
72 pod_int ret = { lhs.value - rhs.value };
77 operator*(const pod_int& lhs, const pod_int& rhs)
79 pod_int ret = { lhs.value * rhs.value };
89 operator==(const pod_state& lhs, const pod_state& rhs)
90 { return lhs.value == rhs.value; }
93 operator<(const pod_state& lhs, const pod_state& rhs)
94 { return lhs.value < rhs.value; }
96 // Alternate character types.
97 using __gnu_cxx::character;
98 typedef character<unsigned char, pod_int, pod_state> pod_char;
99 typedef character<unsigned char, unsigned int, pod_state> pod_uchar;
100 typedef character<unsigned short, unsigned int> pod_ushort;
101 typedef character<unsigned int, unsigned long> pod_uint;
109 template<typename V2>
110 inline __gnu_test::pod_char::char_type
111 __gnu_test::pod_char::char_type::from(const V2& v)
113 char_type ret = { static_cast<value_type>(v.value) };
118 template<typename V2>
120 __gnu_test::pod_char::char_type::to(const char_type& c)
122 V2 ret = { c.value };
127 template<typename V2>
128 inline __gnu_test::pod_uchar::char_type
129 __gnu_test::pod_uchar::char_type::from(const V2& v)
132 ret.value = (v >> 5);
137 template<typename V2>
139 __gnu_test::pod_uchar::char_type::to(const char_type& c)
140 { return static_cast<V2>(c.value << 5); }
141 } // namespace __gnu_test
145 // codecvt specialization
147 // The conversion performed by the specialization is not supposed to
148 // be useful, rather it has been designed to demonstrate the
149 // essential features of stateful conversions:
150 // * Number and value of bytes for each internal character depends on the
151 // state in addition to the character itself.
152 // * Unshift produces an unshift sequence and resets the state. On input
153 // the unshift sequence causes the state to be reset.
155 // The conversion for output is as follows:
156 // 1. Calculate the value tmp by xor-ing the state and the internal
158 // 2. Split tmp into either two or three bytes depending on the value of
159 // state. Output those bytes.
160 // 3. tmp becomes the new value of state.
162 class codecvt<__gnu_test::pod_uchar, char, __gnu_test::pod_state>
163 : public __codecvt_abstract_base<__gnu_test::pod_uchar, char,
164 __gnu_test::pod_state>
167 typedef codecvt_base::result result;
168 typedef __gnu_test::pod_uchar intern_type;
169 typedef char extern_type;
170 typedef __gnu_test::pod_state state_type;
171 typedef __codecvt_abstract_base<intern_type, extern_type, state_type>
174 explicit codecvt(size_t refs = 0) : base_type(refs)
177 static locale::id id;
184 do_out(state_type& state, const intern_type* from,
185 const intern_type* from_end, const intern_type*& from_next,
186 extern_type* to, extern_type* to_limit,
187 extern_type*& to_next) const
189 while (from < from_end && to < to_limit)
191 unsigned char tmp = (state.value ^ from->value);
192 if (state.value & 0x8)
194 if (to >= to_limit - 2)
197 *to++ = ((tmp >> 3) & 0x7);
198 *to++ = ((tmp >> 6) & 0x3);
202 if (to >= to_limit - 1)
205 *to++ = ((tmp >> 4) & 0xf);
213 return (from < from_end) ? partial : ok;
217 do_in(state_type& state, const extern_type* from,
218 const extern_type* from_end, const extern_type*& from_next,
219 intern_type* to, intern_type* to_limit,
220 intern_type*& to_next) const
222 while (from < from_end && to < to_limit)
224 unsigned char c = *from;
234 if (state.value & 0x8)
236 if (from >= from_end - 2)
238 tmp = (*from++ & 0x7);
239 tmp |= ((*from++ << 3) & 0x38);
240 tmp |= ((*from++ << 6) & 0xc0);
244 if (from >= from_end - 1)
246 tmp = (*from++ & 0xf);
247 tmp |= ((*from++ << 4) & 0xf0);
249 to->value = (tmp ^ state.value);
256 return (from < from_end) ? partial : ok;
260 do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
261 extern_type*& to_next) const
263 for (unsigned int i = 0; i < CHAR_BIT; ++i)
265 unsigned int mask = (1 << i);
266 if (state.value & mask)
274 state.value &= ~mask;
275 *to++ = static_cast<unsigned char>(~mask);
280 return state.value == 0 ? ok : error;
284 do_encoding() const throw()
288 do_always_noconv() const throw()
292 do_length(state_type& state, const extern_type* from,
293 const extern_type* end, size_t max) const
295 const extern_type* beg = from;
298 unsigned char c = *from;
310 if (state.value & 0x8)
314 tmp = (*from++ & 0x7);
315 tmp |= ((*from++ << 3) & 0x38);
316 tmp |= ((*from++ << 6) & 0xc0);
322 tmp = (*from++ & 0xf);
323 tmp |= ((*from++ << 4) & 0xf0);
331 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
334 do_max_length() const throw()
339 class ctype<__gnu_test::pod_uchar>
340 : public __ctype_abstract_base<__gnu_test::pod_uchar>
343 typedef __gnu_test::pod_uchar char_type;
345 explicit ctype(size_t refs = 0)
346 : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { }
348 static locale::id id;
355 do_is(mask, char_type) const
358 virtual const char_type*
359 do_is(const char_type* low, const char_type* high, mask* vec) const
361 fill_n(vec, high - low, mask());
365 virtual const char_type*
366 do_scan_is(mask, const char_type*, const char_type* high) const
369 virtual const char_type*
370 do_scan_not(mask, const char_type* low, const char_type*) const
374 do_toupper(char_type c) const
377 virtual const char_type*
378 do_toupper(char_type*, const char_type* high) const
382 do_tolower(char_type c) const
385 virtual const char_type*
386 do_tolower(char_type*, const char_type* high) const
390 do_widen(char c) const
391 { return __gnu_test::pod_uchar::from<char>(c); }
394 do_widen(const char* low, const char* high, char_type* dest) const
396 transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
401 do_narrow(char_type, char dfault) const
404 virtual const char_type*
405 do_narrow(const char_type* low, const char_type* high,
406 char dfault, char* dest) const
408 fill_n(dest, high - low, dfault);
413 // numpunct specializations
415 class numpunct<__gnu_test::pod_uint>
416 : public locale::facet
419 typedef __gnu_test::pod_uint char_type;
420 typedef basic_string<char_type> string_type;
422 static locale::id id;
425 numpunct(size_t refs = 0)
426 : locale::facet(refs)
430 decimal_point() const
431 { return this->do_decimal_point(); }
434 thousands_sep() const
435 { return this->do_thousands_sep(); }
439 { return this->do_grouping(); }
443 { return this->do_truename(); }
447 { return this->do_falsename(); }
454 do_decimal_point() const
455 { return char_type(); }
458 do_thousands_sep() const
459 { return char_type(); }
467 { return string_type(); }
471 { return string_type(); }
475 class moneypunct<__gnu_test::pod_uint>
476 : public locale::facet, public money_base
479 typedef __gnu_test::pod_uint char_type;
480 typedef basic_string<char_type> string_type;
482 static locale::id id;
483 static const bool intl = false;
486 moneypunct(size_t refs = 0)
487 : locale::facet(refs)
491 decimal_point() const
492 { return this->do_decimal_point(); }
495 thousands_sep() const
496 { return this->do_thousands_sep(); }
500 { return this->do_grouping(); }
504 { return this->do_curr_symbol(); }
507 positive_sign() const
508 { return this->do_positive_sign(); }
511 negative_sign() const
512 { return this->do_negative_sign(); }
516 { return this->do_frac_digits(); }
520 { return this->do_pos_format(); }
524 { return this->do_neg_format(); }
531 do_decimal_point() const
532 { return char_type(); }
535 do_thousands_sep() const
536 { return char_type(); }
543 do_curr_symbol() const
544 { return string_type(); }
547 do_positive_sign() const
548 { return string_type(); }
551 do_negative_sign() const
552 { return string_type(); }
555 do_frac_digits() const
559 do_pos_format() const
560 { return pattern(); }
563 do_neg_format() const
564 { return pattern(); }
568 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H