]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/util/testsuite_character.h
Update copyright years in libstdc++-v3/
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / util / testsuite_character.h
1 // -*- C++ -*-
2
3 // Testing character type and state type with char_traits and codecvt
4 // specializations for the C++ library testsuite.
5 //
6 // Copyright (C) 2003-2014 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.
13 //
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.
18 //
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/>.
22 //
23
24 #ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
25 #define _GLIBCXX_TESTSUITE_CHARACTER_H
26
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>
32
33 namespace __gnu_test
34 {
35 struct pod_int
36 {
37 int value;
38
39 #if __cplusplus >= 201103L
40 // For std::iota.
41 pod_int&
42 operator++()
43 {
44 ++value;
45 return *this;
46 }
47 #endif
48 };
49
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; }
55
56 inline bool
57 operator<(const pod_int& lhs, const pod_int& rhs)
58 { return lhs.value < rhs.value; }
59
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)
64 {
65 pod_int ret = { lhs.value + rhs.value };
66 return ret;
67 }
68
69 inline pod_int
70 operator-(const pod_int& lhs, const pod_int& rhs)
71 {
72 pod_int ret = { lhs.value - rhs.value };
73 return ret;
74 }
75
76 inline pod_int
77 operator*(const pod_int& lhs, const pod_int& rhs)
78 {
79 pod_int ret = { lhs.value * rhs.value };
80 return ret;
81 }
82
83 struct pod_state
84 {
85 unsigned long value;
86 };
87
88 inline bool
89 operator==(const pod_state& lhs, const pod_state& rhs)
90 { return lhs.value == rhs.value; }
91
92 inline bool
93 operator<(const pod_state& lhs, const pod_state& rhs)
94 { return lhs.value < rhs.value; }
95
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;
102 }
103
104 namespace __gnu_cxx
105 {
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)
112 {
113 char_type ret = { static_cast<value_type>(v.value) };
114 return ret;
115 }
116
117 template<>
118 template<typename V2>
119 inline V2
120 __gnu_test::pod_char::char_type::to(const char_type& c)
121 {
122 V2 ret = { c.value };
123 return ret;
124 }
125
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)
130 {
131 char_type ret;
132 ret.value = (v >> 5);
133 return ret;
134 }
135
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
142
143 namespace std
144 {
145 // codecvt specialization
146 //
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.
154 //
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>
165 {
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;
173
174 explicit codecvt(size_t refs = 0) : base_type(refs)
175 { }
176
177 static locale::id id;
178
179 protected:
180 ~codecvt()
181 { }
182
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
188 {
189 while (from < from_end && to < to_limit)
190 {
191 unsigned char tmp = (state.value ^ from->value);
192 if (state.value & 0x8)
193 {
194 if (to >= to_limit - 2)
195 break;
196 *to++ = (tmp & 0x7);
197 *to++ = ((tmp >> 3) & 0x7);
198 *to++ = ((tmp >> 6) & 0x3);
199 }
200 else
201 {
202 if (to >= to_limit - 1)
203 break;
204 *to++ = (tmp & 0xf);
205 *to++ = ((tmp >> 4) & 0xf);
206 }
207 state.value = tmp;
208 ++from;
209 }
210
211 from_next = from;
212 to_next = to;
213 return (from < from_end) ? partial : ok;
214 }
215
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
221 {
222 while (from < from_end && to < to_limit)
223 {
224 unsigned char c = *from;
225 if (c & 0xc0)
226 {
227 // Unshift sequence
228 state.value &= c;
229 ++from;
230 continue;
231 }
232
233 unsigned char tmp;
234 if (state.value & 0x8)
235 {
236 if (from >= from_end - 2)
237 break;
238 tmp = (*from++ & 0x7);
239 tmp |= ((*from++ << 3) & 0x38);
240 tmp |= ((*from++ << 6) & 0xc0);
241 }
242 else
243 {
244 if (from >= from_end - 1)
245 break;
246 tmp = (*from++ & 0xf);
247 tmp |= ((*from++ << 4) & 0xf0);
248 }
249 to->value = (tmp ^ state.value);
250 state.value = tmp;
251 ++to;
252 }
253
254 from_next = from;
255 to_next = to;
256 return (from < from_end) ? partial : ok;
257 }
258
259 virtual result
260 do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
261 extern_type*& to_next) const
262 {
263 for (unsigned int i = 0; i < CHAR_BIT; ++i)
264 {
265 unsigned int mask = (1 << i);
266 if (state.value & mask)
267 {
268 if (to == to_limit)
269 {
270 to_next = to;
271 return partial;
272 }
273
274 state.value &= ~mask;
275 *to++ = static_cast<unsigned char>(~mask);
276 }
277 }
278
279 to_next = to;
280 return state.value == 0 ? ok : error;
281 }
282
283 virtual int
284 do_encoding() const throw()
285 { return -1; }
286
287 virtual bool
288 do_always_noconv() const throw()
289 { return false; }
290
291 virtual int
292 do_length(state_type& state, const extern_type* from,
293 const extern_type* end, size_t max) const
294 {
295 const extern_type* beg = from;
296 while (from < end)
297 {
298 unsigned char c = *from;
299 if (c & 0xc0)
300 {
301 // Unshift sequence
302 state.value &= c;
303 ++from;
304 continue;
305 }
306
307 if (max == 0) break;
308
309 unsigned char tmp;
310 if (state.value & 0x8)
311 {
312 if (from >= end - 2)
313 break;
314 tmp = (*from++ & 0x7);
315 tmp |= ((*from++ << 3) & 0x38);
316 tmp |= ((*from++ << 6) & 0xc0);
317 }
318 else
319 {
320 if (from >= end - 1)
321 break;
322 tmp = (*from++ & 0xf);
323 tmp |= ((*from++ << 4) & 0xf0);
324 }
325 state.value = tmp;
326 --max;
327 }
328 return from - beg;
329 }
330
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; }
336 };
337
338 template<>
339 class ctype<__gnu_test::pod_uchar>
340 : public __ctype_abstract_base<__gnu_test::pod_uchar>
341 {
342 public:
343 typedef __gnu_test::pod_uchar char_type;
344
345 explicit ctype(size_t refs = 0)
346 : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { }
347
348 static locale::id id;
349
350 protected:
351 ~ctype()
352 { }
353
354 virtual bool
355 do_is(mask, char_type) const
356 { return false; }
357
358 virtual const char_type*
359 do_is(const char_type* low, const char_type* high, mask* vec) const
360 {
361 fill_n(vec, high - low, mask());
362 return high;
363 }
364
365 virtual const char_type*
366 do_scan_is(mask, const char_type*, const char_type* high) const
367 { return high; }
368
369 virtual const char_type*
370 do_scan_not(mask, const char_type* low, const char_type*) const
371 { return low; }
372
373 virtual char_type
374 do_toupper(char_type c) const
375 { return c; }
376
377 virtual const char_type*
378 do_toupper(char_type*, const char_type* high) const
379 { return high; }
380
381 virtual char_type
382 do_tolower(char_type c) const
383 { return c; }
384
385 virtual const char_type*
386 do_tolower(char_type*, const char_type* high) const
387 { return high; }
388
389 virtual char_type
390 do_widen(char c) const
391 { return __gnu_test::pod_uchar::from<char>(c); }
392
393 virtual const char*
394 do_widen(const char* low, const char* high, char_type* dest) const
395 {
396 transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
397 return high;
398 }
399
400 virtual char
401 do_narrow(char_type, char dfault) const
402 { return dfault; }
403
404 virtual const char_type*
405 do_narrow(const char_type* low, const char_type* high,
406 char dfault, char* dest) const
407 {
408 fill_n(dest, high - low, dfault);
409 return high;
410 }
411 };
412
413 // numpunct specializations
414 template<>
415 class numpunct<__gnu_test::pod_uint>
416 : public locale::facet
417 {
418 public:
419 typedef __gnu_test::pod_uint char_type;
420 typedef basic_string<char_type> string_type;
421
422 static locale::id id;
423
424 explicit
425 numpunct(size_t refs = 0)
426 : locale::facet(refs)
427 { }
428
429 char_type
430 decimal_point() const
431 { return this->do_decimal_point(); }
432
433 char_type
434 thousands_sep() const
435 { return this->do_thousands_sep(); }
436
437 string
438 grouping() const
439 { return this->do_grouping(); }
440
441 string_type
442 truename() const
443 { return this->do_truename(); }
444
445 string_type
446 falsename() const
447 { return this->do_falsename(); }
448
449 protected:
450 ~numpunct()
451 { }
452
453 virtual char_type
454 do_decimal_point() const
455 { return char_type(); }
456
457 virtual char_type
458 do_thousands_sep() const
459 { return char_type(); }
460
461 virtual string
462 do_grouping() const
463 { return string(); }
464
465 virtual string_type
466 do_truename() const
467 { return string_type(); }
468
469 virtual string_type
470 do_falsename() const
471 { return string_type(); }
472 };
473
474 template<>
475 class moneypunct<__gnu_test::pod_uint>
476 : public locale::facet, public money_base
477 {
478 public:
479 typedef __gnu_test::pod_uint char_type;
480 typedef basic_string<char_type> string_type;
481
482 static locale::id id;
483 static const bool intl = false;
484
485 explicit
486 moneypunct(size_t refs = 0)
487 : locale::facet(refs)
488 { }
489
490 char_type
491 decimal_point() const
492 { return this->do_decimal_point(); }
493
494 char_type
495 thousands_sep() const
496 { return this->do_thousands_sep(); }
497
498 string
499 grouping() const
500 { return this->do_grouping(); }
501
502 string_type
503 curr_symbol() const
504 { return this->do_curr_symbol(); }
505
506 string_type
507 positive_sign() const
508 { return this->do_positive_sign(); }
509
510 string_type
511 negative_sign() const
512 { return this->do_negative_sign(); }
513
514 int
515 frac_digits() const
516 { return this->do_frac_digits(); }
517
518 pattern
519 pos_format() const
520 { return this->do_pos_format(); }
521
522 pattern
523 neg_format() const
524 { return this->do_neg_format(); }
525
526 protected:
527 ~moneypunct()
528 { }
529
530 virtual char_type
531 do_decimal_point() const
532 { return char_type(); }
533
534 virtual char_type
535 do_thousands_sep() const
536 { return char_type(); }
537
538 virtual string
539 do_grouping() const
540 { return string(); }
541
542 virtual string_type
543 do_curr_symbol() const
544 { return string_type(); }
545
546 string_type
547 do_positive_sign() const
548 { return string_type(); }
549
550 string_type
551 do_negative_sign() const
552 { return string_type(); }
553
554 int
555 do_frac_digits() const
556 { return 0; }
557
558 pattern
559 do_pos_format() const
560 { return pattern(); }
561
562 pattern
563 do_neg_format() const
564 { return pattern(); }
565 };
566 } // namespace std
567
568 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H
569