OSDN Git Service

2005-04-14 Benjamin Kosnik <bkoz@redhat.com>
[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, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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
75   // Specializations.
76   // pod_char
77   template<>
78     template<typename V2>
79       inline pod_char::char_type
80       pod_char::char_type::from(const V2& v)
81       {
82         char_type ret = { static_cast<value_type>(v.value) };
83         return ret;
84       }
85
86   template<>
87     template<typename V2>
88       inline V2
89       pod_char::char_type::to(const char_type& c)
90       {
91         V2 ret = { c.value };
92         return ret;
93       }
94   
95   // pod_uchar
96   template<>
97     template<typename V2>
98       inline pod_uchar::char_type
99       pod_uchar::char_type::from(const V2& v)
100       {
101         char_type ret;
102         ret.value = (v >> 5);
103         return ret;
104       }
105
106   template<>
107     template<typename V2>
108       inline V2
109       pod_uchar::char_type::to(const char_type& c)
110       { return static_cast<V2>(c.value << 5); }
111 }; // namespace __gnu_test
112
113 namespace std
114 {
115   // codecvt specialization
116   //
117   // The conversion performed by the specialization is not supposed to
118   // be useful, rather it has been designed to demonstrate the
119   // essential features of stateful conversions:
120   // * Number and value of bytes for each internal character depends on the
121   //   state in addition to the character itself.
122   // * Unshift produces an unshift sequence and resets the state. On input
123   //   the unshift sequence causes the state to be reset.
124   //
125   // The conversion for output is as follows:
126   // 1. Calculate the value tmp by xor-ing the state and the internal
127   //    character
128   // 2. Split tmp into either two or three bytes depending on the value of
129   //    state. Output those bytes.
130   // 3. tmp becomes the new value of state.
131   template<>
132     class codecvt<__gnu_test::pod_uchar, char, __gnu_test::pod_state>
133     : public __codecvt_abstract_base<__gnu_test::pod_uchar, char, 
134                                      __gnu_test::pod_state>
135     {
136     public:
137       typedef codecvt_base::result      result;
138       typedef __gnu_test::pod_uchar     intern_type;
139       typedef char                      extern_type;
140       typedef __gnu_test::pod_state     state_type;
141       typedef __codecvt_abstract_base<intern_type, extern_type, state_type>
142       base_type;
143
144       explicit codecvt(size_t refs = 0) : base_type(refs)
145       { }
146
147       static locale::id id;
148
149     protected:
150       ~codecvt()
151       { }
152
153       virtual result
154       do_out(state_type& state, const intern_type* from,
155              const intern_type* from_end, const intern_type*& from_next,
156              extern_type* to, extern_type* to_limit,
157              extern_type*& to_next) const
158       {
159         while (from < from_end && to < to_limit)
160           {
161             unsigned char tmp = (state.value ^ from->value);
162             if (state.value & 0x8)
163               {
164                 if (to >= to_limit - 2)
165                   break;
166                 *to++ = (tmp & 0x7);
167                 *to++ = ((tmp >> 3) & 0x7);
168                 *to++ = ((tmp >> 6) & 0x3);
169               }
170             else
171               {
172                 if (to >= to_limit - 1)
173                   break;
174                 *to++ = (tmp & 0xf);
175                 *to++ = ((tmp >> 4) & 0xf);
176               }
177             state.value = tmp;
178             ++from;
179           }
180
181         from_next = from;
182         to_next = to;
183         return (from < from_end) ? partial : ok;
184       }
185
186       virtual result
187       do_in(state_type& state, const extern_type* from,
188             const extern_type* from_end, const extern_type*& from_next,
189             intern_type* to, intern_type* to_limit,
190             intern_type*& to_next) const
191       {
192         while (from < from_end && to < to_limit)
193           {
194             unsigned char c = *from;
195             if (c & 0xc0)
196               {
197                 // Unshift sequence
198                 state.value &= c;
199                 ++from;
200                 continue;
201               }
202
203             unsigned char tmp;
204             if (state.value & 0x8)
205               {
206                 if (from >= from_end - 2)
207                   break;
208                 tmp = (*from++ & 0x7);
209                 tmp |= ((*from++ << 3) & 0x38);
210                 tmp |= ((*from++ << 6) & 0xc0);
211               }
212             else
213               {
214                 if (from >= from_end - 1)
215                   break;
216                 tmp = (*from++ & 0xf);
217                 tmp |= ((*from++ << 4) & 0xf0);
218               }
219             to->value = (tmp ^ state.value);
220             state.value = tmp;
221             ++to;
222           }
223
224         from_next = from;
225         to_next = to;
226         return (from < from_end) ? partial : ok;
227       }
228
229       virtual result
230       do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
231                  extern_type*& to_next) const
232       {
233         for (unsigned int i = 0; i < CHAR_BIT; ++i)
234           {
235             unsigned int mask = (1 << i);
236             if (state.value & mask)
237               {
238                 if (to == to_limit)
239                   {
240                     to_next = to;
241                     return partial;
242                   }
243
244                 state.value &= ~mask;
245                 *to++ = static_cast<unsigned char>(~mask);
246               }
247           }
248
249         to_next = to;
250         return state.value == 0 ? ok : error;
251       }
252
253       virtual int
254       do_encoding() const throw()
255       { return -1; }
256
257       virtual bool
258       do_always_noconv() const throw()
259       { return false; }
260
261       virtual int
262       do_length(state_type& state, const extern_type* from,
263                 const extern_type* end, size_t max) const
264       {
265         const extern_type* beg = from;
266         while (from < end && max)
267           {
268             unsigned char c = *from;
269             if (c & 0xc0)
270               {
271                 // Unshift sequence
272                 state.value &= c;
273                 ++from;
274                 continue;
275               }
276
277             unsigned char tmp;
278             if (state.value & 0x8)
279               {
280                 if (from >= end - 2)
281                   break;
282                 tmp = (*from++ & 0x7);
283                 tmp |= ((*from++ << 3) & 0x38);
284                 tmp |= ((*from++ << 6) & 0xc0);
285               }
286             else
287               {
288                 if (from >= end - 1)
289                   break;
290                 tmp = (*from++ & 0xf);
291                 tmp |= ((*from++ << 4) & 0xf0);
292               }
293             state.value = tmp;
294             --max;
295           }
296         return from - beg;
297       }
298
299       // Maximum 8 bytes unshift sequence followed by max 3 bytes for
300       // one character.
301       virtual int
302       do_max_length() const throw()
303       { return 11; }
304     };
305
306   template<>
307     class ctype<__gnu_test::pod_uchar>
308     : public __ctype_abstract_base<__gnu_test::pod_uchar>
309     {
310     public:
311       typedef __gnu_test::pod_uchar char_type;
312
313       explicit ctype(size_t refs  = 0)
314       : __ctype_abstract_base<__gnu_test::pod_uchar>(refs) { }
315
316       static locale::id id;
317
318     protected:
319       ~ctype()
320       { }
321
322       virtual bool
323       do_is(mask m, char_type c) const
324       { return false; }
325
326       virtual const char_type*
327       do_is(const char_type* low, const char_type* high, mask* vec) const
328       {
329         fill_n(vec, high - low, mask());
330         return high;
331       }
332
333       virtual const char_type*
334       do_scan_is(mask m, const char_type* low, const char_type* high) const
335       { return high; }
336
337       virtual const char_type*
338       do_scan_not(mask m, const char_type* low, const char_type* high) const
339       { return low; }
340
341       virtual char_type
342       do_toupper(char_type c) const
343       { return c; }
344
345       virtual const char_type*
346       do_toupper(char_type*  low, const char_type*  high) const
347       { return high; }
348
349       virtual char_type
350       do_tolower(char_type c) const
351       { return c; }
352
353       virtual const char_type*
354       do_tolower(char_type*  low, const char_type*  high) const
355       { return high; }
356
357       virtual char_type
358       do_widen(char c) const
359       { return __gnu_test::pod_uchar::from<char>(c); }
360
361       virtual const char* 
362       do_widen(const char* low, const char* high, char_type* dest) const
363       {
364         transform(low, high, dest, &__gnu_test::pod_uchar::from<char>);
365         return high;
366       }
367
368       virtual char
369       do_narrow(char_type, char dfault) const
370       { return dfault; }
371
372       virtual const char_type*
373       do_narrow(const char_type* low, const char_type* high,
374                 char dfault, char*  dest) const
375       {
376         fill_n(dest, high - low, dfault);
377         return high;
378       }
379     };
380 } // namespace std
381
382 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H
383