388 lines
14 KiB
C++
388 lines
14 KiB
C++
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
|
|
// (C) Copyright 2004-2007 Jonathan Turkanis
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
|
|
|
|
// See http://www.boost.org/libs/iostreams for documentation.
|
|
|
|
#include <boost/iostreams/detail/config/wide_streams.hpp>
|
|
#ifdef BOOST_IOSTREAMS_NO_WIDE_STREAMS
|
|
# error wide streams not supported on this platform
|
|
#endif
|
|
|
|
#include <algorithm> // equal.
|
|
#include <locale>
|
|
#include <string>
|
|
#include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME.
|
|
#include <boost/iostreams/code_converter.hpp>
|
|
#include <boost/iostreams/copy.hpp>
|
|
#include <boost/iostreams/detail/add_facet.hpp>
|
|
#include <boost/iostreams/device/back_inserter.hpp>
|
|
#include <boost/iostreams/detail/config/windows_posix.hpp>
|
|
#include <boost/iostreams/device/file.hpp>
|
|
#if !defined(__COMO__) || !defined(BOOST_COMO_STRICT)
|
|
# if defined(BOOST_IOSTREAMS_NO_LIB) || defined(BOOST_ALL_NO_LIB)
|
|
# include "../src/file_descriptor.cpp"
|
|
# else
|
|
# include <boost/iostreams/device/file_descriptor.hpp>
|
|
# endif
|
|
#endif
|
|
#include <boost/iostreams/stream.hpp>
|
|
#include <boost/test/test_tools.hpp>
|
|
#include <boost/test/unit_test.hpp>
|
|
#include "detail/closable.hpp"
|
|
#include "detail/operation_sequence.hpp"
|
|
#include "detail/temp_file.hpp"
|
|
|
|
// Include codevct facets
|
|
|
|
#include "detail/null_padded_codecvt.hpp"
|
|
#include "detail/utf8_codecvt_facet.hpp"
|
|
#ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX
|
|
# include <codecvt/8859_1>
|
|
# include <codecvt/8859_10>
|
|
# include <codecvt/8859_13>
|
|
# include <codecvt/8859_14>
|
|
# include <codecvt/8859_15>
|
|
# include <codecvt/8859_16>
|
|
# include <codecvt/8859_2>
|
|
# include <codecvt/8859_3>
|
|
# include <codecvt/8859_4>
|
|
# include <codecvt/8859_5>
|
|
# include <codecvt/8859_6>
|
|
# include <codecvt/8859_7>
|
|
# include <codecvt/8859_8>
|
|
# include <codecvt/8859_9>
|
|
# include <codecvt/baltic>
|
|
# include <codecvt/big5>
|
|
# include <codecvt/cp037>
|
|
# include <codecvt/cp1006>
|
|
# include <codecvt/cp1026>
|
|
# include <codecvt/cp1250>
|
|
# include <codecvt/cp1251>
|
|
# include <codecvt/cp1252>
|
|
# include <codecvt/cp1253>
|
|
# include <codecvt/cp1254>
|
|
# include <codecvt/cp1255>
|
|
# include <codecvt/cp1256>
|
|
# include <codecvt/cp1257>
|
|
# include <codecvt/cp1258>
|
|
# include <codecvt/cp424>
|
|
# include <codecvt/cp437>
|
|
# include <codecvt/cp500>
|
|
# include <codecvt/cp737>
|
|
# include <codecvt/cp775>
|
|
# include <codecvt/cp850>
|
|
# include <codecvt/cp852>
|
|
# include <codecvt/cp855>
|
|
# include <codecvt/cp856>
|
|
# include <codecvt/cp857>
|
|
# include <codecvt/cp860>
|
|
# include <codecvt/cp861>
|
|
# include <codecvt/cp862>
|
|
# include <codecvt/cp863>
|
|
# include <codecvt/cp864>
|
|
# include <codecvt/cp865>
|
|
# include <codecvt/cp866>
|
|
# include <codecvt/cp869>
|
|
# include <codecvt/cp874>
|
|
# include <codecvt/cp875>
|
|
# include <codecvt/cp932>
|
|
# include <codecvt/cp936>
|
|
# include <codecvt/cp949>
|
|
# include <codecvt/cp950>
|
|
# include <codecvt/cyrillic>
|
|
# include <codecvt/ebcdic>
|
|
# include <codecvt/euc>
|
|
# include <codecvt/euc_0208>
|
|
# include <codecvt/gb12345>
|
|
# include <codecvt/gb2312>
|
|
# include <codecvt/greek>
|
|
# include <codecvt/iceland>
|
|
# include <codecvt/jis>
|
|
# include <codecvt/jis_0208>
|
|
# include <codecvt/jis0201>
|
|
# include <codecvt/ksc5601>
|
|
# include <codecvt/latin2>
|
|
# include <codecvt/one_one>
|
|
# include <codecvt/roman>
|
|
# include <codecvt/sjis>
|
|
# include <codecvt/sjis_0208>
|
|
# include <codecvt/turkish>
|
|
# include <codecvt/utf16>
|
|
# include <codecvt/utf8>
|
|
# include <codecvt/utf8_utf16>
|
|
# include <codecvt/xjis>
|
|
#endif // #ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX]
|
|
|
|
#include <iostream>
|
|
|
|
using namespace std;
|
|
using namespace boost::iostreams;
|
|
using namespace boost::iostreams::detail;
|
|
using namespace boost::iostreams::test;
|
|
using boost::unit_test::test_suite;
|
|
namespace io = boost::iostreams;
|
|
|
|
const int max_length = 30;
|
|
const unsigned int pattern_length = 100;
|
|
const unsigned int pattern_reps = 100;
|
|
|
|
template<typename Codecvt>
|
|
bool valid_char(typename codecvt_intern<Codecvt>::type c)
|
|
{
|
|
typedef typename codecvt_state<Codecvt>::type state_type;
|
|
typedef typename codecvt_intern<Codecvt>::type intern_type;
|
|
Codecvt cvt;
|
|
state_type state = state_type();
|
|
const intern_type* nint;
|
|
char* next;
|
|
char buf[max_length];
|
|
|
|
return cvt.out( state, &c, &c + 1, nint,
|
|
buf, buf + max_length, next )
|
|
==
|
|
codecvt_base::ok;
|
|
}
|
|
|
|
template<typename Codecvt>
|
|
basic_string<
|
|
BOOST_DEDUCED_TYPENAME
|
|
codecvt_intern<Codecvt>::type
|
|
>
|
|
test_string()
|
|
{
|
|
typedef typename codecvt_intern<Codecvt>::type intern_type;
|
|
std::basic_string<intern_type> pattern, result;
|
|
for (intern_type c = 255; pattern.size() < pattern_length; --c)
|
|
if (valid_char<Codecvt>(c))
|
|
pattern += c;
|
|
result.reserve(pattern.size() * pattern_reps);
|
|
for (unsigned int w = 0; w < pattern_reps; ++w)
|
|
result += pattern;
|
|
return result;
|
|
}
|
|
|
|
// Como can't compile file_descriptor.cpp in strict mode; this failure
|
|
// is detected by file_descriptor_test.cpp.
|
|
#if !defined(__COMO__) || !defined(BOOST_COMO_STRICT)
|
|
typedef io::file_descriptor_source classic_file_source;
|
|
typedef io::file_descriptor_sink classic_file_sink;
|
|
#else
|
|
struct classic_file_source : io::source {
|
|
classic_file_source(const std::string& path)
|
|
: file_(new filebuf)
|
|
{
|
|
file_->pubimbue(locale::classic());
|
|
file_->open(path.c_str(), BOOST_IOS::in | BOOST_IOS::binary);
|
|
}
|
|
streamsize read(char* s, streamsize n) { return file_->sgetn(s, n); }
|
|
boost::shared_ptr<filebuf> file_;
|
|
};
|
|
|
|
struct classic_file_sink : io::sink {
|
|
classic_file_sink(const std::string& path)
|
|
: file_(new filebuf)
|
|
{
|
|
file_->pubimbue(locale::classic());
|
|
file_->open(path.c_str(), BOOST_IOS::out | BOOST_IOS::binary);
|
|
}
|
|
streamsize write(const char* s, streamsize n) { return file_->sputn(s, n); }
|
|
boost::shared_ptr<filebuf> file_;
|
|
};
|
|
#endif
|
|
|
|
template<typename Codecvt>
|
|
bool codecvt_test1()
|
|
{
|
|
typedef basic_string<
|
|
BOOST_DEDUCED_TYPENAME
|
|
codecvt_intern<Codecvt>::type
|
|
> string_type;
|
|
typedef code_converter<classic_file_source, Codecvt> wide_file_source;
|
|
typedef code_converter<classic_file_sink, Codecvt> wide_file_sink;
|
|
|
|
BOOST_CHECK(Codecvt().max_length() <= max_length);
|
|
temp_file temp;
|
|
string_type test = test_string<Codecvt>();
|
|
stream<wide_file_sink> out(temp.name());
|
|
out.write(test.data(), static_cast<streamsize>(test.size()));
|
|
out.close();
|
|
|
|
stream<wide_file_source> in(temp.name());
|
|
string_type test2;
|
|
io::copy(in, io::back_inserter(test2));
|
|
|
|
return test == test2;
|
|
}
|
|
|
|
template<typename Codecvt>
|
|
bool codecvt_test2()
|
|
{
|
|
typedef basic_string<
|
|
BOOST_DEDUCED_TYPENAME
|
|
codecvt_intern<Codecvt>::type
|
|
> string_type;
|
|
typedef code_converter<classic_file_source> wide_file_source;
|
|
typedef code_converter<classic_file_sink> wide_file_sink;
|
|
|
|
// Set global locale.
|
|
locale loc = add_facet(locale(), new Codecvt);
|
|
locale::global(loc);
|
|
|
|
temp_file temp;
|
|
string_type test = test_string<Codecvt>();
|
|
stream<wide_file_sink> out(temp.name());
|
|
out.write(test.data(), static_cast<streamsize>(test.size()));
|
|
out.close();
|
|
|
|
stream<wide_file_source> in(temp.name());
|
|
string_type test2;
|
|
io::copy(in, io::back_inserter(test2));
|
|
|
|
return test == test2;
|
|
}
|
|
|
|
template<typename Codecvt>
|
|
bool codecvt_test()
|
|
{
|
|
return codecvt_test1<Codecvt>() && codecvt_test2<Codecvt>();
|
|
}
|
|
|
|
void code_converter_test()
|
|
{
|
|
BOOST_CHECK((codecvt_test<utf8_codecvt_facet<wchar_t, char> >()));
|
|
BOOST_CHECK(codecvt_test<null_padded_codecvt>());
|
|
BOOST_CHECK(codecvt_test<stateless_null_padded_codecvt>());
|
|
#ifdef BOOST_IOSTREAMS_USE_DINKUM_COREX
|
|
using namespace Dinkum::conversions;
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_1<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_10<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_13<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_14<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_15<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_16<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_2<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_3<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_4<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_5<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_6<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_7<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_8<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_8859_9<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_baltic<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_big5<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp037<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1006<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1026<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1250<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1251<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1252<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1253<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1254<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1255<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1256<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1257<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp1258<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp424<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp437<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp500<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp737<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp775<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp850<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp852<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp855<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp856<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp857<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp860<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp861<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp862<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp863<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp864<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp865<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp866<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp869<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp874<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp875<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp932<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp936<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp949<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cp950<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_cyrillic<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_ebcdic<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_euc<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_euc_0208<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_gb12345<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_gb2312<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_greek<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_iceland<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_jis<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_jis_0208<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_jis0201<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_ksc5601<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_latin2<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_one_one<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_roman<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_sjis<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_sjis_0208<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_turkish<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_utf16<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_utf8<wchar_t> >());
|
|
BOOST_CHECK(codecvt_test< codecvt_utf8_utf16<wchar_t> >());
|
|
#endif
|
|
}
|
|
|
|
/* Defer pending further testing
|
|
void close_test()
|
|
{
|
|
typedef utf8_codecvt_facet<wchar_t, char> codecvt_type;
|
|
|
|
// Test code converter based on a source
|
|
{
|
|
operation_sequence seq;
|
|
io::wchain<input> ch;
|
|
ch.push(
|
|
code_converter<closable_device<input>, codecvt_type>(
|
|
seq.new_operation(1)
|
|
)
|
|
);
|
|
BOOST_CHECK_NO_THROW(ch.reset());
|
|
BOOST_CHECK_OPERATION_SEQUENCE(seq);
|
|
}
|
|
|
|
// Test code converter based on a sink
|
|
{
|
|
operation_sequence seq;
|
|
io::wchain<output> ch;
|
|
ch.push(
|
|
code_converter<closable_device<output>, codecvt_type>(
|
|
seq.new_operation(1)
|
|
)
|
|
);
|
|
BOOST_CHECK_NO_THROW(ch.reset());
|
|
BOOST_CHECK_OPERATION_SEQUENCE(seq);
|
|
}
|
|
|
|
// Test code converter based on a bidirectional device
|
|
{
|
|
operation_sequence seq;
|
|
io::wchain<bidirectional> ch;
|
|
ch.push(
|
|
code_converter<closable_device<bidirectional>, codecvt_type>(
|
|
seq.new_operation(1),
|
|
seq.new_operation(2)
|
|
)
|
|
);
|
|
BOOST_CHECK_NO_THROW(ch.reset());
|
|
BOOST_CHECK_OPERATION_SEQUENCE(seq);
|
|
}
|
|
}*/
|
|
|
|
test_suite* init_unit_test_suite(int, char* [])
|
|
{
|
|
test_suite* test = BOOST_TEST_SUITE("code_converter test");
|
|
test->add(BOOST_TEST_CASE(&code_converter_test));
|
|
//test->add(BOOST_TEST_CASE(&close_test));
|
|
return test;
|
|
}
|