function: Restructure *logue insertion
[official-gcc.git] / libstdc++-v3 / testsuite / util / testsuite_character.h
blobedada36e7d6eed9b9f59324cdc687ac94337a00b
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-2016 Free Software Foundation, Inc.
7 //
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)
12 // any later version.
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
27 #include <climits>
28 #include <string> // for char_traits
29 #include <locale> // for codecvt
30 #include <algorithm> // for transform
31 #include <ext/pod_char_traits.h>
33 namespace __gnu_test
35 struct pod_int
37 int value;
39 #if __cplusplus >= 201103L
40 // For std::iota.
41 pod_int&
42 operator++()
44 ++value;
45 return *this;
47 #endif
50 // For 20.1 requirements for instantiable type: equality comparable
51 // and less than comparable.
52 inline bool
53 operator==(const pod_int& lhs, const pod_int& rhs)
54 { return lhs.value == rhs.value; }
56 inline bool
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.
62 inline pod_int
63 operator+(const pod_int& lhs, const pod_int& rhs)
65 pod_int ret = { lhs.value + rhs.value };
66 return ret;
69 inline pod_int
70 operator-(const pod_int& lhs, const pod_int& rhs)
72 pod_int ret = { lhs.value - rhs.value };
73 return ret;
76 inline pod_int
77 operator*(const pod_int& lhs, const pod_int& rhs)
79 pod_int ret = { lhs.value * rhs.value };
80 return ret;
83 struct pod_state
85 unsigned long value;
88 inline bool
89 operator==(const pod_state& lhs, const pod_state& rhs)
90 { return lhs.value == rhs.value; }
92 inline bool
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;
104 namespace __gnu_cxx
106 // Specializations.
107 // pod_char
108 template<>
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) };
114 return ret;
117 template<>
118 template<typename V2>
119 inline V2
120 __gnu_test::pod_char::char_type::to(const char_type& c)
122 V2 ret = { c.value };
123 return ret;
126 template<>
127 template<typename V2>
128 inline __gnu_test::pod_uchar::char_type
129 __gnu_test::pod_uchar::char_type::from(const V2& v)
131 char_type ret;
132 ret.value = (v >> 5);
133 return ret;
136 template<>
137 template<typename V2>
138 inline 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
143 namespace std
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
157 // character
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.
161 template<>
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>
166 public:
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>
172 base_type;
174 explicit codecvt(size_t refs = 0) : base_type(refs)
177 static locale::id id;
179 protected:
180 ~codecvt()
183 virtual result
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)
195 break;
196 *to++ = (tmp & 0x7);
197 *to++ = ((tmp >> 3) & 0x7);
198 *to++ = ((tmp >> 6) & 0x3);
200 else
202 if (to >= to_limit - 1)
203 break;
204 *to++ = (tmp & 0xf);
205 *to++ = ((tmp >> 4) & 0xf);
207 state.value = tmp;
208 ++from;
211 from_next = from;
212 to_next = to;
213 return (from < from_end) ? partial : ok;
216 virtual result
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;
225 if (c & 0xc0)
227 // Unshift sequence
228 state.value &= c;
229 ++from;
230 continue;
233 unsigned char tmp;
234 if (state.value & 0x8)
236 if (from >= from_end - 2)
237 break;
238 tmp = (*from++ & 0x7);
239 tmp |= ((*from++ << 3) & 0x38);
240 tmp |= ((*from++ << 6) & 0xc0);
242 else
244 if (from >= from_end - 1)
245 break;
246 tmp = (*from++ & 0xf);
247 tmp |= ((*from++ << 4) & 0xf0);
249 to->value = (tmp ^ state.value);
250 state.value = tmp;
251 ++to;
254 from_next = from;
255 to_next = to;
256 return (from < from_end) ? partial : ok;
259 virtual result
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)
268 if (to == to_limit)
270 to_next = to;
271 return partial;
274 state.value &= ~mask;
275 *to++ = static_cast<unsigned char>(~mask);
279 to_next = to;
280 return state.value == 0 ? ok : error;
283 virtual int
284 do_encoding() const throw()
285 { return -1; }
287 virtual bool
288 do_always_noconv() const throw()
289 { return false; }
291 virtual int
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;
296 while (from < end)
298 unsigned char c = *from;
299 if (c & 0xc0)
301 // Unshift sequence
302 state.value &= c;
303 ++from;
304 continue;
307 if (max == 0) break;
309 unsigned char tmp;
310 if (state.value & 0x8)
312 if (from >= end - 2)
313 break;
314 tmp = (*from++ & 0x7);
315 tmp |= ((*from++ << 3) & 0x38);
316 tmp |= ((*from++ << 6) & 0xc0);
318 else
320 if (from >= end - 1)
321 break;
322 tmp = (*from++ & 0xf);
323 tmp |= ((*from++ << 4) & 0xf0);
325 state.value = tmp;
326 --max;
328 return from - beg;
331 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
332 // one character.
333 virtual int
334 do_max_length() const throw()
335 { return 11; }
338 template<>
339 class ctype<__gnu_test::pod_uchar>
340 : public __ctype_abstract_base<__gnu_test::pod_uchar>
342 public:
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;
350 protected:
351 ~ctype()
354 virtual bool
355 do_is(mask, char_type) const
356 { return false; }
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());
362 return high;
365 virtual const char_type*
366 do_scan_is(mask, const char_type*, const char_type* high) const
367 { return high; }
369 virtual const char_type*
370 do_scan_not(mask, const char_type* low, const char_type*) const
371 { return low; }
373 virtual char_type
374 do_toupper(char_type c) const
375 { return c; }
377 virtual const char_type*
378 do_toupper(char_type*, const char_type* high) const
379 { return high; }
381 virtual char_type
382 do_tolower(char_type c) const
383 { return c; }
385 virtual const char_type*
386 do_tolower(char_type*, const char_type* high) const
387 { return high; }
389 virtual char_type
390 do_widen(char c) const
391 { return __gnu_test::pod_uchar::from<char>(c); }
393 virtual const char*
394 do_widen(const char* low, const char* high, char_type* dest) const
396 transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
397 return high;
400 virtual char
401 do_narrow(char_type, char dfault) const
402 { return dfault; }
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);
409 return high;
413 // numpunct specializations
414 template<>
415 class numpunct<__gnu_test::pod_uint>
416 : public locale::facet
418 public:
419 typedef __gnu_test::pod_uint char_type;
420 typedef basic_string<char_type> string_type;
422 static locale::id id;
424 explicit
425 numpunct(size_t refs = 0)
426 : locale::facet(refs)
429 char_type
430 decimal_point() const
431 { return this->do_decimal_point(); }
433 char_type
434 thousands_sep() const
435 { return this->do_thousands_sep(); }
437 string
438 grouping() const
439 { return this->do_grouping(); }
441 string_type
442 truename() const
443 { return this->do_truename(); }
445 string_type
446 falsename() const
447 { return this->do_falsename(); }
449 protected:
450 ~numpunct()
453 virtual char_type
454 do_decimal_point() const
455 { return char_type(); }
457 virtual char_type
458 do_thousands_sep() const
459 { return char_type(); }
461 virtual string
462 do_grouping() const
463 { return string(); }
465 virtual string_type
466 do_truename() const
467 { return string_type(); }
469 virtual string_type
470 do_falsename() const
471 { return string_type(); }
474 template<>
475 class moneypunct<__gnu_test::pod_uint>
476 : public locale::facet, public money_base
478 public:
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;
485 explicit
486 moneypunct(size_t refs = 0)
487 : locale::facet(refs)
490 char_type
491 decimal_point() const
492 { return this->do_decimal_point(); }
494 char_type
495 thousands_sep() const
496 { return this->do_thousands_sep(); }
498 string
499 grouping() const
500 { return this->do_grouping(); }
502 string_type
503 curr_symbol() const
504 { return this->do_curr_symbol(); }
506 string_type
507 positive_sign() const
508 { return this->do_positive_sign(); }
510 string_type
511 negative_sign() const
512 { return this->do_negative_sign(); }
515 frac_digits() const
516 { return this->do_frac_digits(); }
518 pattern
519 pos_format() const
520 { return this->do_pos_format(); }
522 pattern
523 neg_format() const
524 { return this->do_neg_format(); }
526 protected:
527 ~moneypunct()
530 virtual char_type
531 do_decimal_point() const
532 { return char_type(); }
534 virtual char_type
535 do_thousands_sep() const
536 { return char_type(); }
538 virtual string
539 do_grouping() const
540 { return string(); }
542 virtual string_type
543 do_curr_symbol() const
544 { return string_type(); }
546 string_type
547 do_positive_sign() const
548 { return string_type(); }
550 string_type
551 do_negative_sign() const
552 { return string_type(); }
555 do_frac_digits() const
556 { return 0; }
558 pattern
559 do_pos_format() const
560 { return pattern(); }
562 pattern
563 do_neg_format() const
564 { return pattern(); }
566 } // namespace std
568 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H