]>
Commit | Line | Data |
---|---|---|
5e93f39f | 1 | // -*- C++ -*- |
5305b1ae | 2 | |
5e93f39f PR |
3 | // Testing character type and state type with char_traits and codecvt |
4 | // specializations for the C++ library testsuite. | |
5 | // | |
5305b1ae | 6 | // Copyright (C) 2003, 2005 Free Software Foundation, Inc. |
5e93f39f PR |
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 2, 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 COPYING. If not, write to the Free | |
83f51799 | 21 | // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
5e93f39f PR |
22 | // USA. |
23 | // | |
24 | // As a special exception, you may use this file as part of a free software | |
25 | // library without restriction. Specifically, if other files instantiate | |
26 | // templates or use macros or inline functions from this file, or you compile | |
27 | // this file and link it with other files to produce an executable, this | |
28 | // file does not by itself cause the resulting executable to be covered by | |
29 | // the GNU General Public License. This exception does not however | |
30 | // invalidate any other reasons why the executable file might be covered by | |
31 | // the GNU General Public License. | |
32 | ||
33 | #ifndef _GLIBCXX_TESTSUITE_CHARACTER_H | |
34 | #define _GLIBCXX_TESTSUITE_CHARACTER_H | |
35 | ||
5305b1ae | 36 | #include <climits> |
5e93f39f PR |
37 | #include <string> // for char_traits |
38 | #include <locale> // for codecvt | |
5305b1ae | 39 | #include <ext/pod_char_traits.h> |
5e93f39f PR |
40 | |
41 | namespace __gnu_test | |
42 | { | |
821503db | 43 | struct pod_int |
5e93f39f | 44 | { |
821503db | 45 | int value; |
5e93f39f | 46 | }; |
821503db BK |
47 | |
48 | inline bool | |
49 | operator==(const pod_int& lhs, const pod_int& rhs) | |
50 | { return lhs.value == rhs.value; } | |
51 | ||
ce345590 | 52 | inline bool |
821503db BK |
53 | operator<(const pod_int& lhs, const pod_int& rhs) |
54 | { return lhs.value < rhs.value; } | |
ce345590 | 55 | |
821503db | 56 | struct pod_state |
5e93f39f | 57 | { |
821503db | 58 | unsigned long value; |
5e93f39f | 59 | }; |
5305b1ae | 60 | |
821503db BK |
61 | inline bool |
62 | operator==(const pod_state& lhs, const pod_state& rhs) | |
63 | { return lhs.value == rhs.value; } | |
5305b1ae BK |
64 | |
65 | inline bool | |
821503db BK |
66 | operator<(const pod_state& lhs, const pod_state& rhs) |
67 | { return lhs.value < rhs.value; } | |
5305b1ae | 68 | |
821503db BK |
69 | // Alternate character types. |
70 | using __gnu_cxx::character; | |
71 | typedef character<unsigned char, pod_int, pod_state> pod_char; | |
72 | typedef character<unsigned char, unsigned int, pod_state> pod_uchar; | |
73 | typedef character<unsigned short, unsigned int> pod_ushort; | |
a70c902e | 74 | typedef character<unsigned int, unsigned long> pod_uint; |
9c12301f | 75 | } |
5e93f39f | 76 | |
3cbc7af0 BK |
77 | namespace __gnu_cxx |
78 | { | |
821503db BK |
79 | // Specializations. |
80 | // pod_char | |
5e93f39f | 81 | template<> |
821503db | 82 | template<typename V2> |
9c12301f MM |
83 | inline __gnu_test::pod_char::char_type |
84 | __gnu_test::pod_char::char_type::from(const V2& v) | |
5e93f39f | 85 | { |
821503db BK |
86 | char_type ret = { static_cast<value_type>(v.value) }; |
87 | return ret; | |
5e93f39f PR |
88 | } |
89 | ||
821503db BK |
90 | template<> |
91 | template<typename V2> | |
92 | inline V2 | |
9c12301f | 93 | __gnu_test::pod_char::char_type::to(const char_type& c) |
5e93f39f | 94 | { |
821503db BK |
95 | V2 ret = { c.value }; |
96 | return ret; | |
5e93f39f | 97 | } |
821503db | 98 | |
821503db BK |
99 | template<> |
100 | template<typename V2> | |
9c12301f MM |
101 | inline __gnu_test::pod_uchar::char_type |
102 | __gnu_test::pod_uchar::char_type::from(const V2& v) | |
5e93f39f PR |
103 | { |
104 | char_type ret; | |
821503db | 105 | ret.value = (v >> 5); |
5e93f39f PR |
106 | return ret; |
107 | } | |
108 | ||
821503db BK |
109 | template<> |
110 | template<typename V2> | |
111 | inline V2 | |
9c12301f | 112 | __gnu_test::pod_uchar::char_type::to(const char_type& c) |
821503db BK |
113 | { return static_cast<V2>(c.value << 5); } |
114 | }; // namespace __gnu_test | |
5e93f39f | 115 | |
821503db BK |
116 | namespace std |
117 | { | |
5e93f39f PR |
118 | // codecvt specialization |
119 | // | |
120 | // The conversion performed by the specialization is not supposed to | |
121 | // be useful, rather it has been designed to demonstrate the | |
122 | // essential features of stateful conversions: | |
123 | // * Number and value of bytes for each internal character depends on the | |
124 | // state in addition to the character itself. | |
125 | // * Unshift produces an unshift sequence and resets the state. On input | |
126 | // the unshift sequence causes the state to be reset. | |
127 | // | |
128 | // The conversion for output is as follows: | |
129 | // 1. Calculate the value tmp by xor-ing the state and the internal | |
130 | // character | |
131 | // 2. Split tmp into either two or three bytes depending on the value of | |
132 | // state. Output those bytes. | |
133 | // 3. tmp becomes the new value of state. | |
134 | template<> | |
821503db BK |
135 | class codecvt<__gnu_test::pod_uchar, char, __gnu_test::pod_state> |
136 | : public __codecvt_abstract_base<__gnu_test::pod_uchar, char, | |
137 | __gnu_test::pod_state> | |
5e93f39f PR |
138 | { |
139 | public: | |
821503db BK |
140 | typedef codecvt_base::result result; |
141 | typedef __gnu_test::pod_uchar intern_type; | |
142 | typedef char extern_type; | |
143 | typedef __gnu_test::pod_state state_type; | |
144 | typedef __codecvt_abstract_base<intern_type, extern_type, state_type> | |
145 | base_type; | |
146 | ||
147 | explicit codecvt(size_t refs = 0) : base_type(refs) | |
5e93f39f PR |
148 | { } |
149 | ||
5e93f39f PR |
150 | static locale::id id; |
151 | ||
152 | protected: | |
153 | ~codecvt() | |
154 | { } | |
155 | ||
156 | virtual result | |
157 | do_out(state_type& state, const intern_type* from, | |
158 | const intern_type* from_end, const intern_type*& from_next, | |
159 | extern_type* to, extern_type* to_limit, | |
160 | extern_type*& to_next) const | |
161 | { | |
162 | while (from < from_end && to < to_limit) | |
163 | { | |
821503db BK |
164 | unsigned char tmp = (state.value ^ from->value); |
165 | if (state.value & 0x8) | |
5e93f39f PR |
166 | { |
167 | if (to >= to_limit - 2) | |
168 | break; | |
169 | *to++ = (tmp & 0x7); | |
170 | *to++ = ((tmp >> 3) & 0x7); | |
171 | *to++ = ((tmp >> 6) & 0x3); | |
172 | } | |
173 | else | |
174 | { | |
175 | if (to >= to_limit - 1) | |
176 | break; | |
177 | *to++ = (tmp & 0xf); | |
178 | *to++ = ((tmp >> 4) & 0xf); | |
179 | } | |
821503db | 180 | state.value = tmp; |
5e93f39f PR |
181 | ++from; |
182 | } | |
183 | ||
184 | from_next = from; | |
185 | to_next = to; | |
186 | return (from < from_end) ? partial : ok; | |
187 | } | |
188 | ||
189 | virtual result | |
190 | do_in(state_type& state, const extern_type* from, | |
191 | const extern_type* from_end, const extern_type*& from_next, | |
192 | intern_type* to, intern_type* to_limit, | |
193 | intern_type*& to_next) const | |
194 | { | |
195 | while (from < from_end && to < to_limit) | |
196 | { | |
197 | unsigned char c = *from; | |
198 | if (c & 0xc0) | |
199 | { | |
200 | // Unshift sequence | |
821503db | 201 | state.value &= c; |
5e93f39f PR |
202 | ++from; |
203 | continue; | |
204 | } | |
205 | ||
206 | unsigned char tmp; | |
821503db | 207 | if (state.value & 0x8) |
5e93f39f PR |
208 | { |
209 | if (from >= from_end - 2) | |
210 | break; | |
211 | tmp = (*from++ & 0x7); | |
212 | tmp |= ((*from++ << 3) & 0x38); | |
213 | tmp |= ((*from++ << 6) & 0xc0); | |
214 | } | |
215 | else | |
216 | { | |
217 | if (from >= from_end - 1) | |
218 | break; | |
219 | tmp = (*from++ & 0xf); | |
220 | tmp |= ((*from++ << 4) & 0xf0); | |
221 | } | |
821503db BK |
222 | to->value = (tmp ^ state.value); |
223 | state.value = tmp; | |
5e93f39f PR |
224 | ++to; |
225 | } | |
226 | ||
227 | from_next = from; | |
228 | to_next = to; | |
229 | return (from < from_end) ? partial : ok; | |
230 | } | |
231 | ||
232 | virtual result | |
233 | do_unshift(state_type& state, extern_type* to, extern_type* to_limit, | |
234 | extern_type*& to_next) const | |
235 | { | |
236 | for (unsigned int i = 0; i < CHAR_BIT; ++i) | |
237 | { | |
238 | unsigned int mask = (1 << i); | |
821503db | 239 | if (state.value & mask) |
5e93f39f PR |
240 | { |
241 | if (to == to_limit) | |
242 | { | |
243 | to_next = to; | |
244 | return partial; | |
245 | } | |
246 | ||
821503db | 247 | state.value &= ~mask; |
5e93f39f PR |
248 | *to++ = static_cast<unsigned char>(~mask); |
249 | } | |
250 | } | |
251 | ||
252 | to_next = to; | |
821503db | 253 | return state.value == 0 ? ok : error; |
5e93f39f PR |
254 | } |
255 | ||
256 | virtual int | |
257 | do_encoding() const throw() | |
258 | { return -1; } | |
259 | ||
260 | virtual bool | |
261 | do_always_noconv() const throw() | |
262 | { return false; } | |
263 | ||
264 | virtual int | |
265 | do_length(state_type& state, const extern_type* from, | |
266 | const extern_type* end, size_t max) const | |
267 | { | |
268 | const extern_type* beg = from; | |
269 | while (from < end && max) | |
270 | { | |
271 | unsigned char c = *from; | |
272 | if (c & 0xc0) | |
273 | { | |
274 | // Unshift sequence | |
821503db | 275 | state.value &= c; |
5e93f39f PR |
276 | ++from; |
277 | continue; | |
278 | } | |
279 | ||
280 | unsigned char tmp; | |
821503db | 281 | if (state.value & 0x8) |
5e93f39f PR |
282 | { |
283 | if (from >= end - 2) | |
284 | break; | |
285 | tmp = (*from++ & 0x7); | |
286 | tmp |= ((*from++ << 3) & 0x38); | |
287 | tmp |= ((*from++ << 6) & 0xc0); | |
288 | } | |
289 | else | |
290 | { | |
291 | if (from >= end - 1) | |
292 | break; | |
293 | tmp = (*from++ & 0xf); | |
294 | tmp |= ((*from++ << 4) & 0xf0); | |
295 | } | |
821503db | 296 | state.value = tmp; |
5e93f39f PR |
297 | --max; |
298 | } | |
299 | return from - beg; | |
300 | } | |
301 | ||
302 | // Maximum 8 bytes unshift sequence followed by max 3 bytes for | |
303 | // one character. | |
304 | virtual int | |
305 | do_max_length() const throw() | |
306 | { return 11; } | |
307 | }; | |
308 | ||
5305b1ae | 309 | template<> |
821503db BK |
310 | class ctype<__gnu_test::pod_uchar> |
311 | : public __ctype_abstract_base<__gnu_test::pod_uchar> | |
5305b1ae | 312 | { |
821503db BK |
313 | public: |
314 | typedef __gnu_test::pod_uchar char_type; | |
5305b1ae | 315 | |
821503db BK |
316 | explicit ctype(size_t refs = 0) |
317 | : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { } | |
5305b1ae | 318 | |
821503db | 319 | static locale::id id; |
5305b1ae | 320 | |
821503db BK |
321 | protected: |
322 | ~ctype() | |
323 | { } | |
5305b1ae | 324 | |
821503db | 325 | virtual bool |
8b5bc374 | 326 | do_is(mask, char_type) const |
821503db BK |
327 | { return false; } |
328 | ||
329 | virtual const char_type* | |
330 | do_is(const char_type* low, const char_type* high, mask* vec) const | |
5305b1ae | 331 | { |
821503db BK |
332 | fill_n(vec, high - low, mask()); |
333 | return high; | |
5305b1ae BK |
334 | } |
335 | ||
821503db | 336 | virtual const char_type* |
8b5bc374 | 337 | do_scan_is(mask, const char_type*, const char_type* high) const |
821503db BK |
338 | { return high; } |
339 | ||
340 | virtual const char_type* | |
8b5bc374 | 341 | do_scan_not(mask, const char_type* low, const char_type*) const |
821503db BK |
342 | { return low; } |
343 | ||
344 | virtual char_type | |
345 | do_toupper(char_type c) const | |
346 | { return c; } | |
5305b1ae | 347 | |
821503db | 348 | virtual const char_type* |
8b5bc374 | 349 | do_toupper(char_type*, const char_type* high) const |
821503db BK |
350 | { return high; } |
351 | ||
352 | virtual char_type | |
353 | do_tolower(char_type c) const | |
354 | { return c; } | |
355 | ||
356 | virtual const char_type* | |
8b5bc374 | 357 | do_tolower(char_type*, const char_type* high) const |
821503db BK |
358 | { return high; } |
359 | ||
360 | virtual char_type | |
361 | do_widen(char c) const | |
362 | { return __gnu_test::pod_uchar::from<char>(c); } | |
363 | ||
364 | virtual const char* | |
365 | do_widen(const char* low, const char* high, char_type* dest) const | |
5305b1ae | 366 | { |
821503db BK |
367 | transform(low, high, dest, &__gnu_test::pod_uchar::from<char>); |
368 | return high; | |
5305b1ae BK |
369 | } |
370 | ||
821503db BK |
371 | virtual char |
372 | do_narrow(char_type, char dfault) const | |
373 | { return dfault; } | |
374 | ||
375 | virtual const char_type* | |
376 | do_narrow(const char_type* low, const char_type* high, | |
377 | char dfault, char* dest) const | |
5305b1ae | 378 | { |
821503db BK |
379 | fill_n(dest, high - low, dfault); |
380 | return high; | |
5305b1ae BK |
381 | } |
382 | }; | |
a70c902e PC |
383 | |
384 | // numpunct specializations | |
385 | template<> | |
386 | class numpunct<__gnu_test::pod_uint> | |
387 | : public locale::facet | |
388 | { | |
389 | public: | |
390 | typedef __gnu_test::pod_uint char_type; | |
391 | typedef basic_string<char_type> string_type; | |
392 | ||
393 | static locale::id id; | |
394 | ||
395 | explicit | |
396 | numpunct(size_t refs = 0) | |
397 | : locale::facet(refs) | |
398 | { } | |
399 | ||
400 | char_type | |
401 | decimal_point() const | |
402 | { return this->do_decimal_point(); } | |
403 | ||
404 | char_type | |
405 | thousands_sep() const | |
406 | { return this->do_thousands_sep(); } | |
407 | ||
408 | string | |
409 | grouping() const | |
410 | { return this->do_grouping(); } | |
411 | ||
412 | string_type | |
413 | truename() const | |
414 | { return this->do_truename(); } | |
415 | ||
416 | string_type | |
417 | falsename() const | |
418 | { return this->do_falsename(); } | |
419 | ||
420 | protected: | |
421 | ~numpunct() | |
422 | { } | |
423 | ||
424 | virtual char_type | |
425 | do_decimal_point() const | |
426 | { return char_type(); } | |
427 | ||
428 | virtual char_type | |
429 | do_thousands_sep() const | |
430 | { return char_type(); } | |
431 | ||
432 | virtual string | |
433 | do_grouping() const | |
434 | { return string(); } | |
435 | ||
436 | virtual string_type | |
437 | do_truename() const | |
438 | { return string_type(); } | |
439 | ||
440 | virtual string_type | |
441 | do_falsename() const | |
442 | { return string_type(); } | |
443 | }; | |
444 | ||
445 | template<> | |
446 | class moneypunct<__gnu_test::pod_uint> | |
447 | : public locale::facet, public money_base | |
448 | { | |
449 | public: | |
450 | typedef __gnu_test::pod_uint char_type; | |
451 | typedef basic_string<char_type> string_type; | |
452 | ||
453 | static locale::id id; | |
454 | static const bool intl = false; | |
455 | ||
456 | explicit | |
457 | moneypunct(size_t refs = 0) | |
458 | : locale::facet(refs) | |
459 | { } | |
460 | ||
461 | char_type | |
462 | decimal_point() const | |
463 | { return this->do_decimal_point(); } | |
464 | ||
465 | char_type | |
466 | thousands_sep() const | |
467 | { return this->do_thousands_sep(); } | |
468 | ||
469 | string | |
470 | grouping() const | |
471 | { return this->do_grouping(); } | |
472 | ||
473 | string_type | |
474 | curr_symbol() const | |
475 | { return this->do_curr_symbol(); } | |
476 | ||
477 | string_type | |
478 | positive_sign() const | |
479 | { return this->do_positive_sign(); } | |
480 | ||
481 | string_type | |
482 | negative_sign() const | |
483 | { return this->do_negative_sign(); } | |
484 | ||
485 | int | |
486 | frac_digits() const | |
487 | { return this->do_frac_digits(); } | |
488 | ||
489 | pattern | |
490 | pos_format() const | |
491 | { return this->do_pos_format(); } | |
492 | ||
493 | pattern | |
494 | neg_format() const | |
495 | { return this->do_neg_format(); } | |
496 | ||
497 | protected: | |
498 | ~moneypunct() | |
499 | { } | |
500 | ||
501 | virtual char_type | |
502 | do_decimal_point() const | |
503 | { return char_type(); } | |
504 | ||
505 | virtual char_type | |
506 | do_thousands_sep() const | |
507 | { return char_type(); } | |
508 | ||
509 | virtual string | |
510 | do_grouping() const | |
511 | { return string(); } | |
512 | ||
513 | virtual string_type | |
514 | do_curr_symbol() const | |
515 | { return string_type(); } | |
516 | ||
517 | string_type | |
518 | do_positive_sign() const | |
519 | { return string_type(); } | |
520 | ||
521 | string_type | |
522 | do_negative_sign() const | |
523 | { return string_type(); } | |
524 | ||
525 | int | |
526 | do_frac_digits() const | |
527 | { return 0; } | |
528 | ||
529 | pattern | |
530 | do_pos_format() const | |
531 | { return pattern(); } | |
532 | ||
533 | pattern | |
534 | do_neg_format() const | |
535 | { return pattern(); } | |
536 | }; | |
5e93f39f PR |
537 | } // namespace std |
538 | ||
539 | #endif // _GLIBCXX_TESTSUITE_CHARACTER_H | |
540 |