OSDN Git Service

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