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
120using namespace std;
121using namespace boost::iostreams;
122using namespace boost::iostreams::detail;
123using namespace boost::iostreams::test;
124using boost::unit_test::test_suite;
125namespace io = boost::iostreams;
126
127const int max_length = 30;
128const unsigned int pattern_length = 100;
129const unsigned int pattern_reps = 100;
130
131template<typename Codecvt>
132bool 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
148template<typename Codecvt>
149basic_string<
150 BOOST_DEDUCED_TYPENAME
151 codecvt_intern<Codecvt>::type
152>
153test_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
195template<typename Codecvt>
196bool 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
219template<typename Codecvt>
220bool 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: loc);
232
233 temp_file temp;
234 string_type test = test_string<Codecvt>();
235 stream<wide_file_sink> out(temp.name());
236 out.write(s: test.data(), n: 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
246template<typename Codecvt>
247bool codecvt_test()
248{
249 return codecvt_test1<Codecvt>() && codecvt_test2<Codecvt>();
250}
251
252void 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
336void 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
381test_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}
388

source code of boost/libs/iostreams/test/code_converter_test.cpp