1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2004-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
6 // See http://www.boost.org/libs/iostreams for documentation.
8 #include <boost/iostreams/detail/config/wide_streams.hpp>
9 #ifdef BOOST_IOSTREAMS_NO_WIDE_STREAMS
10 # error wide streams not supported on this platform
13 #include <algorithm> // equal.
16 #include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME.
17 #include <boost/iostreams/code_converter.hpp>
18 #include <boost/iostreams/copy.hpp>
19 #include <boost/iostreams/detail/add_facet.hpp>
20 #include <boost/iostreams/device/back_inserter.hpp>
21 #include <boost/iostreams/detail/config/windows_posix.hpp>
22 #include <boost/iostreams/device/file.hpp>
23 #if !defined(__COMO__) || !defined(BOOST_COMO_STRICT)
24 # if defined(BOOST_IOSTREAMS_NO_LIB) || defined(BOOST_ALL_NO_LIB)
25 # include "../src/file_descriptor.cpp"
27 # include <boost/iostreams/device/file_descriptor.hpp>
30 #include <boost/iostreams/stream.hpp>
31 #include <boost/test/test_tools.hpp>
32 #include <boost/test/unit_test.hpp>
33 #include "detail/closable.hpp"
34 #include "detail/operation_sequence.hpp"
35 #include "detail/temp_file.hpp"
37 // Include codevct facets
39 #include "detail/null_padded_codecvt.hpp"
40 #include "detail/utf8_codecvt_facet.hpp"
41 #ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX
42 # include <codecvt/8859_1>
43 # include <codecvt/8859_10>
44 # include <codecvt/8859_13>
45 # include <codecvt/8859_14>
46 # include <codecvt/8859_15>
47 # include <codecvt/8859_16>
48 # include <codecvt/8859_2>
49 # include <codecvt/8859_3>
50 # include <codecvt/8859_4>
51 # include <codecvt/8859_5>
52 # include <codecvt/8859_6>
53 # include <codecvt/8859_7>
54 # include <codecvt/8859_8>
55 # include <codecvt/8859_9>
56 # include <codecvt/baltic>
57 # include <codecvt/big5>
58 # include <codecvt/cp037>
59 # include <codecvt/cp1006>
60 # include <codecvt/cp1026>
61 # include <codecvt/cp1250>
62 # include <codecvt/cp1251>
63 # include <codecvt/cp1252>
64 # include <codecvt/cp1253>
65 # include <codecvt/cp1254>
66 # include <codecvt/cp1255>
67 # include <codecvt/cp1256>
68 # include <codecvt/cp1257>
69 # include <codecvt/cp1258>
70 # include <codecvt/cp424>
71 # include <codecvt/cp437>
72 # include <codecvt/cp500>
73 # include <codecvt/cp737>
74 # include <codecvt/cp775>
75 # include <codecvt/cp850>
76 # include <codecvt/cp852>
77 # include <codecvt/cp855>
78 # include <codecvt/cp856>
79 # include <codecvt/cp857>
80 # include <codecvt/cp860>
81 # include <codecvt/cp861>
82 # include <codecvt/cp862>
83 # include <codecvt/cp863>
84 # include <codecvt/cp864>
85 # include <codecvt/cp865>
86 # include <codecvt/cp866>
87 # include <codecvt/cp869>
88 # include <codecvt/cp874>
89 # include <codecvt/cp875>
90 # include <codecvt/cp932>
91 # include <codecvt/cp936>
92 # include <codecvt/cp949>
93 # include <codecvt/cp950>
94 # include <codecvt/cyrillic>
95 # include <codecvt/ebcdic>
96 # include <codecvt/euc>
97 # include <codecvt/euc_0208>
98 # include <codecvt/gb12345>
99 # include <codecvt/gb2312>
100 # include <codecvt/greek>
101 # include <codecvt/iceland>
102 # include <codecvt/jis>
103 # include <codecvt/jis_0208>
104 # include <codecvt/jis0201>
105 # include <codecvt/ksc5601>
106 # include <codecvt/latin2>
107 # include <codecvt/one_one>
108 # include <codecvt/roman>
109 # include <codecvt/sjis>
110 # include <codecvt/sjis_0208>
111 # include <codecvt/turkish>
112 # include <codecvt/utf16>
113 # include <codecvt/utf8>
114 # include <codecvt/utf8_utf16>
115 # include <codecvt/xjis>
116 #endif // #ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX]
121 using namespace boost::iostreams
;
122 using namespace boost::iostreams::detail
;
123 using namespace boost::iostreams::test
;
124 using boost::unit_test::test_suite
;
125 namespace io
= boost::iostreams
;
127 const int max_length
= 30;
128 const unsigned int pattern_length
= 100;
129 const unsigned int pattern_reps
= 100;
131 template<typename Codecvt
>
132 bool valid_char(typename codecvt_intern
<Codecvt
>::type c
)
134 typedef typename codecvt_state
<Codecvt
>::type state_type
;
135 typedef typename codecvt_intern
<Codecvt
>::type intern_type
;
137 state_type state
= state_type();
138 const intern_type
* nint
;
140 char buf
[max_length
];
142 return cvt
.out( state
, &c
, &c
+ 1, nint
,
143 buf
, buf
+ max_length
, next
)
148 template<typename Codecvt
>
150 BOOST_DEDUCED_TYPENAME
151 codecvt_intern
<Codecvt
>::type
155 typedef typename codecvt_intern
<Codecvt
>::type intern_type
;
156 std::basic_string
<intern_type
> pattern
, result
;
157 for (intern_type c
= 255; pattern
.size() < pattern_length
; --c
)
158 if (valid_char
<Codecvt
>(c
))
160 result
.reserve(pattern
.size() * pattern_reps
);
161 for (unsigned int w
= 0; w
< pattern_reps
; ++w
)
166 // Como can't compile file_descriptor.cpp in strict mode; this failure
167 // is detected by file_descriptor_test.cpp.
168 #if !defined(__COMO__) || !defined(BOOST_COMO_STRICT)
169 typedef io::file_descriptor_source classic_file_source
;
170 typedef io::file_descriptor_sink classic_file_sink
;
172 struct classic_file_source
: io::source
{
173 classic_file_source(const std::string
& path
)
176 file_
->pubimbue(locale::classic());
177 file_
->open(path
.c_str(), BOOST_IOS::in
| BOOST_IOS::binary
);
179 streamsize
read(char* s
, streamsize n
) { return file_
->sgetn(s
, n
); }
180 boost::shared_ptr
<filebuf
> file_
;
183 struct classic_file_sink
: io::sink
{
184 classic_file_sink(const std::string
& path
)
187 file_
->pubimbue(locale::classic());
188 file_
->open(path
.c_str(), BOOST_IOS::out
| BOOST_IOS::binary
);
190 streamsize
write(const char* s
, streamsize n
) { return file_
->sputn(s
, n
); }
191 boost::shared_ptr
<filebuf
> file_
;
195 template<typename Codecvt
>
198 typedef basic_string
<
199 BOOST_DEDUCED_TYPENAME
200 codecvt_intern
<Codecvt
>::type
202 typedef code_converter
<classic_file_source
, Codecvt
> wide_file_source
;
203 typedef code_converter
<classic_file_sink
, Codecvt
> wide_file_sink
;
205 BOOST_CHECK(Codecvt().max_length() <= max_length
);
207 string_type test
= test_string
<Codecvt
>();
208 stream
<wide_file_sink
> out(temp
.name());
209 out
.write(test
.data(), static_cast<streamsize
>(test
.size()));
212 stream
<wide_file_source
> in(temp
.name());
214 io::copy(in
, io::back_inserter(test2
));
216 return test
== test2
;
219 template<typename Codecvt
>
222 typedef basic_string
<
223 BOOST_DEDUCED_TYPENAME
224 codecvt_intern
<Codecvt
>::type
226 typedef code_converter
<classic_file_source
> wide_file_source
;
227 typedef code_converter
<classic_file_sink
> wide_file_sink
;
229 // Set global locale.
230 locale loc
= add_facet(locale(), new Codecvt
);
234 string_type test
= test_string
<Codecvt
>();
235 stream
<wide_file_sink
> out(temp
.name());
236 out
.write(test
.data(), static_cast<streamsize
>(test
.size()));
239 stream
<wide_file_source
> in(temp
.name());
241 io::copy(in
, io::back_inserter(test2
));
243 return test
== test2
;
246 template<typename Codecvt
>
249 return codecvt_test1
<Codecvt
>() && codecvt_test2
<Codecvt
>();
252 void code_converter_test()
254 BOOST_CHECK((codecvt_test
<utf8_codecvt_facet
<wchar_t, char> >()));
255 BOOST_CHECK(codecvt_test
<null_padded_codecvt
>());
256 BOOST_CHECK(codecvt_test
<stateless_null_padded_codecvt
>());
257 #ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX
258 using namespace Dinkum::conversions
;
259 BOOST_CHECK(codecvt_test
< codecvt_8859_1
<wchar_t> >());
260 BOOST_CHECK(codecvt_test
< codecvt_8859_10
<wchar_t> >());
261 BOOST_CHECK(codecvt_test
< codecvt_8859_13
<wchar_t> >());
262 BOOST_CHECK(codecvt_test
< codecvt_8859_14
<wchar_t> >());
263 BOOST_CHECK(codecvt_test
< codecvt_8859_15
<wchar_t> >());
264 BOOST_CHECK(codecvt_test
< codecvt_8859_16
<wchar_t> >());
265 BOOST_CHECK(codecvt_test
< codecvt_8859_2
<wchar_t> >());
266 BOOST_CHECK(codecvt_test
< codecvt_8859_3
<wchar_t> >());
267 BOOST_CHECK(codecvt_test
< codecvt_8859_4
<wchar_t> >());
268 BOOST_CHECK(codecvt_test
< codecvt_8859_5
<wchar_t> >());
269 BOOST_CHECK(codecvt_test
< codecvt_8859_6
<wchar_t> >());
270 BOOST_CHECK(codecvt_test
< codecvt_8859_7
<wchar_t> >());
271 BOOST_CHECK(codecvt_test
< codecvt_8859_8
<wchar_t> >());
272 BOOST_CHECK(codecvt_test
< codecvt_8859_9
<wchar_t> >());
273 BOOST_CHECK(codecvt_test
< codecvt_baltic
<wchar_t> >());
274 BOOST_CHECK(codecvt_test
< codecvt_big5
<wchar_t> >());
275 BOOST_CHECK(codecvt_test
< codecvt_cp037
<wchar_t> >());
276 BOOST_CHECK(codecvt_test
< codecvt_cp1006
<wchar_t> >());
277 BOOST_CHECK(codecvt_test
< codecvt_cp1026
<wchar_t> >());
278 BOOST_CHECK(codecvt_test
< codecvt_cp1250
<wchar_t> >());
279 BOOST_CHECK(codecvt_test
< codecvt_cp1251
<wchar_t> >());
280 BOOST_CHECK(codecvt_test
< codecvt_cp1252
<wchar_t> >());
281 BOOST_CHECK(codecvt_test
< codecvt_cp1253
<wchar_t> >());
282 BOOST_CHECK(codecvt_test
< codecvt_cp1254
<wchar_t> >());
283 BOOST_CHECK(codecvt_test
< codecvt_cp1255
<wchar_t> >());
284 BOOST_CHECK(codecvt_test
< codecvt_cp1256
<wchar_t> >());
285 BOOST_CHECK(codecvt_test
< codecvt_cp1257
<wchar_t> >());
286 BOOST_CHECK(codecvt_test
< codecvt_cp1258
<wchar_t> >());
287 BOOST_CHECK(codecvt_test
< codecvt_cp424
<wchar_t> >());
288 BOOST_CHECK(codecvt_test
< codecvt_cp437
<wchar_t> >());
289 BOOST_CHECK(codecvt_test
< codecvt_cp500
<wchar_t> >());
290 BOOST_CHECK(codecvt_test
< codecvt_cp737
<wchar_t> >());
291 BOOST_CHECK(codecvt_test
< codecvt_cp775
<wchar_t> >());
292 BOOST_CHECK(codecvt_test
< codecvt_cp850
<wchar_t> >());
293 BOOST_CHECK(codecvt_test
< codecvt_cp852
<wchar_t> >());
294 BOOST_CHECK(codecvt_test
< codecvt_cp855
<wchar_t> >());
295 BOOST_CHECK(codecvt_test
< codecvt_cp856
<wchar_t> >());
296 BOOST_CHECK(codecvt_test
< codecvt_cp857
<wchar_t> >());
297 BOOST_CHECK(codecvt_test
< codecvt_cp860
<wchar_t> >());
298 BOOST_CHECK(codecvt_test
< codecvt_cp861
<wchar_t> >());
299 BOOST_CHECK(codecvt_test
< codecvt_cp862
<wchar_t> >());
300 BOOST_CHECK(codecvt_test
< codecvt_cp863
<wchar_t> >());
301 BOOST_CHECK(codecvt_test
< codecvt_cp864
<wchar_t> >());
302 BOOST_CHECK(codecvt_test
< codecvt_cp865
<wchar_t> >());
303 BOOST_CHECK(codecvt_test
< codecvt_cp866
<wchar_t> >());
304 BOOST_CHECK(codecvt_test
< codecvt_cp869
<wchar_t> >());
305 BOOST_CHECK(codecvt_test
< codecvt_cp874
<wchar_t> >());
306 BOOST_CHECK(codecvt_test
< codecvt_cp875
<wchar_t> >());
307 BOOST_CHECK(codecvt_test
< codecvt_cp932
<wchar_t> >());
308 BOOST_CHECK(codecvt_test
< codecvt_cp936
<wchar_t> >());
309 BOOST_CHECK(codecvt_test
< codecvt_cp949
<wchar_t> >());
310 BOOST_CHECK(codecvt_test
< codecvt_cp950
<wchar_t> >());
311 BOOST_CHECK(codecvt_test
< codecvt_cyrillic
<wchar_t> >());
312 BOOST_CHECK(codecvt_test
< codecvt_ebcdic
<wchar_t> >());
313 BOOST_CHECK(codecvt_test
< codecvt_euc
<wchar_t> >());
314 BOOST_CHECK(codecvt_test
< codecvt_euc_0208
<wchar_t> >());
315 BOOST_CHECK(codecvt_test
< codecvt_gb12345
<wchar_t> >());
316 BOOST_CHECK(codecvt_test
< codecvt_gb2312
<wchar_t> >());
317 BOOST_CHECK(codecvt_test
< codecvt_greek
<wchar_t> >());
318 BOOST_CHECK(codecvt_test
< codecvt_iceland
<wchar_t> >());
319 BOOST_CHECK(codecvt_test
< codecvt_jis
<wchar_t> >());
320 BOOST_CHECK(codecvt_test
< codecvt_jis_0208
<wchar_t> >());
321 BOOST_CHECK(codecvt_test
< codecvt_jis0201
<wchar_t> >());
322 BOOST_CHECK(codecvt_test
< codecvt_ksc5601
<wchar_t> >());
323 BOOST_CHECK(codecvt_test
< codecvt_latin2
<wchar_t> >());
324 BOOST_CHECK(codecvt_test
< codecvt_one_one
<wchar_t> >());
325 BOOST_CHECK(codecvt_test
< codecvt_roman
<wchar_t> >());
326 BOOST_CHECK(codecvt_test
< codecvt_sjis
<wchar_t> >());
327 BOOST_CHECK(codecvt_test
< codecvt_sjis_0208
<wchar_t> >());
328 BOOST_CHECK(codecvt_test
< codecvt_turkish
<wchar_t> >());
329 BOOST_CHECK(codecvt_test
< codecvt_utf16
<wchar_t> >());
330 BOOST_CHECK(codecvt_test
< codecvt_utf8
<wchar_t> >());
331 BOOST_CHECK(codecvt_test
< codecvt_utf8_utf16
<wchar_t> >());
335 /* Defer pending further testing
338 typedef utf8_codecvt_facet<wchar_t, char> codecvt_type;
340 // Test code converter based on a source
342 operation_sequence seq;
343 io::wchain<input> ch;
345 code_converter<closable_device<input>, codecvt_type>(
349 BOOST_CHECK_NO_THROW(ch.reset());
350 BOOST_CHECK_OPERATION_SEQUENCE(seq);
353 // Test code converter based on a sink
355 operation_sequence seq;
356 io::wchain<output> ch;
358 code_converter<closable_device<output>, codecvt_type>(
362 BOOST_CHECK_NO_THROW(ch.reset());
363 BOOST_CHECK_OPERATION_SEQUENCE(seq);
366 // Test code converter based on a bidirectional device
368 operation_sequence seq;
369 io::wchain<bidirectional> ch;
371 code_converter<closable_device<bidirectional>, codecvt_type>(
372 seq.new_operation(1),
376 BOOST_CHECK_NO_THROW(ch.reset());
377 BOOST_CHECK_OPERATION_SEQUENCE(seq);
381 test_suite
* init_unit_test_suite(int, char* [])
383 test_suite
* test
= BOOST_TEST_SUITE("code_converter test");
384 test
->add(BOOST_TEST_CASE(&code_converter_test
));
385 //test->add(BOOST_TEST_CASE(&close_test));