3 // Testing character type and state type with char_traits and codecvt
4 // specializations for the C++ library testsuite.
6 // Copyright (C) 2003-2016 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