]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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.) | |
5 | ||
6 | // See http://www.boost.org/libs/iostreams for documentation. | |
7 | ||
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 | |
11 | #endif | |
12 | ||
13 | #include <algorithm> // equal. | |
14 | #include <locale> | |
15 | #include <string> | |
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" | |
26 | # else | |
27 | # include <boost/iostreams/device/file_descriptor.hpp> | |
28 | # endif | |
29 | #endif | |
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" | |
36 | ||
37 | // Include codevct facets | |
38 | ||
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] | |
117 | ||
118 | #include <iostream> | |
119 | ||
120 | using namespace std; | |
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; | |
126 | ||
127 | const int max_length = 30; | |
128 | const unsigned int pattern_length = 100; | |
129 | const unsigned int pattern_reps = 100; | |
130 | ||
131 | template<typename Codecvt> | |
132 | bool valid_char(typename codecvt_intern<Codecvt>::type c) | |
133 | { | |
134 | typedef typename codecvt_state<Codecvt>::type state_type; | |
135 | typedef typename codecvt_intern<Codecvt>::type intern_type; | |
136 | Codecvt cvt; | |
137 | state_type state = state_type(); | |
138 | const intern_type* nint; | |
139 | char* next; | |
140 | char buf[max_length]; | |
141 | ||
142 | return cvt.out( state, &c, &c + 1, nint, | |
143 | buf, buf + max_length, next ) | |
144 | == | |
145 | codecvt_base::ok; | |
146 | } | |
147 | ||
148 | template<typename Codecvt> | |
149 | basic_string< | |
150 | BOOST_DEDUCED_TYPENAME | |
151 | codecvt_intern<Codecvt>::type | |
152 | > | |
153 | test_string() | |
154 | { | |
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)) | |
159 | pattern += c; | |
160 | result.reserve(pattern.size() * pattern_reps); | |
161 | for (unsigned int w = 0; w < pattern_reps; ++w) | |
162 | result += pattern; | |
163 | return result; | |
164 | } | |
165 | ||
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; | |
171 | #else | |
172 | struct classic_file_source : io::source { | |
173 | classic_file_source(const std::string& path) | |
174 | : file_(new filebuf) | |
175 | { | |
176 | file_->pubimbue(locale::classic()); | |
177 | file_->open(path.c_str(), BOOST_IOS::in | BOOST_IOS::binary); | |
178 | } | |
179 | streamsize read(char* s, streamsize n) { return file_->sgetn(s, n); } | |
180 | boost::shared_ptr<filebuf> file_; | |
181 | }; | |
182 | ||
183 | struct classic_file_sink : io::sink { | |
184 | classic_file_sink(const std::string& path) | |
185 | : file_(new filebuf) | |
186 | { | |
187 | file_->pubimbue(locale::classic()); | |
188 | file_->open(path.c_str(), BOOST_IOS::out | BOOST_IOS::binary); | |
189 | } | |
190 | streamsize write(const char* s, streamsize n) { return file_->sputn(s, n); } | |
191 | boost::shared_ptr<filebuf> file_; | |
192 | }; | |
193 | #endif | |
194 | ||
195 | template<typename Codecvt> | |
196 | bool codecvt_test1() | |
197 | { | |
198 | typedef basic_string< | |
199 | BOOST_DEDUCED_TYPENAME | |
200 | codecvt_intern<Codecvt>::type | |
201 | > string_type; | |
202 | typedef code_converter<classic_file_source, Codecvt> wide_file_source; | |
203 | typedef code_converter<classic_file_sink, Codecvt> wide_file_sink; | |
204 | ||
205 | BOOST_CHECK(Codecvt().max_length() <= max_length); | |
206 | temp_file temp; | |
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())); | |
210 | out.close(); | |
211 | ||
212 | stream<wide_file_source> in(temp.name()); | |
213 | string_type test2; | |
214 | io::copy(in, io::back_inserter(test2)); | |
215 | ||
216 | return test == test2; | |
217 | } | |
218 | ||
219 | template<typename Codecvt> | |
220 | bool codecvt_test2() | |
221 | { | |
222 | typedef basic_string< | |
223 | BOOST_DEDUCED_TYPENAME | |
224 | codecvt_intern<Codecvt>::type | |
225 | > string_type; | |
226 | typedef code_converter<classic_file_source> wide_file_source; | |
227 | typedef code_converter<classic_file_sink> wide_file_sink; | |
228 | ||
229 | // Set global locale. | |
230 | locale loc = add_facet(locale(), new Codecvt); | |
231 | locale::global(loc); | |
232 | ||
233 | temp_file temp; | |
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())); | |
237 | out.close(); | |
238 | ||
239 | stream<wide_file_source> in(temp.name()); | |
240 | string_type test2; | |
241 | io::copy(in, io::back_inserter(test2)); | |
242 | ||
243 | return test == test2; | |
244 | } | |
245 | ||
246 | template<typename Codecvt> | |
247 | bool codecvt_test() | |
248 | { | |
249 | return codecvt_test1<Codecvt>() && codecvt_test2<Codecvt>(); | |
250 | } | |
251 | ||
252 | void code_converter_test() | |
253 | { | |
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> >()); | |
332 | #endif | |
333 | } | |
334 | ||
335 | /* Defer pending further testing | |
336 | void close_test() | |
337 | { | |
338 | typedef utf8_codecvt_facet<wchar_t, char> codecvt_type; | |
339 | ||
340 | // Test code converter based on a source | |
341 | { | |
342 | operation_sequence seq; | |
343 | io::wchain<input> ch; | |
344 | ch.push( | |
345 | code_converter<closable_device<input>, codecvt_type>( | |
346 | seq.new_operation(1) | |
347 | ) | |
348 | ); | |
349 | BOOST_CHECK_NO_THROW(ch.reset()); | |
350 | BOOST_CHECK_OPERATION_SEQUENCE(seq); | |
351 | } | |
352 | ||
353 | // Test code converter based on a sink | |
354 | { | |
355 | operation_sequence seq; | |
356 | io::wchain<output> ch; | |
357 | ch.push( | |
358 | code_converter<closable_device<output>, codecvt_type>( | |
359 | seq.new_operation(1) | |
360 | ) | |
361 | ); | |
362 | BOOST_CHECK_NO_THROW(ch.reset()); | |
363 | BOOST_CHECK_OPERATION_SEQUENCE(seq); | |
364 | } | |
365 | ||
366 | // Test code converter based on a bidirectional device | |
367 | { | |
368 | operation_sequence seq; | |
369 | io::wchain<bidirectional> ch; | |
370 | ch.push( | |
371 | code_converter<closable_device<bidirectional>, codecvt_type>( | |
372 | seq.new_operation(1), | |
373 | seq.new_operation(2) | |
374 | ) | |
375 | ); | |
376 | BOOST_CHECK_NO_THROW(ch.reset()); | |
377 | BOOST_CHECK_OPERATION_SEQUENCE(seq); | |
378 | } | |
379 | }*/ | |
380 | ||
381 | test_suite* init_unit_test_suite(int, char* []) | |
382 | { | |
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)); | |
386 | return test; | |
387 | } |