|
#pragma once |
|
|
|
#include <iostream> |
|
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|
# pragma once |
|
#endif |
|
|
|
#include <cassert> |
|
#include <iosfwd> // streamsize. |
|
#include <memory> // allocator, bad_alloc. |
|
#include <new> |
|
#include <string> |
|
#include <boost/config.hpp> |
|
#include <boost/cstdint.hpp> |
|
#include <boost/detail/workaround.hpp> |
|
#include <boost/iostreams/constants.hpp> |
|
#include <boost/iostreams/detail/config/auto_link.hpp> |
|
#include <boost/iostreams/detail/config/dyn_link.hpp> |
|
#include <boost/iostreams/detail/config/wide_streams.hpp> |
|
#include <boost/iostreams/detail/config/zlib.hpp> |
|
#include <boost/iostreams/detail/ios.hpp> |
|
#include <boost/iostreams/filter/symmetric.hpp> |
|
#include <boost/iostreams/pipeline.hpp> |
|
#include <boost/type_traits/is_same.hpp> |
|
#include <boost/iostreams/filter/zlib.hpp> |
|
#include <iconv.h> |
|
|
|
// Must come last. |
|
#ifdef BOOST_MSVC |
|
# pragma warning(push) |
|
# pragma warning(disable:4251 4231 4660) // Dependencies not exported. |
|
#endif |
|
#include <boost/config/abi_prefix.hpp> |
|
#undef small |
|
|
|
|
|
namespace boost |
|
{ |
|
namespace iostreams |
|
{ |
|
// CONSTANTS |
|
// --------- |
|
|
|
extern const size_t maxUnicodeWidth; |
|
|
|
// OBJECTS |
|
// ------- |
|
|
|
|
|
/** @brief Parameters for input and output encodings to pass to iconv. |
|
*/ |
|
struct encoded_params { |
|
std::string input; |
|
std::string output; |
|
|
|
encoded_params(const std::string &input = "UTF-8", |
|
const std::string &output = "UTF-8"): |
|
input(input), |
|
output(output) |
|
{} |
|
}; |
|
|
|
|
|
namespace detail |
|
{ |
|
// DETAILS |
|
// ------- |
|
|
|
|
|
/** @brief Base class for the character set conversion filter. |
|
* Contains a core process function which converts the source |
|
* encoding to the destination encoding. |
|
*/ |
|
class BOOST_IOSTREAMS_DECL encoded_base { |
|
public: |
|
typedef char char_type; |
|
protected: |
|
encoded_base(const encoded_params & params = encoded_params()); |
|
|
|
~encoded_base(); |
|
|
|
int convert(const char * & src_begin, |
|
const char * & src_end, |
|
char * & dest_begin, |
|
char * & dest_end); |
|
|
|
int copy(const char * & src_begin, |
|
const char * & src_end, |
|
char * & dest_begin, |
|
char * & dest_end); |
|
|
|
int process(const char * & src_begin, |
|
const char * & src_end, |
|
char * & dest_begin, |
|
char * & dest_end, |
|
int /* flushLevel */); |
|
|
|
public: |
|
int total_in(); |
|
int total_out(); |
|
|
|
|
|
private: |
|
iconv_t conv; |
|
bool differentCharset; |
|
}; |
|
|
|
|
|
/** @brief Template implementation for the encoded writer. |
|
* |
|
* Model of a C-style file filter for character set conversions, via |
|
* iconv. |
|
*/ |
|
template<typename Alloc = std::allocator<char> > |
|
class encoded_writer_impl : public encoded_base { |
|
public: |
|
encoded_writer_impl(const encoded_params ¶ms = encoded_params()); |
|
~encoded_writer_impl(); |
|
bool filter(const char*& src_begin, const char* src_end, |
|
char*& dest_begin, char* dest_end, bool flush); |
|
void close(); |
|
}; |
|
|
|
|
|
/** @brief Template implementation for the encoded reader. |
|
* |
|
* Model of a C-style file filter for character set conversions, via |
|
* iconv. |
|
*/ |
|
template<typename Alloc = std::allocator<char> > |
|
class encoded_reader_impl : public encoded_base { |
|
public: |
|
encoded_reader_impl(const encoded_params ¶ms = encoded_params()); |
|
~encoded_reader_impl(); |
|
bool filter(const char*& begin_in, const char* end_in, |
|
char*& begin_out, char* end_out, bool flush); |
|
void close(); |
|
bool eof() const |
|
{ |
|
return eof_; |
|
} |
|
|
|
private: |
|
bool eof_; |
|
}; |
|
|
|
|
|
|
|
} /* detail */ |
|
|
|
// FILTERS |
|
// ------- |
|
|
|
/** @brief Model of InputFilter and OutputFilter implementing |
|
* character set conversion via iconv. |
|
*/ |
|
template<typename Alloc = std::allocator<char> > |
|
struct basic_encoded_writer |
|
: symmetric_filter<detail::encoded_writer_impl<Alloc>, Alloc> |
|
{ |
|
private: |
|
typedef detail::encoded_writer_impl<Alloc> impl_type; |
|
typedef symmetric_filter<impl_type, Alloc> base_type; |
|
public: |
|
typedef typename base_type::char_type char_type; |
|
typedef typename base_type::category category; |
|
basic_encoded_writer(const encoded_params ¶ms = encoded_params(), |
|
int buffer_size = default_device_buffer_size); |
|
int total_in() { return this->filter().total_in(); } |
|
}; |
|
BOOST_IOSTREAMS_PIPABLE(basic_encoded_writer, 1) |
|
|
|
typedef basic_encoded_writer<> encoded_writer; |
|
|
|
|
|
/** @brief Model of InputFilter and OutputFilter implementing |
|
* character set conversion via iconv. |
|
*/ |
|
template<typename Alloc = std::allocator<char> > |
|
struct basic_encoded_reader |
|
: symmetric_filter<detail::encoded_reader_impl<Alloc>, Alloc> |
|
{ |
|
private: |
|
typedef detail::encoded_reader_impl<Alloc> impl_type; |
|
typedef symmetric_filter<impl_type, Alloc> base_type; |
|
public: |
|
typedef typename base_type::char_type char_type; |
|
typedef typename base_type::category category; |
|
basic_encoded_reader(const encoded_params ¶ms = encoded_params(), |
|
int buffer_size = default_device_buffer_size); |
|
int total_out() { return this->filter().total_out(); } |
|
bool eof() { return this->filter().eof(); } |
|
}; |
|
BOOST_IOSTREAMS_PIPABLE(basic_encoded_reader, 1) |
|
|
|
typedef basic_encoded_reader<> encoded_reader; |
|
|
|
|
|
namespace detail |
|
{ |
|
// IMPLEMENTATION |
|
// -------------- |
|
|
|
|
|
/** @brief Initialize the encoded writer with the iconv parameters. |
|
*/ |
|
template<typename Alloc> |
|
encoded_writer_impl<Alloc>::encoded_writer_impl(const encoded_params& p): |
|
encoded_base(p) |
|
{} |
|
|
|
|
|
/** @brief Close the encoded writer. |
|
*/ |
|
template<typename Alloc> |
|
encoded_writer_impl<Alloc>::~encoded_writer_impl() |
|
{} |
|
|
|
|
|
/** @brief Implementation of the symmetric, character set encoding filter |
|
* for the writer. |
|
*/ |
|
template<typename Alloc> |
|
bool encoded_writer_impl<Alloc>::filter |
|
(const char*& src_begin, const char* src_end, |
|
char*& dest_begin, char* dest_end, bool flush) |
|
{ |
|
int result = process(src_begin, src_end, dest_begin, dest_end, flush); |
|
return result == -1; |
|
} |
|
|
|
|
|
/** @brief Close the encoded writer. |
|
*/ |
|
template<typename Alloc> |
|
void encoded_writer_impl<Alloc>::close() |
|
{} |
|
|
|
|
|
/** @brief Close the encoded reader. |
|
*/ |
|
template<typename Alloc> |
|
encoded_reader_impl<Alloc>::~encoded_reader_impl() |
|
{} |
|
|
|
|
|
/** @brief Initialize the encoded reader with the iconv parameters. |
|
*/ |
|
template<typename Alloc> |
|
encoded_reader_impl<Alloc>::encoded_reader_impl(const encoded_params& p): |
|
encoded_base(p), |
|
eof_(false) |
|
{} |
|
|
|
|
|
/** @brief Implementation of the symmetric, character set encoding filter |
|
* for the reader. |
|
*/ |
|
template<typename Alloc> |
|
bool encoded_reader_impl<Alloc>::filter |
|
(const char*& src_begin, const char* src_end, |
|
char*& dest_begin, char* dest_end, bool /* flush */) |
|
{ |
|
int result = process(src_begin, src_end, dest_begin, dest_end, true); |
|
return result; |
|
} |
|
|
|
|
|
/** @brief Close the encoded reader. |
|
*/ |
|
template<typename Alloc> |
|
void encoded_reader_impl<Alloc>::close() |
|
{ |
|
// cannot re-open, not a true stream |
|
//eof_ = false; |
|
//reset(false, true); |
|
} |
|
|
|
} /* detail */ |
|
|
|
|
|
/** @brief Initializer for the symmetric write filter, which initializes |
|
* the iconv base from the parameters and the buffer size. |
|
*/ |
|
template<typename Alloc> |
|
basic_encoded_writer<Alloc>::basic_encoded_writer |
|
(const encoded_params& p, int buffer_size): |
|
base_type(buffer_size, p) |
|
{} |
|
|
|
|
|
/** @brief Initializer for the symmetric read filter, which initializes |
|
* the iconv base from the parameters and the buffer size. |
|
*/ |
|
template<typename Alloc> |
|
basic_encoded_reader<Alloc>::basic_encoded_reader(const encoded_params &p, int buffer_size): |
|
base_type(buffer_size, p) |
|
{} |
|
|
|
|
|
} /* iostreams */ |
|
} /* boost */ |
|
|
|
#include <boost/config/abi_suffix.hpp> // Pops abi_suffix.hpp pragmas. |
|
#ifdef BOOST_MSVC |
|
# pragma warning(pop) |
|
#endif |