2 // Testing character type and state type with char_traits and codecvt
3 // specializations for the C++ library testsuite.
5 // Copyright (C) 2003 Free Software Foundation, Inc.
7 // This file is part of the GNU ISO C++ Library. This library is free
8 // software; you can redistribute it and/or modify it under the
9 // terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 2, or (at your option)
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License along
19 // with this library; see the file COPYING. If not, write to the Free
20 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23 // As a special exception, you may use this file as part of a free software
24 // library without restriction. Specifically, if other files instantiate
25 // templates or use macros or inline functions from this file, or you compile
26 // this file and link it with other files to produce an executable, this
27 // file does not by itself cause the resulting executable to be covered by
28 // the GNU General Public License. This exception does not however
29 // invalidate any other reasons why the executable file might be covered by
30 // the GNU General Public License.
32 #ifndef _GLIBCXX_TESTSUITE_CHARACTER_H
33 #define _GLIBCXX_TESTSUITE_CHARACTER_H
35 #include <string> // for char_traits
36 #include <locale> // for codecvt
46 static character
from_char(char c
)
55 operator==(const character
& lhs
, const character
& rhs
)
56 { return lhs
.val
== rhs
.val
; }
59 struct conversion_state
63 }; // namespace __gnu_test
67 // char_traits specialization. Meets the additional requirements for
70 struct char_traits
<__gnu_test::character
>
72 typedef __gnu_test::character char_type
;
73 typedef unsigned int int_type
;
74 typedef __gnu_test::conversion_state state_type
;
75 typedef streamoff off_type
;
76 typedef fpos
<state_type
> pos_type
;
79 assign(char_type
& c1
, const char_type
& c2
)
83 eq(const char_type
& c1
, const char_type
& c2
)
84 { return c1
.val
== c2
.val
; }
87 lt(const char_type
& c1
, const char_type
& c2
)
88 { return c1
.val
< c2
.val
; }
91 compare(const char_type
* s1
, const char_type
* s2
, size_t n
)
93 for (size_t i
= 0; i
< n
; ++i
)
97 else if (lt(s2
[i
], s1
[i
]))
104 length(const char_type
* s
)
107 while (!eq(s
[n
], char_type()))
112 static const char_type
*
113 find(const char_type
* s
, size_t n
, const char_type
& a
)
115 for (size_t i
= 0; i
< n
; ++i
)
124 move(char_type
* s1
, const char_type
* s2
, size_t n
)
128 for (size_t i
= 0; i
< n
; ++i
)
129 assign(s1
[n
- i
- 1], s2
[n
- i
- 1]);
133 for (size_t i
= 0; i
< n
; ++i
)
134 assign(s1
[i
], s2
[i
]);
140 copy(char_type
* s1
, const char_type
* s2
, size_t n
)
142 for (size_t i
= 0; i
< n
; ++i
)
143 assign(s1
[i
], s2
[i
]);
148 assign(char_type
* s
, size_t n
, char_type a
)
150 for (size_t i
= 0; i
< n
; ++i
)
156 not_eof(const int_type
& c
)
158 if (eq_int_type(c
, eof()))
163 // Note non-trivial conversion to maximize chance of catching bugs
165 to_char_type(const int_type
& c
)
173 to_int_type(const char_type
& c
)
179 eq_int_type(const int_type
& c1
, const int_type
& c2
)
182 static int_type
eof()
186 // codecvt specialization
188 // The conversion performed by the specialization is not supposed to
189 // be useful, rather it has been designed to demonstrate the
190 // essential features of stateful conversions:
191 // * Number and value of bytes for each internal character depends on the
192 // state in addition to the character itself.
193 // * Unshift produces an unshift sequence and resets the state. On input
194 // the unshift sequence causes the state to be reset.
196 // The conversion for output is as follows:
197 // 1. Calculate the value tmp by xor-ing the state and the internal
199 // 2. Split tmp into either two or three bytes depending on the value of
200 // state. Output those bytes.
201 // 3. tmp becomes the new value of state.
203 class codecvt
<__gnu_test::character
, char, __gnu_test::conversion_state
>
204 : public locale::facet
, public codecvt_base
207 typedef __gnu_test::character intern_type
;
208 typedef char extern_type
;
209 typedef __gnu_test::conversion_state state_type
;
211 explicit codecvt(size_t refs
= 0)
212 : locale::facet(refs
)
216 out(state_type
& state
, const intern_type
* from
,
217 const intern_type
* from_end
, const intern_type
*& from_next
,
218 extern_type
* to
, extern_type
* to_limit
, extern_type
*& to_next
) const
220 return do_out(state
, from
, from_end
, from_next
,
221 to
, to_limit
, to_next
);
225 unshift(state_type
& state
, extern_type
* to
, extern_type
* to_limit
,
226 extern_type
*& to_next
) const
227 { return do_unshift(state
, to
, to_limit
, to_next
); }
230 in(state_type
& state
, const extern_type
* from
,
231 const extern_type
* from_end
, const extern_type
*& from_next
,
232 intern_type
* to
, intern_type
* to_limit
, intern_type
*& to_next
) const
234 return do_in(state
, from
, from_end
, from_next
,
235 to
, to_limit
, to_next
);
239 encoding() const throw()
240 { return do_encoding(); }
243 always_noconv() const throw()
244 { return do_always_noconv(); }
247 length(state_type
& state
, const extern_type
* from
,
248 const extern_type
* end
, size_t max
) const
249 { return do_length(state
, from
, end
, max
); }
252 max_length() const throw()
253 { return do_max_length(); }
255 static locale::id id
;
262 do_out(state_type
& state
, const intern_type
* from
,
263 const intern_type
* from_end
, const intern_type
*& from_next
,
264 extern_type
* to
, extern_type
* to_limit
,
265 extern_type
*& to_next
) const
267 while (from
< from_end
&& to
< to_limit
)
269 unsigned char tmp
= (state
.state
^ from
->val
);
270 if (state
.state
& 0x8)
272 if (to
>= to_limit
- 2)
275 *to
++ = ((tmp
>> 3) & 0x7);
276 *to
++ = ((tmp
>> 6) & 0x3);
280 if (to
>= to_limit
- 1)
283 *to
++ = ((tmp
>> 4) & 0xf);
291 return (from
< from_end
) ? partial
: ok
;
295 do_in(state_type
& state
, const extern_type
* from
,
296 const extern_type
* from_end
, const extern_type
*& from_next
,
297 intern_type
* to
, intern_type
* to_limit
,
298 intern_type
*& to_next
) const
300 while (from
< from_end
&& to
< to_limit
)
302 unsigned char c
= *from
;
312 if (state
.state
& 0x8)
314 if (from
>= from_end
- 2)
316 tmp
= (*from
++ & 0x7);
317 tmp
|= ((*from
++ << 3) & 0x38);
318 tmp
|= ((*from
++ << 6) & 0xc0);
322 if (from
>= from_end
- 1)
324 tmp
= (*from
++ & 0xf);
325 tmp
|= ((*from
++ << 4) & 0xf0);
327 to
->val
= (tmp
^ state
.state
);
334 return (from
< from_end
) ? partial
: ok
;
338 do_unshift(state_type
& state
, extern_type
* to
, extern_type
* to_limit
,
339 extern_type
*& to_next
) const
341 for (unsigned int i
= 0; i
< CHAR_BIT
; ++i
)
343 unsigned int mask
= (1 << i
);
344 if (state
.state
& mask
)
352 state
.state
&= ~mask
;
353 *to
++ = static_cast<unsigned char>(~mask
);
358 return state
.state
== 0 ? ok
: error
;
362 do_encoding() const throw()
366 do_always_noconv() const throw()
370 do_length(state_type
& state
, const extern_type
* from
,
371 const extern_type
* end
, size_t max
) const
373 const extern_type
* beg
= from
;
374 while (from
< end
&& max
)
376 unsigned char c
= *from
;
386 if (state
.state
& 0x8)
390 tmp
= (*from
++ & 0x7);
391 tmp
|= ((*from
++ << 3) & 0x38);
392 tmp
|= ((*from
++ << 6) & 0xc0);
398 tmp
= (*from
++ & 0xf);
399 tmp
|= ((*from
++ << 4) & 0xf0);
407 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
410 do_max_length() const throw()
415 codecvt
<__gnu_test::character
, char, __gnu_test::conversion_state
>::id
;
418 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H