Added boost header
This commit is contained in:
424
test/external/boost/iostreams/code_converter.hpp
vendored
Normal file
424
test/external/boost/iostreams/code_converter.hpp
vendored
Normal file
@@ -0,0 +1,424 @@
|
||||
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
|
||||
// (C) Copyright 2003-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.
|
||||
|
||||
// Contains machinery for performing code conversion.
|
||||
|
||||
#ifndef BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED
|
||||
#define BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/iostreams/detail/config/wide_streams.hpp>
|
||||
#if defined(BOOST_IOSTREAMS_NO_WIDE_STREAMS) || \
|
||||
defined(BOOST_IOSTREAMS_NO_LOCALE) \
|
||||
/**/
|
||||
# error code conversion not supported on this platform
|
||||
#endif
|
||||
|
||||
#include <algorithm> // max.
|
||||
#include <cstring> // memcpy.
|
||||
#include <exception>
|
||||
#include <boost/config.hpp> // DEDUCED_TYPENAME,
|
||||
#include <boost/iostreams/char_traits.hpp>
|
||||
#include <boost/iostreams/constants.hpp> // default_filter_buffer_size.
|
||||
#include <boost/iostreams/detail/adapter/concept_adapter.hpp>
|
||||
#include <boost/iostreams/detail/adapter/direct_adapter.hpp>
|
||||
#include <boost/iostreams/detail/buffer.hpp>
|
||||
#include <boost/iostreams/detail/call_traits.hpp>
|
||||
#include <boost/iostreams/detail/codecvt_holder.hpp>
|
||||
#include <boost/iostreams/detail/codecvt_helper.hpp>
|
||||
#include <boost/iostreams/detail/double_object.hpp>
|
||||
#include <boost/iostreams/detail/execute.hpp>
|
||||
#include <boost/iostreams/detail/forward.hpp>
|
||||
#include <boost/iostreams/detail/functional.hpp>
|
||||
#include <boost/iostreams/detail/ios.hpp> // failure, openmode, int types.
|
||||
#include <boost/iostreams/detail/optional.hpp>
|
||||
#include <boost/iostreams/detail/select.hpp>
|
||||
#include <boost/iostreams/traits.hpp>
|
||||
#include <boost/iostreams/operations.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
// Must come last.
|
||||
#include <boost/iostreams/detail/config/disable_warnings.hpp> // Borland 5.x
|
||||
|
||||
namespace boost { namespace iostreams {
|
||||
|
||||
struct code_conversion_error : BOOST_IOSTREAMS_FAILURE {
|
||||
code_conversion_error()
|
||||
: BOOST_IOSTREAMS_FAILURE("code conversion error")
|
||||
{ }
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
//--------------Definition of strncpy_if_same---------------------------------//
|
||||
|
||||
// Helper template for strncpy_if_same, below.
|
||||
template<bool B>
|
||||
struct strncpy_if_same_impl;
|
||||
|
||||
template<>
|
||||
struct strncpy_if_same_impl<true> {
|
||||
template<typename Ch>
|
||||
static Ch* copy(Ch* tgt, const Ch* src, std::streamsize n)
|
||||
{ return BOOST_IOSTREAMS_CHAR_TRAITS(Ch)::copy(tgt, src, n); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct strncpy_if_same_impl<false> {
|
||||
template<typename Src, typename Tgt>
|
||||
static Tgt* copy(Tgt* tgt, const Src*, std::streamsize) { return tgt; }
|
||||
};
|
||||
|
||||
template<typename Src, typename Tgt>
|
||||
Tgt* strncpy_if_same(Tgt* tgt, const Src* src, std::streamsize n)
|
||||
{
|
||||
typedef strncpy_if_same_impl<is_same<Src, Tgt>::value> impl;
|
||||
return impl::copy(tgt, src, n);
|
||||
}
|
||||
|
||||
//--------------Definition of conversion_buffer-------------------------------//
|
||||
|
||||
// Buffer and conversion state for reading.
|
||||
template<typename Codecvt, typename Alloc>
|
||||
class conversion_buffer
|
||||
: public buffer<
|
||||
BOOST_DEDUCED_TYPENAME detail::codecvt_extern<Codecvt>::type,
|
||||
Alloc
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef typename Codecvt::state_type state_type;
|
||||
conversion_buffer()
|
||||
: buffer<
|
||||
BOOST_DEDUCED_TYPENAME detail::codecvt_extern<Codecvt>::type,
|
||||
Alloc
|
||||
>(0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
state_type& state() { return state_; }
|
||||
void reset()
|
||||
{
|
||||
if (this->size())
|
||||
this->set(0, 0);
|
||||
state_ = state_type();
|
||||
}
|
||||
private:
|
||||
state_type state_;
|
||||
};
|
||||
|
||||
//--------------Definition of converter_impl----------------------------------//
|
||||
|
||||
// Contains member data, open/is_open/close and buffer management functions.
|
||||
template<typename Device, typename Codecvt, typename Alloc>
|
||||
struct code_converter_impl {
|
||||
typedef typename codecvt_extern<Codecvt>::type extern_type;
|
||||
typedef typename category_of<Device>::type device_category;
|
||||
typedef is_convertible<device_category, input> can_read;
|
||||
typedef is_convertible<device_category, output> can_write;
|
||||
typedef is_convertible<device_category, bidirectional> is_bidir;
|
||||
typedef typename
|
||||
iostreams::select< // Disambiguation for Tru64.
|
||||
is_bidir, bidirectional,
|
||||
can_read, input,
|
||||
can_write, output
|
||||
>::type mode;
|
||||
typedef typename
|
||||
mpl::if_<
|
||||
is_direct<Device>,
|
||||
direct_adapter<Device>,
|
||||
Device
|
||||
>::type device_type;
|
||||
typedef optional< concept_adapter<device_type> > storage_type;
|
||||
typedef is_convertible<device_category, two_sequence> is_double;
|
||||
typedef conversion_buffer<Codecvt, Alloc> buffer_type;
|
||||
|
||||
code_converter_impl() : cvt_(), flags_(0) { }
|
||||
|
||||
~code_converter_impl()
|
||||
{
|
||||
try {
|
||||
if (flags_ & f_open) close();
|
||||
} catch (...) { /* */ }
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void open(const T& dev, int buffer_size)
|
||||
{
|
||||
if (flags_ & f_open)
|
||||
boost::throw_exception(BOOST_IOSTREAMS_FAILURE("already open"));
|
||||
if (buffer_size == -1)
|
||||
buffer_size = default_filter_buffer_size;
|
||||
int max_length = cvt_.get().max_length();
|
||||
buffer_size = (std::max)(buffer_size, 2 * max_length);
|
||||
if (can_read::value) {
|
||||
buf_.first().resize(buffer_size);
|
||||
buf_.first().set(0, 0);
|
||||
}
|
||||
if (can_write::value && !is_double::value) {
|
||||
buf_.second().resize(buffer_size);
|
||||
buf_.second().set(0, 0);
|
||||
}
|
||||
dev_.reset(concept_adapter<device_type>(dev));
|
||||
flags_ = f_open;
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
detail::execute_all(
|
||||
detail::call_member_close(*this, BOOST_IOS::in),
|
||||
detail::call_member_close(*this, BOOST_IOS::out)
|
||||
);
|
||||
}
|
||||
|
||||
void close(BOOST_IOS::openmode which)
|
||||
{
|
||||
if (which == BOOST_IOS::in && (flags_ & f_input_closed) == 0) {
|
||||
flags_ |= f_input_closed;
|
||||
iostreams::close(dev(), BOOST_IOS::in);
|
||||
}
|
||||
if (which == BOOST_IOS::out && (flags_ & f_output_closed) == 0) {
|
||||
flags_ |= f_output_closed;
|
||||
detail::execute_all(
|
||||
detail::flush_buffer(buf_.second(), dev(), can_write::value),
|
||||
detail::call_close(dev(), BOOST_IOS::out),
|
||||
detail::call_reset(dev_),
|
||||
detail::call_reset(buf_.first()),
|
||||
detail::call_reset(buf_.second())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_open() const { return (flags_ & f_open) != 0;}
|
||||
|
||||
device_type& dev() { return **dev_; }
|
||||
|
||||
enum flag_type {
|
||||
f_open = 1,
|
||||
f_input_closed = f_open << 1,
|
||||
f_output_closed = f_input_closed << 1
|
||||
};
|
||||
|
||||
codecvt_holder<Codecvt> cvt_;
|
||||
storage_type dev_;
|
||||
double_object<
|
||||
buffer_type,
|
||||
is_double
|
||||
> buf_;
|
||||
int flags_;
|
||||
};
|
||||
|
||||
} // End namespace detail.
|
||||
|
||||
//--------------Definition of converter---------------------------------------//
|
||||
|
||||
#define BOOST_IOSTREAMS_CONVERTER_PARAMS() , int buffer_size = -1
|
||||
#define BOOST_IOSTREAMS_CONVERTER_ARGS() , buffer_size
|
||||
|
||||
template<typename Device, typename Codecvt, typename Alloc>
|
||||
struct code_converter_base {
|
||||
typedef detail::code_converter_impl<
|
||||
Device, Codecvt, Alloc
|
||||
> impl_type;
|
||||
code_converter_base() : pimpl_(new impl_type) { }
|
||||
shared_ptr<impl_type> pimpl_;
|
||||
};
|
||||
|
||||
template< typename Device,
|
||||
typename Codecvt = detail::default_codecvt,
|
||||
typename Alloc = std::allocator<char> >
|
||||
class code_converter
|
||||
: protected code_converter_base<Device, Codecvt, Alloc>
|
||||
{
|
||||
private:
|
||||
typedef detail::code_converter_impl<
|
||||
Device, Codecvt, Alloc
|
||||
> impl_type;
|
||||
typedef typename impl_type::device_type device_type;
|
||||
typedef typename impl_type::buffer_type buffer_type;
|
||||
typedef typename detail::codecvt_holder<Codecvt>::codecvt_type codecvt_type;
|
||||
typedef typename detail::codecvt_intern<Codecvt>::type intern_type;
|
||||
typedef typename detail::codecvt_extern<Codecvt>::type extern_type;
|
||||
typedef typename detail::codecvt_state<Codecvt>::type state_type;
|
||||
public:
|
||||
typedef intern_type char_type;
|
||||
struct category
|
||||
: impl_type::mode, device_tag, closable_tag, localizable_tag
|
||||
{ };
|
||||
BOOST_STATIC_ASSERT((
|
||||
is_same<
|
||||
extern_type,
|
||||
BOOST_DEDUCED_TYPENAME char_type_of<Device>::type
|
||||
>::value
|
||||
));
|
||||
public:
|
||||
code_converter() { }
|
||||
#if BOOST_WORKAROUND(__GNUC__, < 3)
|
||||
code_converter(code_converter& rhs)
|
||||
: code_converter_base<Device, Codecvt, Alloc>(rhs)
|
||||
{ }
|
||||
code_converter(const code_converter& rhs)
|
||||
: code_converter_base<Device, Codecvt, Alloc>(rhs)
|
||||
{ }
|
||||
#endif
|
||||
BOOST_IOSTREAMS_FORWARD( code_converter, open_impl, Device,
|
||||
BOOST_IOSTREAMS_CONVERTER_PARAMS,
|
||||
BOOST_IOSTREAMS_CONVERTER_ARGS )
|
||||
|
||||
// fstream-like interface.
|
||||
|
||||
bool is_open() const { return this->pimpl_->is_open(); }
|
||||
void close(BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out )
|
||||
{ impl().close(which); }
|
||||
|
||||
// Device interface.
|
||||
|
||||
std::streamsize read(char_type*, std::streamsize);
|
||||
std::streamsize write(const char_type*, std::streamsize);
|
||||
void imbue(const std::locale& loc) { impl().cvt_.imbue(loc); }
|
||||
|
||||
// Direct device access.
|
||||
|
||||
Device& operator*() { return detail::unwrap_direct(dev()); }
|
||||
Device* operator->() { return &detail::unwrap_direct(dev()); }
|
||||
private:
|
||||
template<typename T> // Used for forwarding.
|
||||
void open_impl(const T& t BOOST_IOSTREAMS_CONVERTER_PARAMS())
|
||||
{
|
||||
impl().open(t BOOST_IOSTREAMS_CONVERTER_ARGS());
|
||||
}
|
||||
|
||||
const codecvt_type& cvt() { return impl().cvt_.get(); }
|
||||
device_type& dev() { return impl().dev(); }
|
||||
buffer_type& in() { return impl().buf_.first(); }
|
||||
buffer_type& out() { return impl().buf_.second(); }
|
||||
impl_type& impl() { return *this->pimpl_; }
|
||||
};
|
||||
|
||||
//--------------Implementation of converter-----------------------------------//
|
||||
|
||||
// Implementation note: if end of stream contains a partial character,
|
||||
// it is ignored.
|
||||
template<typename Device, typename Codevt, typename Alloc>
|
||||
std::streamsize code_converter<Device, Codevt, Alloc>::read
|
||||
(char_type* s, std::streamsize n)
|
||||
{
|
||||
const extern_type* next; // Next external char.
|
||||
intern_type* nint; // Next internal char.
|
||||
std::streamsize total = 0; // Characters read.
|
||||
int status = iostreams::char_traits<char>::good();
|
||||
bool partial = false;
|
||||
buffer_type& buf = in();
|
||||
|
||||
do {
|
||||
|
||||
// Fill buffer.
|
||||
if (buf.ptr() == buf.eptr() || partial) {
|
||||
status = buf.fill(dev());
|
||||
if (buf.ptr() == buf.eptr())
|
||||
break;
|
||||
partial = false;
|
||||
}
|
||||
|
||||
// Convert.
|
||||
std::codecvt_base::result result =
|
||||
cvt().in( buf.state(),
|
||||
buf.ptr(), buf.eptr(), next,
|
||||
s + total, s + n, nint );
|
||||
buf.ptr() += next - buf.ptr();
|
||||
total = static_cast<std::streamsize>(nint - s);
|
||||
|
||||
switch (result) {
|
||||
case std::codecvt_base::partial:
|
||||
partial = true;
|
||||
break;
|
||||
case std::codecvt_base::ok:
|
||||
break;
|
||||
case std::codecvt_base::noconv:
|
||||
{
|
||||
std::streamsize amt =
|
||||
std::min<std::streamsize>(next - buf.ptr(), n - total);
|
||||
detail::strncpy_if_same(s + total, buf.ptr(), amt);
|
||||
total += amt;
|
||||
}
|
||||
break;
|
||||
case std::codecvt_base::error:
|
||||
default:
|
||||
buf.state() = state_type();
|
||||
boost::throw_exception(code_conversion_error());
|
||||
}
|
||||
|
||||
} while (total < n && status != EOF && status != WOULD_BLOCK);
|
||||
|
||||
return total == 0 && status == EOF ? -1 : total;
|
||||
}
|
||||
|
||||
template<typename Device, typename Codevt, typename Alloc>
|
||||
std::streamsize code_converter<Device, Codevt, Alloc>::write
|
||||
(const char_type* s, std::streamsize n)
|
||||
{
|
||||
buffer_type& buf = out();
|
||||
extern_type* next; // Next external char.
|
||||
const intern_type* nint; // Next internal char.
|
||||
std::streamsize total = 0; // Characters written.
|
||||
bool partial = false;
|
||||
|
||||
while (total < n) {
|
||||
|
||||
// Empty buffer.
|
||||
if (buf.eptr() == buf.end() || partial) {
|
||||
if (!buf.flush(dev()))
|
||||
break;
|
||||
partial = false;
|
||||
}
|
||||
|
||||
// Convert.
|
||||
std::codecvt_base::result result =
|
||||
cvt().out( buf.state(),
|
||||
s + total, s + n, nint,
|
||||
buf.eptr(), buf.end(), next );
|
||||
int progress = (int) (next - buf.eptr());
|
||||
buf.eptr() += progress;
|
||||
|
||||
switch (result) {
|
||||
case std::codecvt_base::partial:
|
||||
partial = true; // Fall through.
|
||||
case std::codecvt_base::ok:
|
||||
total = static_cast<std::streamsize>(nint - s);
|
||||
break;
|
||||
case std::codecvt_base::noconv:
|
||||
{
|
||||
std::streamsize amt =
|
||||
std::min<std::streamsize>( nint - total - s,
|
||||
buf.end() - buf.eptr() );
|
||||
detail::strncpy_if_same(buf.eptr(), s + total, amt);
|
||||
total += amt;
|
||||
}
|
||||
break;
|
||||
case std::codecvt_base::error:
|
||||
default:
|
||||
buf.state() = state_type();
|
||||
boost::throw_exception(code_conversion_error());
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
} } // End namespaces iostreams, boost.
|
||||
|
||||
#include <boost/iostreams/detail/config/enable_warnings.hpp> // Borland 5.x
|
||||
|
||||
#endif // #ifndef BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED
|
||||
Reference in New Issue
Block a user