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 struct conversion_state
59 }; // namespace __gnu_test
63 // char_traits specialization. Meets the additional requirements for
66 struct char_traits
<__gnu_test::character
>
68 typedef __gnu_test::character char_type
;
69 typedef unsigned int int_type
;
70 typedef __gnu_test::conversion_state state_type
;
71 typedef streamoff off_type
;
72 typedef fpos
<state_type
> pos_type
;
75 assign(char_type
& c1
, const char_type
& c2
)
79 eq(const char_type
& c1
, const char_type
& c2
)
80 { return c1
.val
== c2
.val
; }
83 lt(const char_type
& c1
, const char_type
& c2
)
84 { return c1
.val
< c2
.val
; }
87 compare(const char_type
* s1
, const char_type
* s2
, size_t n
)
89 for (size_t i
= 0; i
< n
; ++i
)
93 else if (lt(s2
[i
], s1
[i
]))
100 length(const char_type
* s
)
103 while (!eq(s
[n
], char_type()))
108 static const char_type
*
109 find(const char_type
* s
, size_t n
, const char_type
& a
)
111 for (size_t i
= 0; i
< n
; ++i
)
120 move(char_type
* s1
, const char_type
* s2
, size_t n
)
124 for (size_t i
= 0; i
< n
; ++i
)
125 assign(s1
[n
- i
- 1], s2
[n
- i
- 1]);
129 for (size_t i
= 0; i
< n
; ++i
)
130 assign(s1
[i
], s2
[i
]);
136 copy(char_type
* s1
, const char_type
* s2
, size_t n
)
138 for (size_t i
= 0; i
< n
; ++i
)
139 assign(s1
[i
], s2
[i
]);
144 assign(char_type
* s
, size_t n
, char_type a
)
146 for (size_t i
= 0; i
< n
; ++i
)
152 not_eof(const int_type
& c
)
154 if (eq_int_type(c
, eof()))
159 // Note non-trivial conversion to maximize chance of catching bugs
161 to_char_type(const int_type
& c
)
169 to_int_type(const char_type
& c
)
175 eq_int_type(const int_type
& c1
, const int_type
& c2
)
178 static int_type
eof()
182 // codecvt specialization
184 // The conversion performed by the specialization is not supposed to
185 // be useful, rather it has been designed to demonstrate the
186 // essential features of stateful conversions:
187 // * Number and value of bytes for each internal character depends on the
188 // state in addition to the character itself.
189 // * Unshift produces an unshift sequence and resets the state. On input
190 // the unshift sequence causes the state to be reset.
192 // The conversion for output is as follows:
193 // 1. Calculate the value tmp by xor-ing the state and the internal
195 // 2. Split tmp into either two or three bytes depending on the value of
196 // state. Output those bytes.
197 // 3. tmp becomes the new value of state.
199 class codecvt
<__gnu_test::character
, char, __gnu_test::conversion_state
>
200 : public locale::facet
, public codecvt_base
203 typedef __gnu_test::character intern_type
;
204 typedef char extern_type
;
205 typedef __gnu_test::conversion_state state_type
;
207 explicit codecvt(size_t refs
= 0)
208 : locale::facet(refs
)
212 out(state_type
& state
, const intern_type
* from
,
213 const intern_type
* from_end
, const intern_type
*& from_next
,
214 extern_type
* to
, extern_type
* to_limit
, extern_type
*& to_next
) const
216 return do_out(state
, from
, from_end
, from_next
,
217 to
, to_limit
, to_next
);
221 unshift(state_type
& state
, extern_type
* to
, extern_type
* to_limit
,
222 extern_type
*& to_next
) const
223 { return do_unshift(state
, to
, to_limit
, to_next
); }
226 in(state_type
& state
, const extern_type
* from
,
227 const extern_type
* from_end
, const extern_type
*& from_next
,
228 intern_type
* to
, intern_type
* to_limit
, intern_type
*& to_next
) const
230 return do_in(state
, from
, from_end
, from_next
,
231 to
, to_limit
, to_next
);
235 encoding() const throw()
236 { return do_encoding(); }
239 always_noconv() const throw()
240 { return do_always_noconv(); }
243 length(state_type
& state
, const extern_type
* from
,
244 const extern_type
* end
, size_t max
) const
245 { return do_length(state
, from
, end
, max
); }
248 max_length() const throw()
249 { return do_max_length(); }
251 static locale::id id
;
258 do_out(state_type
& state
, const intern_type
* from
,
259 const intern_type
* from_end
, const intern_type
*& from_next
,
260 extern_type
* to
, extern_type
* to_limit
,
261 extern_type
*& to_next
) const
263 while (from
< from_end
&& to
< to_limit
)
265 unsigned char tmp
= (state
.state
^ from
->val
);
266 if (state
.state
& 0x8)
268 if (to
>= to_limit
- 2)
271 *to
++ = ((tmp
>> 3) & 0x7);
272 *to
++ = ((tmp
>> 6) & 0x3);
276 if (to
>= to_limit
- 1)
279 *to
++ = ((tmp
>> 4) & 0xf);
287 return (from
< from_end
) ? partial
: ok
;
291 do_in(state_type
& state
, const extern_type
* from
,
292 const extern_type
* from_end
, const extern_type
*& from_next
,
293 intern_type
* to
, intern_type
* to_limit
,
294 intern_type
*& to_next
) const
296 while (from
< from_end
&& to
< to_limit
)
298 unsigned char c
= *from
;
308 if (state
.state
& 0x8)
310 if (from
>= from_end
- 2)
312 tmp
= (*from
++ & 0x7);
313 tmp
|= ((*from
++ << 3) & 0x38);
314 tmp
|= ((*from
++ << 6) & 0xc0);
318 if (from
>= from_end
- 1)
320 tmp
= (*from
++ & 0xf);
321 tmp
|= ((*from
++ << 4) & 0xf0);
323 to
->val
= (tmp
^ state
.state
);
330 return (from
< from_end
) ? partial
: ok
;
334 do_unshift(state_type
& state
, extern_type
* to
, extern_type
* to_limit
,
335 extern_type
*& to_next
) const
337 for (unsigned int i
= 0; i
< CHAR_BIT
; ++i
)
339 unsigned int mask
= (1 << i
);
340 if (state
.state
& mask
)
348 state
.state
&= ~mask
;
349 *to
++ = static_cast<unsigned char>(~mask
);
354 return state
.state
== 0 ? ok
: error
;
358 do_encoding() const throw()
362 do_always_noconv() const throw()
366 do_length(state_type
& state
, const extern_type
* from
,
367 const extern_type
* end
, size_t max
) const
369 const extern_type
* beg
= from
;
370 while (from
< end
&& max
)
372 unsigned char c
= *from
;
382 if (state
.state
& 0x8)
386 tmp
= (*from
++ & 0x7);
387 tmp
|= ((*from
++ << 3) & 0x38);
388 tmp
|= ((*from
++ << 6) & 0xc0);
394 tmp
= (*from
++ & 0xf);
395 tmp
|= ((*from
++ << 4) & 0xf0);
403 // Maximum 8 bytes unshift sequence followed by max 3 bytes for
406 do_max_length() const throw()
411 codecvt
<__gnu_test::character
, char, __gnu_test::conversion_state
>::id
;
414 #endif // _GLIBCXX_TESTSUITE_CHARACTER_H