OSDN Git Service

* Makefile.tpl (BUILD_CONFIGDIRS): Remove
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / testsuite / 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, 2005 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 <ext/pod_char_traits.h>
40
41 namespace __gnu_test
42 {  
43   struct pod_int
44   {
45     int value;
46   };
47   
48   inline bool
49   operator==(const pod_int& lhs, const pod_int& rhs)
50   { return lhs.value == rhs.value; }
51   
52   inline bool
53   operator<(const pod_int& lhs, const pod_int& rhs)
54   { return lhs.value < rhs.value; }
55
56   struct pod_state
57   {
58     unsigned long value;
59   };
60
61   inline bool
62   operator==(const pod_state& lhs, const pod_state& rhs)
63   { return lhs.value == rhs.value; }
64
65   inline bool
66   operator<(const pod_state& lhs, const pod_state& rhs)
67   { return lhs.value < rhs.value; }
68
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;
74   typedef character<unsigned int, unsigned long>                pod_uint;  
75 }
76
77 namespace __gnu_cxx 
78 {
79   // Specializations.
80   // pod_char
81   template<>
82     template<typename V2>
83       inline __gnu_test::pod_char::char_type
84       __gnu_test::pod_char::char_type::from(const V2& v)
85       {
86         char_type ret = { static_cast<value_type>(v.value) };
87         return ret;
88       }
89
90   template<>
91     template<typename V2>
92       inline V2
93       __gnu_test::pod_char::char_type::to(const char_type& c)
94       {
95         V2 ret = { c.value };
96         return ret;
97       }
98   
99   template<>
100     template<typename V2>
101       inline __gnu_test::pod_uchar::char_type
102       __gnu_test::pod_uchar::char_type::from(const V2& v)
103       {
104         char_type ret;
105         ret.value = (v >> 5);
106         return ret;
107       }
108
109   template<>
110     template<typename V2>
111       inline V2
112       __gnu_test::pod_uchar::char_type::to(const char_type& c)
113       { return static_cast<V2>(c.value << 5); }
114 }; // namespace __gnu_test
115
116 namespace std
117 {
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<>
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>
138     {
139     public:
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)
148       { }
149
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           {
164             unsigned char tmp = (state.value ^ from->value);
165             if (state.value & 0x8)
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               }
180             state.value = tmp;
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
201                 state.value &= c;
202                 ++from;
203                 continue;
204               }
205
206             unsigned char tmp;
207             if (state.value & 0x8)
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               }
222             to->value = (tmp ^ state.value);
223             state.value = tmp;
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);
239             if (state.value & mask)
240               {
241                 if (to == to_limit)
242                   {
243                     to_next = to;
244                     return partial;
245                   }
246
247                 state.value &= ~mask;
248                 *to++ = static_cast<unsigned char>(~mask);
249               }
250           }
251
252         to_next = to;
253         return state.value == 0 ? ok : error;
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
275                 state.value &= c;
276                 ++from;
277                 continue;
278               }
279
280             unsigned char tmp;
281             if (state.value & 0x8)
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               }
296             state.value = tmp;
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
309   template<>
310     class ctype<__gnu_test::pod_uchar>
311     : public __ctype_abstract_base<__gnu_test::pod_uchar>
312     {
313     public:
314       typedef __gnu_test::pod_uchar char_type;
315
316       explicit ctype(size_t refs  = 0)
317       : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { }
318
319       static locale::id id;
320
321     protected:
322       ~ctype()
323       { }
324
325       virtual bool
326       do_is(mask, char_type) const
327       { return false; }
328
329       virtual const char_type*
330       do_is(const char_type* low, const char_type* high, mask* vec) const
331       {
332         fill_n(vec, high - low, mask());
333         return high;
334       }
335
336       virtual const char_type*
337       do_scan_is(mask, const char_type*, const char_type* high) const
338       { return high; }
339
340       virtual const char_type*
341       do_scan_not(mask, const char_type* low, const char_type*) const
342       { return low; }
343
344       virtual char_type
345       do_toupper(char_type c) const
346       { return c; }
347
348       virtual const char_type*
349       do_toupper(char_type*, const char_type*  high) const
350       { return high; }
351
352       virtual char_type
353       do_tolower(char_type c) const
354       { return c; }
355
356       virtual const char_type*
357       do_tolower(char_type*, const char_type*  high) const
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
366       {
367         transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
368         return high;
369       }
370
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
378       {
379         fill_n(dest, high - low, dfault);
380         return high;
381       }
382     };
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      };
537 } // namespace std
538
539 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H
540