OSDN Git Service

2005-04-06 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   // Character type
44   struct character
45   {
46     unsigned char val;
47
48     static character from_char(char c)
49     {
50       character ret;
51       ret.val = c;
52       return ret;
53     }
54   };
55
56   inline bool
57   operator==(const character& lhs, const character& rhs)
58   { return lhs.val == rhs.val; }
59
60   // State type.
61   struct conversion_state
62   {
63     unsigned int state;
64   };
65
66   // Test data types.
67   struct pod_char
68   {
69     unsigned char c;
70   };
71
72   inline bool
73   operator==(const pod_char& lhs, const pod_char& rhs)
74   { return lhs.c == rhs.c; }
75   
76   struct pod_int
77   {
78     int i;
79   };
80   
81   struct state
82   {
83     unsigned long l;
84     unsigned long l2;
85   };
86
87   typedef unsigned short                                value_type;
88   typedef unsigned int                                  int_type;
89   typedef __gnu_cxx::character<value_type, int_type>    pod_type;
90 }; // namespace __gnu_test
91
92 namespace std
93 {
94   // A std::char_traits specialization. Meets the additional
95   // requirements for basic_filebuf.
96   template<>
97     struct char_traits<__gnu_test::character>
98     {
99       typedef __gnu_test::character char_type;
100       typedef unsigned int int_type;
101       typedef __gnu_test::conversion_state state_type;
102       typedef streamoff off_type;
103       typedef fpos<state_type> pos_type;
104
105       static void
106       assign(char_type& c1, const char_type& c2)
107       { c1 = c2; }
108
109       static bool
110       eq(const char_type& c1, const char_type& c2)
111       { return c1.val == c2.val; }
112
113       static bool
114       lt(const char_type& c1, const char_type& c2)
115       { return c1.val < c2.val; }
116
117       static int
118       compare(const char_type* s1, const char_type* s2, size_t n)
119       {
120         for (size_t i = 0; i < n; ++i)
121           {
122             if (lt(s1[i], s2[i]))
123               return -1;
124             else if (lt(s2[i], s1[i]))
125               return 1;
126           }
127         return 0;
128       }
129
130       static size_t
131       length(const char_type* s)
132       {
133         size_t n = 0;
134         while (!eq(s[n], char_type()))
135           ++n;
136         return n;
137       }
138
139       static const char_type*
140       find(const char_type* s, size_t n, const char_type& a)
141       {
142         for (size_t i = 0; i < n; ++i)
143           {
144             if (eq(s[i], a))
145               return s + i;
146           }
147         return NULL;
148       }
149
150       static char_type*
151       move(char_type* s1, const char_type* s2, size_t n)
152       {
153         if (s1 > s2)
154           {
155             for (size_t i = 0; i < n; ++i)
156               assign(s1[n - i - 1], s2[n - i - 1]);
157           }
158         else
159           {
160             for (size_t i = 0; i < n; ++i)
161               assign(s1[i], s2[i]);
162           }
163         return s1;
164       }
165
166       static char_type*
167       copy(char_type* s1, const char_type* s2, size_t n)
168       {
169         for (size_t i = 0; i < n; ++i)
170           assign(s1[i], s2[i]);
171         return s1;
172       }
173
174       static char_type*
175       assign(char_type* s, size_t n, char_type a)
176       {
177         for (size_t i = 0; i < n; ++i)
178           assign(s[i], a);
179         return s;
180       }
181
182       static int_type
183       not_eof(const int_type& c)
184       {
185         if (eq_int_type(c, eof()))
186           return 0;
187         return c;
188       }
189
190       // Note non-trivial conversion to maximize chance of catching bugs
191       static char_type
192       to_char_type(const int_type& c)
193       {
194         char_type ret;
195         ret.val = (c >> 5);
196         return ret;
197       }
198
199       static int_type
200       to_int_type(const char_type& c)
201       {
202         return c.val << 5;
203       }
204
205       static bool
206       eq_int_type(const int_type& c1, const int_type& c2)
207       { return c1 == c2; }
208
209       static int_type eof()
210       { return 0xf; }
211     };
212
213   // codecvt specialization
214   //
215   // The conversion performed by the specialization is not supposed to
216   // be useful, rather it has been designed to demonstrate the
217   // essential features of stateful conversions:
218   // * Number and value of bytes for each internal character depends on the
219   //   state in addition to the character itself.
220   // * Unshift produces an unshift sequence and resets the state. On input
221   //   the unshift sequence causes the state to be reset.
222   //
223   // The conversion for output is as follows:
224   // 1. Calculate the value tmp by xor-ing the state and the internal
225   //    character
226   // 2. Split tmp into either two or three bytes depending on the value of
227   //    state. Output those bytes.
228   // 3. tmp becomes the new value of state.
229   template<>
230     class codecvt<__gnu_test::character, char, __gnu_test::conversion_state>
231       : public locale::facet, public codecvt_base
232     {
233     public:
234       typedef __gnu_test::character intern_type;
235       typedef char extern_type;
236       typedef __gnu_test::conversion_state state_type;
237
238       explicit codecvt(size_t refs = 0)
239       : locale::facet(refs)
240       { }
241
242       result
243       out(state_type& state, const intern_type* from,
244           const intern_type* from_end, const intern_type*& from_next,
245           extern_type* to, extern_type* to_limit, extern_type*& to_next) const
246       {
247         return do_out(state, from, from_end, from_next,
248                       to, to_limit, to_next);
249       }
250
251       result
252       unshift(state_type& state, extern_type* to, extern_type* to_limit,
253               extern_type*& to_next) const
254       { return do_unshift(state, to, to_limit, to_next); }
255
256       result
257       in(state_type& state, const extern_type* from,
258          const extern_type* from_end, const extern_type*& from_next,
259          intern_type* to, intern_type* to_limit, intern_type*& to_next) const
260       {
261         return do_in(state, from, from_end, from_next,
262                      to, to_limit, to_next);
263       }
264
265       int
266       encoding() const throw()
267       { return do_encoding(); }
268
269       bool
270       always_noconv() const throw()
271       { return do_always_noconv(); }
272       
273       int
274       length(state_type& state, const extern_type* from,
275              const extern_type* end, size_t max) const
276       { return do_length(state, from, end, max); }
277       
278       int
279       max_length() const throw()
280       { return do_max_length(); }
281
282       static locale::id id;
283
284     protected:
285       ~codecvt()
286       { }
287
288       virtual result
289       do_out(state_type& state, const intern_type* from,
290              const intern_type* from_end, const intern_type*& from_next,
291              extern_type* to, extern_type* to_limit,
292              extern_type*& to_next) const
293       {
294         while (from < from_end && to < to_limit)
295           {
296             unsigned char tmp = (state.state ^ from->val);
297             if (state.state & 0x8)
298               {
299                 if (to >= to_limit - 2)
300                   break;
301                 *to++ = (tmp & 0x7);
302                 *to++ = ((tmp >> 3) & 0x7);
303                 *to++ = ((tmp >> 6) & 0x3);
304               }
305             else
306               {
307                 if (to >= to_limit - 1)
308                   break;
309                 *to++ = (tmp & 0xf);
310                 *to++ = ((tmp >> 4) & 0xf);
311               }
312             state.state = tmp;
313             ++from;
314           }
315
316         from_next = from;
317         to_next = to;
318         return (from < from_end) ? partial : ok;
319       }
320
321       virtual result
322       do_in(state_type& state, const extern_type* from,
323             const extern_type* from_end, const extern_type*& from_next,
324             intern_type* to, intern_type* to_limit,
325             intern_type*& to_next) const
326       {
327         while (from < from_end && to < to_limit)
328           {
329             unsigned char c = *from;
330             if (c & 0xc0)
331               {
332                 // Unshift sequence
333                 state.state &= c;
334                 ++from;
335                 continue;
336               }
337
338             unsigned char tmp;
339             if (state.state & 0x8)
340               {
341                 if (from >= from_end - 2)
342                   break;
343                 tmp = (*from++ & 0x7);
344                 tmp |= ((*from++ << 3) & 0x38);
345                 tmp |= ((*from++ << 6) & 0xc0);
346               }
347             else
348               {
349                 if (from >= from_end - 1)
350                   break;
351                 tmp = (*from++ & 0xf);
352                 tmp |= ((*from++ << 4) & 0xf0);
353               }
354             to->val = (tmp ^ state.state);
355             state.state = tmp;
356             ++to;
357           }
358
359         from_next = from;
360         to_next = to;
361         return (from < from_end) ? partial : ok;
362       }
363
364       virtual result
365       do_unshift(state_type& state, extern_type* to, extern_type* to_limit,
366                  extern_type*& to_next) const
367       {
368         for (unsigned int i = 0; i < CHAR_BIT; ++i)
369           {
370             unsigned int mask = (1 << i);
371             if (state.state & mask)
372               {
373                 if (to == to_limit)
374                   {
375                     to_next = to;
376                     return partial;
377                   }
378
379                 state.state &= ~mask;
380                 *to++ = static_cast<unsigned char>(~mask);
381               }
382           }
383
384         to_next = to;
385         return state.state == 0 ? ok : error;
386       }
387
388       virtual int
389       do_encoding() const throw()
390       { return -1; }
391
392       virtual bool
393       do_always_noconv() const throw()
394       { return false; }
395
396       virtual int
397       do_length(state_type& state, const extern_type* from,
398                 const extern_type* end, size_t max) const
399       {
400         const extern_type* beg = from;
401         while (from < end && max)
402           {
403             unsigned char c = *from;
404             if (c & 0xc0)
405               {
406                 // Unshift sequence
407                 state.state &= c;
408                 ++from;
409                 continue;
410               }
411
412             unsigned char tmp;
413             if (state.state & 0x8)
414               {
415                 if (from >= end - 2)
416                   break;
417                 tmp = (*from++ & 0x7);
418                 tmp |= ((*from++ << 3) & 0x38);
419                 tmp |= ((*from++ << 6) & 0xc0);
420               }
421             else
422               {
423                 if (from >= end - 1)
424                   break;
425                 tmp = (*from++ & 0xf);
426                 tmp |= ((*from++ << 4) & 0xf0);
427               }
428             state.state = tmp;
429             --max;
430           }
431         return from - beg;
432       }
433
434       // Maximum 8 bytes unshift sequence followed by max 3 bytes for
435       // one character.
436       virtual int
437       do_max_length() const throw()
438       { return 11; }
439     };
440
441
442   // A std::char_traits specialization with POD types for char_type,
443   // int_type, and state_type.
444   template<>
445     struct char_traits<__gnu_test::pod_char>
446     {
447       typedef __gnu_test::pod_char      char_type;
448       typedef __gnu_test::pod_int       int_type;
449       typedef __gnu_test::state         state_type;
450       typedef fpos<state_type>          pos_type;
451       typedef streamoff                 off_type;
452       
453       static void 
454       assign(char_type& c1, const char_type& c2)
455       { c1.c = c2.c; }
456
457       static bool 
458       eq(const char_type& c1, const char_type& c2)
459       { return c1.c == c2.c; }
460
461       static bool 
462       lt(const char_type& c1, const char_type& c2)
463       { return c1.c < c2.c; }
464
465       static int 
466       compare(const char_type* s1, const char_type* s2, size_t n)
467       { return memcmp(s1, s2, n); }
468
469       static size_t
470       length(const char_type* s)
471       { return strlen(reinterpret_cast<const char*>(s)); }
472
473       static const char_type* 
474       find(const char_type* s, size_t n, const char_type& a)
475       { return static_cast<const char_type*>(memchr(s, a.c, n)); }
476
477       static char_type* 
478       move(char_type* s1, const char_type* s2, size_t n)
479       {
480         memmove(s1, s2, n);
481         return s1;
482       }
483
484       static char_type* 
485       copy(char_type* s1, const char_type* s2, size_t n)
486       {
487         memcpy(s1, s2, n);
488         return s1;
489       }
490
491       static char_type* 
492       assign(char_type* s, size_t n, char_type a)
493       {
494         memset(s, a.c, n);
495         return s;
496       }
497
498       static char_type 
499       to_char_type(const int_type& c)
500       {
501         char_type ret;
502         ret.c = static_cast<unsigned char>(c.i);
503         return ret;
504       }
505
506       static int_type 
507       to_int_type(const char_type& c)
508       {
509         int_type ret;
510         ret.i = c.c;
511         return ret;
512       }
513
514       static bool 
515       eq_int_type(const int_type& c1, const int_type& c2)
516       { return c1.i == c2.i; }
517
518       static int_type 
519       eof()
520       {
521         int_type n;
522         n.i = -10;
523         return n;
524       }
525
526       static int_type 
527       not_eof(const int_type& c)
528       {
529         if (eq_int_type(c, eof()))
530           return int_type();
531         return c;
532       }
533     };
534 } // namespace std
535
536 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H
537