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