Chris@16: // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) Chris@16: // (C) Copyright 2003-2007 Jonathan Turkanis Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) Chris@16: Chris@16: // See http://www.boost.org/libs/iostreams for documentation. Chris@16: Chris@16: #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_ADAPTER_HPP_INCLUDED Chris@16: #define BOOST_IOSTREAMS_DETAIL_DIRECT_ADAPTER_HPP_INCLUDED Chris@16: Chris@16: #if defined(_MSC_VER) && (_MSC_VER >= 1020) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include // SFINAE, MSVC, put ptrdiff_t in std. Chris@16: #include // copy, min. Chris@16: #include // ptrdiff_t. Chris@16: #include Chris@16: #include Chris@16: #include // forwarding. Chris@16: #include // locale. Chris@16: #include Chris@16: #include Chris@16: #include // openmode, seekdir, int types. Chris@16: #include // mode_of, is_direct. Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // Must come last. Chris@16: #include // VC7.1 Chris@16: Chris@16: namespace boost { namespace iostreams { namespace detail { Chris@16: Chris@16: //------------------Definition of direct_adapter_base-------------------------// Chris@16: Chris@16: // Put all initialization in base class to faciliate forwarding. Chris@16: template Chris@16: class direct_adapter_base { Chris@16: public: Chris@16: typedef typename char_type_of::type char_type; Chris@16: typedef typename mode_of::type mode_type; Chris@16: struct category Chris@16: : mode_type, Chris@16: device_tag, Chris@16: closable_tag Chris@16: #ifndef BOOST_IOSTREAMS_NO_LOCALE Chris@16: , localizable_tag Chris@16: #endif Chris@16: { }; Chris@16: protected: Chris@16: explicit direct_adapter_base(const Direct& d); Chris@16: typedef is_convertible is_double; Chris@16: struct pointers { Chris@16: char_type *beg, *ptr, *end; Chris@16: }; Chris@16: void init_input(mpl::true_); Chris@16: void init_input(mpl::false_) { } Chris@16: void init_output(mpl::true_); Chris@16: void init_output(mpl::false_) { } Chris@16: double_object ptrs_; Chris@16: Direct d_; Chris@16: }; Chris@16: Chris@16: template Chris@16: class direct_adapter : private direct_adapter_base { Chris@16: private: Chris@16: typedef direct_adapter_base base_type; Chris@16: typedef typename base_type::pointers pointers; Chris@16: typedef typename base_type::is_double is_double; Chris@16: using base_type::ptrs_; Chris@16: using base_type::d_; Chris@16: public: Chris@16: typedef typename base_type::char_type char_type; Chris@16: typedef typename base_type::category category; Chris@16: Chris@16: // Constructors Chris@16: Chris@16: #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1310) Chris@16: direct_adapter(const Direct& d) : base_type(d) { } Chris@16: direct_adapter(const direct_adapter& d) : base_type(d) { } Chris@16: # define BOOST_PP_LOCAL_LIMITS (1, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY) Chris@16: #else Chris@16: template Chris@16: struct is_direct Chris@16: : mpl::or_< Chris@16: is_same >, Chris@16: is_same Chris@16: > Chris@16: { }; Chris@16: template Chris@16: direct_adapter(const U& u) Chris@16: : base_type(forward(u, is_direct())) Chris@16: { } Chris@16: # define BOOST_PP_LOCAL_LIMITS (2, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY) Chris@16: #endif Chris@16: Chris@16: #define BOOST_PP_LOCAL_MACRO(n) \ Chris@16: template \ Chris@16: direct_adapter(BOOST_PP_ENUM_BINARY_PARAMS(n, const P, &p)) \ Chris@16: : base_type(Direct(BOOST_PP_ENUM_PARAMS(n, p))) \ Chris@16: { } \ Chris@16: /**/ Chris@16: #include BOOST_PP_LOCAL_ITERATE() Chris@16: #undef BOOST_PP_LOCAL_MACRO Chris@16: Chris@16: // Device interface. Chris@16: Chris@16: std::streamsize read(char_type* s, std::streamsize n); Chris@16: std::streamsize write(const char_type* s, std::streamsize n); Chris@16: std::streampos seek( stream_offset, BOOST_IOS::seekdir, Chris@16: BOOST_IOS::openmode = BOOST_IOS::in | BOOST_IOS::out ); Chris@16: void close(); Chris@16: void close(BOOST_IOS::openmode which); Chris@16: #ifndef BOOST_IOSTREAMS_NO_LOCALE Chris@16: void imbue(const std::locale&); Chris@16: #endif Chris@16: Chris@16: // Direct device access. Chris@16: Chris@16: Direct& operator*() { return d_; } Chris@16: Direct* operator->() { return &d_; } Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310) Chris@16: private: Chris@16: template Chris@16: static Direct forward(const U& u, mpl::true_) { return u; } Chris@16: template Chris@16: static Direct forward(const U& u, mpl::false_) { return Direct(u); } Chris@16: #endif Chris@16: }; Chris@16: Chris@16: //--------------Definition of wrap_direct and unwrap_direct-------------------// Chris@16: Chris@16: template Chris@16: struct wrap_direct_traits Chris@16: : mpl::if_< Chris@16: is_direct, Chris@16: direct_adapter, Chris@16: Device Chris@16: > Chris@16: { }; Chris@16: Chris@16: template Chris@16: typename wrap_direct_traits::type Chris@16: inline wrap_direct(Device dev) Chris@16: { Chris@16: typedef typename wrap_direct_traits::type type; Chris@16: return type(dev); Chris@16: } Chris@16: Chris@16: template Chris@16: inline Device& unwrap_direct(Device& d) { return d; } Chris@16: Chris@16: template Chris@16: inline Device& unwrap_direct(direct_adapter& d) { return *d; } Chris@16: Chris@16: //--------------Implementation of direct_adapter_base-------------------------// Chris@16: Chris@16: template Chris@16: direct_adapter_base::direct_adapter_base(const Direct& d) : d_(d) Chris@16: { Chris@16: init_input(is_convertible()); Chris@16: init_output(is_convertible()); Chris@16: } Chris@16: Chris@16: template Chris@16: void direct_adapter_base::init_input(mpl::true_) Chris@16: { Chris@16: std::pair seq = iostreams::input_sequence(d_); Chris@16: ptrs_.first().beg = seq.first; Chris@16: ptrs_.first().ptr = seq.first; Chris@16: ptrs_.first().end = seq.second; Chris@16: } Chris@16: Chris@16: template Chris@16: void direct_adapter_base::init_output(mpl::true_) Chris@16: { Chris@16: std::pair seq = iostreams::output_sequence(d_); Chris@16: ptrs_.second().beg = seq.first; Chris@16: ptrs_.second().ptr = seq.first; Chris@16: ptrs_.second().end = seq.second; Chris@16: } Chris@16: Chris@16: //--------------Implementation of direct_adapter------------------------------// Chris@16: Chris@16: template Chris@16: inline std::streamsize direct_adapter::read Chris@16: (char_type* s, std::streamsize n) Chris@16: { Chris@16: using namespace std; Chris@16: pointers& get = ptrs_.first(); Chris@16: std::streamsize avail = Chris@16: static_cast(get.end - get.ptr); Chris@16: std::streamsize result = (std::min)(n, avail); Chris@16: std::copy(get.ptr, get.ptr + result, s); Chris@16: get.ptr += result; Chris@16: return result != 0 ? result : -1; Chris@16: } Chris@16: Chris@16: template Chris@16: inline std::streamsize direct_adapter::write Chris@16: (const char_type* s, std::streamsize n) Chris@16: { Chris@16: using namespace std; Chris@16: pointers& put = ptrs_.second(); Chris@16: if (n > static_cast(put.end - put.ptr)) Chris@16: boost::throw_exception(write_area_exhausted()); Chris@16: std::copy(s, s + n, put.ptr); Chris@16: put.ptr += n; Chris@16: return n; Chris@16: } Chris@16: Chris@16: template Chris@16: inline std::streampos direct_adapter::seek Chris@16: ( stream_offset off, BOOST_IOS::seekdir way, Chris@16: BOOST_IOS::openmode which ) Chris@16: { Chris@16: using namespace std; Chris@16: pointers& get = ptrs_.first(); Chris@16: pointers& put = ptrs_.second(); Chris@16: if (way == BOOST_IOS::cur && get.ptr != put.ptr) Chris@16: boost::throw_exception(bad_seek()); Chris@16: ptrdiff_t next = 0; Chris@16: if ((which & BOOST_IOS::in) || !is_double::value) { Chris@16: if (way == BOOST_IOS::beg) Chris@16: next = off; Chris@16: else if (way == BOOST_IOS::cur) Chris@16: next = get.ptr - get.beg + off; Chris@16: else Chris@16: next = get.end - get.beg + off; Chris@16: if (next >= 0 && next <= get.end - get.beg) Chris@16: get.ptr = get.beg + next; Chris@16: else Chris@16: boost::throw_exception(bad_seek()); Chris@16: } Chris@16: if ((which & BOOST_IOS::out) && is_double::value) { Chris@16: if (way == BOOST_IOS::beg) Chris@16: next = off; Chris@16: else if (way == BOOST_IOS::cur) Chris@16: next = put.ptr - put.beg + off; Chris@16: else Chris@16: next = put.end - put.beg + off; Chris@16: if (next >= 0 && next <= put.end - put.beg) Chris@16: put.ptr = put.beg + next; Chris@16: else Chris@16: boost::throw_exception(bad_seek()); Chris@16: } Chris@16: return offset_to_position(next); Chris@16: } Chris@16: Chris@16: template Chris@16: void direct_adapter::close() Chris@16: { Chris@16: BOOST_STATIC_ASSERT((!is_convertible::value)); Chris@16: detail::close_all(d_); Chris@16: } Chris@16: Chris@16: template Chris@16: void direct_adapter::close(BOOST_IOS::openmode which) Chris@16: { Chris@16: BOOST_STATIC_ASSERT((is_convertible::value)); Chris@16: boost::iostreams::close(d_, which); Chris@16: } Chris@16: Chris@16: #ifndef BOOST_IOSTREAMS_NO_LOCALE Chris@16: template Chris@16: void direct_adapter::imbue(const std::locale& loc) Chris@16: { boost::iostreams::imbue(d_, loc); } Chris@16: #endif Chris@16: Chris@16: } } } // End namespaces detail, iostreams, boost. Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_ADAPTER_HPP_INCLUDED