1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ossrv_pub/boost_apis/boost/iostreams/code_converter.hpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,394 @@
1.4 +// (C) Copyright Jonathan Turkanis 2003.
1.5 +// Distributed under the Boost Software License, Version 1.0. (See accompanying
1.6 +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
1.7 +
1.8 +// See http://www.boost.org/libs/iostreams for documentation.
1.9 +
1.10 +// Contains machinery for performing code conversion.
1.11 +
1.12 +#ifndef BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED
1.13 +#define BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED
1.14 +
1.15 +#if defined(_MSC_VER) && (_MSC_VER >= 1020)
1.16 +# pragma once
1.17 +#endif
1.18 +
1.19 +#include <boost/iostreams/detail/config/wide_streams.hpp>
1.20 +#if defined(BOOST_IOSTREAMS_NO_WIDE_STREAMS) || \
1.21 + defined(BOOST_IOSTREAMS_NO_LOCALE) \
1.22 + /**/
1.23 +# error code conversion not supported on this platform
1.24 +#endif
1.25 +
1.26 +#include <algorithm> // max.
1.27 +#include <cstring> // memcpy.
1.28 +#include <exception>
1.29 +#include <boost/config.hpp> // DEDUCED_TYPENAME.
1.30 +#include <boost/iostreams/char_traits.hpp>
1.31 +#include <boost/iostreams/constants.hpp> // default_filter_buffer_size.
1.32 +#include <boost/iostreams/detail/adapter/concept_adapter.hpp>
1.33 +#include <boost/iostreams/detail/adapter/direct_adapter.hpp>
1.34 +#include <boost/iostreams/detail/buffer.hpp>
1.35 +#include <boost/iostreams/detail/call_traits.hpp>
1.36 +#include <boost/iostreams/detail/codecvt_holder.hpp>
1.37 +#include <boost/iostreams/detail/codecvt_helper.hpp>
1.38 +#include <boost/iostreams/detail/double_object.hpp>
1.39 +#include <boost/iostreams/detail/forward.hpp>
1.40 +#include <boost/iostreams/detail/ios.hpp> // failure, openmode, int types.
1.41 +#include <boost/iostreams/detail/select.hpp>
1.42 +#include <boost/iostreams/traits.hpp>
1.43 +#include <boost/iostreams/operations.hpp>
1.44 +#include <boost/optional.hpp>
1.45 +#include <boost/shared_ptr.hpp>
1.46 +#include <boost/static_assert.hpp>
1.47 +#include <boost/type_traits/is_convertible.hpp>
1.48 +#include <boost/type_traits/is_same.hpp>
1.49 +
1.50 +// Must come last.
1.51 +#include <boost/iostreams/detail/config/disable_warnings.hpp> // Borland 5.x
1.52 +
1.53 +namespace boost { namespace iostreams {
1.54 +
1.55 +struct code_conversion_error : BOOST_IOSTREAMS_FAILURE {
1.56 + code_conversion_error()
1.57 + : BOOST_IOSTREAMS_FAILURE("code conversion error")
1.58 + { }
1.59 +};
1.60 +
1.61 +namespace detail {
1.62 +
1.63 +//--------------Definition of conversion_buffer-------------------------------//
1.64 +
1.65 +// Buffer and conversion state for reading.
1.66 +template<typename Codecvt, typename Alloc>
1.67 +class conversion_buffer
1.68 + : public buffer<
1.69 + BOOST_DEDUCED_TYPENAME detail::codecvt_extern<Codecvt>::type,
1.70 + Alloc
1.71 + >
1.72 +{
1.73 +public:
1.74 + typedef typename Codecvt::state_type state_type;
1.75 + conversion_buffer()
1.76 + : buffer<
1.77 + BOOST_DEDUCED_TYPENAME detail::codecvt_extern<Codecvt>::type,
1.78 + Alloc
1.79 + >(0)
1.80 + {
1.81 + reset();
1.82 + }
1.83 + state_type& state() { return state_; }
1.84 + void reset()
1.85 + {
1.86 + if (this->size())
1.87 + this->set(0, 0);
1.88 + state_ = state_type();
1.89 + }
1.90 +private:
1.91 + state_type state_;
1.92 +};
1.93 +
1.94 +//--------------Definition of converter_impl----------------------------------//
1.95 +
1.96 +// Contains member data, open/is_open/close and buffer management functions.
1.97 +template<typename Device, typename Codecvt, typename Alloc>
1.98 +struct code_converter_impl {
1.99 + typedef typename codecvt_extern<Codecvt>::type extern_type;
1.100 + typedef typename category_of<Device>::type device_category;
1.101 + typedef is_convertible<device_category, input> can_read;
1.102 + typedef is_convertible<device_category, output> can_write;
1.103 + typedef is_convertible<device_category, bidirectional> is_bidir;
1.104 + typedef typename
1.105 + iostreams::select< // Disambiguation for Tru64.
1.106 + is_bidir, bidirectional,
1.107 + can_read, input,
1.108 + can_write, output
1.109 + >::type mode;
1.110 + typedef typename
1.111 + mpl::if_<
1.112 + is_direct<Device>,
1.113 + direct_adapter<Device>,
1.114 + Device
1.115 + >::type policy_type;
1.116 + typedef optional< concept_adapter<policy_type> > storage_type;
1.117 + typedef is_convertible<device_category, two_sequence> is_double;
1.118 + typedef conversion_buffer<Codecvt, Alloc> buffer_type;
1.119 +
1.120 + code_converter_impl() : cvt_(), flags_(0) { }
1.121 +
1.122 + ~code_converter_impl()
1.123 + {
1.124 + try {
1.125 + if (flags_ & f_open) close();
1.126 + } catch (std::exception&) { /* */ }
1.127 + }
1.128 +
1.129 + void open(const Device& dev, int buffer_size)
1.130 + {
1.131 + if (flags_ & f_open)
1.132 + throw BOOST_IOSTREAMS_FAILURE("already open");
1.133 + if (buffer_size == -1)
1.134 + buffer_size = default_filter_buffer_size;
1.135 + int max_length = cvt_.get().max_length();
1.136 + buffer_size = (std::max)(buffer_size, 2 * max_length);
1.137 + if (can_read::value) {
1.138 + buf_.first().resize(buffer_size);
1.139 + buf_.first().set(0, 0);
1.140 + }
1.141 + if (can_write::value && !is_double::value) {
1.142 + buf_.second().resize(buffer_size);
1.143 + buf_.second().set(0, 0);
1.144 + }
1.145 + dev_.reset(concept_adapter<policy_type>(dev));
1.146 + flags_ |= f_open;
1.147 + }
1.148 +
1.149 + void close(BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out)
1.150 + {
1.151 + if (which & BOOST_IOS::in) {
1.152 + iostreams::close(dev(), BOOST_IOS::in);
1.153 + flags_ |= f_input_closed;
1.154 + }
1.155 + if (which & BOOST_IOS::out) {
1.156 + buf_.second().flush(dev());
1.157 + iostreams::close(dev(), BOOST_IOS::out);
1.158 + flags_ |= f_output_closed;
1.159 + }
1.160 + if ( !is_double::value ||
1.161 + (flags_ & f_input_closed) != 0 &&
1.162 + (flags_ & f_output_closed) != 0 )
1.163 + {
1.164 + dev_.reset();
1.165 + buf_.first().reset();
1.166 + buf_.second().reset();
1.167 + flags_ = 0;
1.168 + }
1.169 + }
1.170 +
1.171 + bool is_open() const { return (flags_ & f_open) != 0;}
1.172 +
1.173 + policy_type& dev() { return **dev_; }
1.174 +
1.175 + enum {
1.176 + f_open = 1,
1.177 + f_input_closed = f_open << 1,
1.178 + f_output_closed = f_input_closed << 1
1.179 + };
1.180 +
1.181 + codecvt_holder<Codecvt> cvt_;
1.182 + storage_type dev_;
1.183 + double_object<
1.184 + buffer_type,
1.185 + is_double
1.186 + > buf_;
1.187 + int flags_;
1.188 +};
1.189 +
1.190 +} // End namespace detail.
1.191 +
1.192 +//--------------Definition of converter---------------------------------------//
1.193 +
1.194 +#define BOOST_IOSTREAMS_CONVERTER_PARAMS() , int buffer_size = -1
1.195 +#define BOOST_IOSTREAMS_CONVERTER_ARGS() , buffer_size
1.196 +
1.197 +template<typename Device, typename Codecvt, typename Alloc>
1.198 +struct code_converter_base {
1.199 + typedef detail::code_converter_impl<
1.200 + Device, Codecvt, Alloc
1.201 + > impl_type;
1.202 + code_converter_base() : pimpl_(new impl_type) { }
1.203 + shared_ptr<impl_type> pimpl_;
1.204 +};
1.205 +
1.206 +template< typename Device,
1.207 + typename Codecvt = detail::default_codecvt,
1.208 + typename Alloc = std::allocator<char> >
1.209 +class code_converter
1.210 + : protected code_converter_base<Device, Codecvt, Alloc>
1.211 +{
1.212 +private:
1.213 + typedef detail::code_converter_impl<
1.214 + Device, Codecvt, Alloc
1.215 + > impl_type;
1.216 + typedef typename impl_type::policy_type policy_type;
1.217 + typedef typename impl_type::buffer_type buffer_type;
1.218 + typedef typename detail::codecvt_holder<Codecvt>::codecvt_type codecvt_type;
1.219 + typedef typename detail::codecvt_intern<Codecvt>::type intern_type;
1.220 + typedef typename detail::codecvt_extern<Codecvt>::type extern_type;
1.221 + typedef typename detail::codecvt_state<Codecvt>::type state_type;
1.222 +public:
1.223 + typedef intern_type char_type;
1.224 + struct category
1.225 + : impl_type::mode, device_tag, closable_tag, localizable_tag
1.226 + { };
1.227 + BOOST_STATIC_ASSERT((
1.228 + is_same<
1.229 + extern_type,
1.230 + BOOST_DEDUCED_TYPENAME char_type_of<Device>::type
1.231 + >::value
1.232 + ));
1.233 +public:
1.234 + code_converter() { }
1.235 +#if BOOST_WORKAROUND(__GNUC__, < 3)
1.236 + code_converter(code_converter& rhs)
1.237 + : code_converter_base<Device, Codecvt, Alloc>(rhs)
1.238 + { }
1.239 + code_converter(const code_converter& rhs)
1.240 + : code_converter_base<Device, Codecvt, Alloc>(rhs)
1.241 + { }
1.242 +#endif
1.243 + BOOST_IOSTREAMS_FORWARD( code_converter, open_impl, Device,
1.244 + BOOST_IOSTREAMS_CONVERTER_PARAMS,
1.245 + BOOST_IOSTREAMS_CONVERTER_ARGS )
1.246 +
1.247 + // fstream-like interface.
1.248 +
1.249 + bool is_open() const { return this->pimpl_->is_open(); }
1.250 + void close(BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out )
1.251 + { impl().close(which); }
1.252 +
1.253 + // Device interface.
1.254 +
1.255 + std::streamsize read(char_type*, std::streamsize);
1.256 + std::streamsize write(const char_type*, std::streamsize);
1.257 + void imbue(const std::locale& loc) { impl().cvt_.imbue(loc); }
1.258 +
1.259 + // Direct device access.
1.260 +
1.261 + Device& operator*() { return detail::unwrap_direct(dev()); }
1.262 + Device* operator->() { return &detail::unwrap_direct(dev()); }
1.263 +private:
1.264 + template<typename T> // Used for forwarding.
1.265 + void open_impl(const T& t BOOST_IOSTREAMS_CONVERTER_PARAMS())
1.266 + {
1.267 + impl().open(t BOOST_IOSTREAMS_CONVERTER_ARGS());
1.268 + }
1.269 +
1.270 + const codecvt_type& cvt() { return impl().cvt_.get(); }
1.271 + policy_type& dev() { return impl().dev(); }
1.272 + buffer_type& in() { return impl().buf_.first(); }
1.273 + buffer_type& out() { return impl().buf_.second(); }
1.274 + impl_type& impl() { return *this->pimpl_; }
1.275 +};
1.276 +
1.277 +//--------------Implementation of converter-----------------------------------//
1.278 +
1.279 +// Implementation note: if end of stream contains a partial character,
1.280 +// it is ignored.
1.281 +template<typename Device, typename Codevt, typename Alloc>
1.282 +std::streamsize code_converter<Device, Codevt, Alloc>::read
1.283 + (char_type* s, std::streamsize n)
1.284 +{
1.285 + using namespace std;
1.286 + const extern_type* next; // Next external char.
1.287 + intern_type* nint; // Next internal char.
1.288 + streamsize total = 0; // Characters read.
1.289 + int status = iostreams::char_traits<char>::good();
1.290 + bool partial = false;
1.291 + buffer_type& buf = in();
1.292 +
1.293 + do {
1.294 +
1.295 + // Fill buffer.
1.296 + if (buf.ptr() == buf.eptr() || partial) {
1.297 + status = buf.fill(dev());
1.298 + if (buf.ptr() == buf.eptr())
1.299 + break;
1.300 + partial = false;
1.301 + }
1.302 +
1.303 + // Convert.
1.304 + codecvt_base::result result =
1.305 + cvt().in( buf.state(),
1.306 + buf.ptr(), buf.eptr(), next,
1.307 + s + total, s + n, nint );
1.308 + buf.ptr() += next - buf.ptr();
1.309 + total = static_cast<streamsize>(nint - s);
1.310 +
1.311 + switch (result) {
1.312 + case codecvt_base::partial:
1.313 + partial = true;
1.314 + break;
1.315 + case codecvt_base::ok:
1.316 + break;
1.317 + case codecvt_base::error:
1.318 + buf.state() = state_type();
1.319 + throw code_conversion_error();
1.320 + case codecvt_base::noconv:
1.321 + default:
1.322 + buf.state() = state_type();
1.323 + intern_type c = intern_type();
1.324 + memcpy(&c, (const void*) buf.ptr(), sizeof(extern_type));
1.325 + s[total++] = c;
1.326 + break;
1.327 + }
1.328 +
1.329 + } while (total < n && status != EOF && status != WOULD_BLOCK);
1.330 +
1.331 + return total == 0 && status == EOF ? -1 : total;
1.332 +}
1.333 +
1.334 +template<typename Device, typename Codevt, typename Alloc>
1.335 +std::streamsize code_converter<Device, Codevt, Alloc>::write
1.336 + (const char_type* s, std::streamsize n)
1.337 +{
1.338 + using namespace std;
1.339 + buffer_type& buf = out();
1.340 + extern_type* next; // Next external char.
1.341 + const intern_type* nint; // Next internal char.
1.342 + streamsize total = 0; // Characters written.
1.343 + bool partial = false;
1.344 +
1.345 + while (total < n) {
1.346 +
1.347 + // Empty buffer.
1.348 + if (buf.eptr() == buf.end() || partial) {
1.349 + if (!buf.flush(dev()))
1.350 + break;
1.351 + partial = false;
1.352 + }
1.353 +
1.354 + // Convert.
1.355 + codecvt_base::result result =
1.356 + cvt().out( buf.state(),
1.357 + s + total, s + n, nint,
1.358 + buf.eptr(), buf.end(), next );
1.359 + int progress = (int) (next - buf.eptr());
1.360 + buf.eptr() += progress;
1.361 +
1.362 + switch (result) {
1.363 + case codecvt_base::partial:
1.364 + partial = true; // Fall through.
1.365 + case codecvt_base::ok:
1.366 + total = static_cast<streamsize>(nint - s);
1.367 + break;
1.368 + case codecvt_base::error:
1.369 + buf.state() = state_type();
1.370 + throw code_conversion_error();
1.371 + case codecvt_base::noconv:
1.372 + {
1.373 + // This can be shortened to two memcpy's.
1.374 + const char* c = (const char*) (s + total);
1.375 + for ( std::size_t index = 0;
1.376 + index < sizeof(intern_type);
1.377 + index += sizeof(extern_type),
1.378 + ++buf.ptr() )
1.379 + {
1.380 + memcpy(buf.ptr(), c + index, sizeof(extern_type));
1.381 + if (buf.eptr() == buf.end())
1.382 + buf.flush(dev());
1.383 + }
1.384 + ++total;
1.385 + }
1.386 + }
1.387 + }
1.388 + return total;
1.389 +}
1.390 +
1.391 +//----------------------------------------------------------------------------//
1.392 +
1.393 +} } // End namespaces iostreams, boost.
1.394 +
1.395 +#include <boost/iostreams/detail/config/enable_warnings.hpp> // Borland 5.x
1.396 +
1.397 +#endif // #ifndef BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED