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_STREAMBUF_HPP_INCLUDED Chris@16: #define BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_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 Chris@16: #include Chris@16: #include Chris@16: #include // pair. Chris@16: #include // BOOST_DEDUCED_TYPENAME, Chris@16: #include // member template friends. 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: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // Must come last. Chris@16: #include // MSVC. Chris@16: Chris@16: namespace boost { namespace iostreams { Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template< typename T, Chris@16: typename Tr = Chris@16: BOOST_IOSTREAMS_CHAR_TRAITS( Chris@16: BOOST_DEDUCED_TYPENAME char_type_of::type Chris@16: ) > Chris@16: class direct_streambuf Chris@16: : public linked_streambuf::type, Tr> Chris@16: { Chris@16: public: Chris@16: typedef typename char_type_of::type char_type; Chris@16: BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) Chris@16: private: Chris@16: typedef linked_streambuf base_type; Chris@16: typedef typename category_of::type category; Chris@16: typedef BOOST_IOSTREAMS_BASIC_STREAMBUF( Chris@16: char_type, traits_type Chris@16: ) streambuf_type; Chris@16: public: // stream needs access. Chris@16: void open(const T& t, std::streamsize buffer_size, Chris@16: std::streamsize pback_size); Chris@16: bool is_open() const; Chris@16: void close(); Chris@16: bool auto_close() const { return auto_close_; } Chris@16: void set_auto_close(bool close) { auto_close_ = close; } Chris@16: bool strict_sync() { return true; } Chris@16: Chris@16: // Declared in linked_streambuf. Chris@16: T* component() { return storage_.get(); } Chris@16: protected: Chris@16: #if !BOOST_WORKAROUND(__GNUC__, == 2) Chris@16: BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type) Chris@16: #endif Chris@16: direct_streambuf(); Chris@16: Chris@16: //--------------Virtual functions-----------------------------------------// Chris@16: Chris@16: // Declared in linked_streambuf. Chris@16: void close_impl(BOOST_IOS::openmode m); Chris@16: const std::type_info& component_type() const { return typeid(T); } Chris@16: void* component_impl() { return component(); } Chris@16: #ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES Chris@16: public: Chris@16: #endif Chris@16: Chris@16: // Declared in basic_streambuf. Chris@16: int_type underflow(); Chris@16: int_type pbackfail(int_type c); Chris@16: int_type overflow(int_type c); Chris@16: pos_type seekoff( off_type off, BOOST_IOS::seekdir way, Chris@16: BOOST_IOS::openmode which ); Chris@16: pos_type seekpos(pos_type sp, BOOST_IOS::openmode which); Chris@16: private: Chris@16: pos_type seek_impl( stream_offset off, BOOST_IOS::seekdir way, Chris@16: BOOST_IOS::openmode which ); Chris@16: void init_input(any_tag) { } Chris@16: void init_input(input); Chris@16: void init_output(any_tag) { } Chris@16: void init_output(output); Chris@16: void init_get_area(); Chris@16: void init_put_area(); Chris@16: bool one_head() const; Chris@16: bool two_head() const; Chris@16: optional storage_; Chris@16: char_type *ibeg_, *iend_, *obeg_, *oend_; Chris@16: bool auto_close_; Chris@16: }; Chris@16: Chris@16: //------------------Implementation of direct_streambuf------------------------// Chris@16: Chris@16: template Chris@16: direct_streambuf::direct_streambuf() Chris@16: : ibeg_(0), iend_(0), obeg_(0), oend_(0), auto_close_(true) Chris@16: { this->set_true_eof(true); } Chris@16: Chris@16: template Chris@16: void direct_streambuf::open Chris@16: (const T& t, std::streamsize, std::streamsize) Chris@16: { Chris@16: storage_.reset(t); Chris@16: init_input(category()); Chris@16: init_output(category()); Chris@16: setg(0, 0, 0); Chris@16: setp(0, 0); Chris@16: this->set_needs_close(); Chris@16: } Chris@16: Chris@16: template Chris@16: bool direct_streambuf::is_open() const Chris@16: { return ibeg_ != 0 || obeg_ != 0; } Chris@16: Chris@16: template Chris@16: void direct_streambuf::close() Chris@16: { Chris@16: base_type* self = this; Chris@16: detail::execute_all( detail::call_member_close(*self, BOOST_IOS::in), Chris@16: detail::call_member_close(*self, BOOST_IOS::out), Chris@16: detail::call_reset(storage_) ); Chris@16: } Chris@16: Chris@16: template Chris@16: typename direct_streambuf::int_type Chris@16: direct_streambuf::underflow() Chris@16: { Chris@16: if (!ibeg_) Chris@16: boost::throw_exception(cant_read()); Chris@16: if (!gptr()) Chris@16: init_get_area(); Chris@16: return gptr() != iend_ ? Chris@16: traits_type::to_int_type(*gptr()) : Chris@16: traits_type::eof(); Chris@16: } Chris@16: Chris@16: template Chris@16: typename direct_streambuf::int_type Chris@16: direct_streambuf::pbackfail(int_type c) Chris@16: { Chris@16: using namespace std; Chris@16: if (!ibeg_) Chris@16: boost::throw_exception(cant_read()); Chris@16: if (gptr() != 0 && gptr() != ibeg_) { Chris@16: gbump(-1); Chris@16: if (!traits_type::eq_int_type(c, traits_type::eof())) Chris@16: *gptr() = traits_type::to_char_type(c); Chris@16: return traits_type::not_eof(c); Chris@16: } Chris@16: boost::throw_exception(bad_putback()); Chris@16: } Chris@16: Chris@16: template Chris@16: typename direct_streambuf::int_type Chris@16: direct_streambuf::overflow(int_type c) Chris@16: { Chris@16: using namespace std; Chris@16: if (!obeg_) Chris@16: boost::throw_exception(BOOST_IOSTREAMS_FAILURE("no write access")); Chris@16: if (!pptr()) init_put_area(); Chris@16: if (!traits_type::eq_int_type(c, traits_type::eof())) { Chris@16: if (pptr() == oend_) Chris@16: boost::throw_exception( Chris@16: BOOST_IOSTREAMS_FAILURE("write area exhausted") Chris@16: ); Chris@16: *pptr() = traits_type::to_char_type(c); Chris@16: pbump(1); Chris@16: return c; Chris@16: } Chris@16: return traits_type::not_eof(c); Chris@16: } Chris@16: Chris@16: template Chris@16: inline typename direct_streambuf::pos_type Chris@16: direct_streambuf::seekoff Chris@16: (off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) Chris@16: { return seek_impl(off, way, which); } Chris@16: Chris@16: template Chris@16: inline typename direct_streambuf::pos_type Chris@16: direct_streambuf::seekpos Chris@16: (pos_type sp, BOOST_IOS::openmode which) Chris@16: { Chris@16: return seek_impl(position_to_offset(sp), BOOST_IOS::beg, which); Chris@16: } Chris@16: Chris@16: template Chris@16: void direct_streambuf::close_impl(BOOST_IOS::openmode which) Chris@16: { Chris@16: if (which == BOOST_IOS::in && ibeg_ != 0) { Chris@16: setg(0, 0, 0); Chris@16: ibeg_ = iend_ = 0; Chris@16: } Chris@16: if (which == BOOST_IOS::out && obeg_ != 0) { Chris@16: sync(); Chris@16: setp(0, 0); Chris@16: obeg_ = oend_ = 0; Chris@16: } Chris@16: boost::iostreams::close(*storage_, which); Chris@16: } Chris@16: Chris@16: template Chris@16: typename direct_streambuf::pos_type direct_streambuf::seek_impl Chris@16: (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) Chris@16: { Chris@16: using namespace std; Chris@16: BOOST_IOS::openmode both = BOOST_IOS::in | BOOST_IOS::out; Chris@16: if (two_head() && (which & both) == both) Chris@16: boost::throw_exception(bad_seek()); Chris@16: stream_offset result = -1; Chris@16: bool one = one_head(); Chris@16: if (one && (pptr() != 0 || gptr()== 0)) Chris@16: init_get_area(); // Switch to input mode, for code reuse. Chris@16: if (one || ((which & BOOST_IOS::in) != 0 && ibeg_ != 0)) { Chris@16: if (!gptr()) setg(ibeg_, ibeg_, iend_); Chris@16: ptrdiff_t next = 0; Chris@16: switch (way) { Chris@16: case BOOST_IOS::beg: next = off; break; Chris@16: case BOOST_IOS::cur: next = (gptr() - ibeg_) + off; break; Chris@16: case BOOST_IOS::end: next = (iend_ - ibeg_) + off; break; Chris@16: default: BOOST_ASSERT(0); Chris@16: } Chris@16: if (next < 0 || next > (iend_ - ibeg_)) Chris@16: boost::throw_exception(bad_seek()); Chris@16: setg(ibeg_, ibeg_ + next, iend_); Chris@16: result = next; Chris@16: } Chris@16: if (!one && (which & BOOST_IOS::out) != 0 && obeg_ != 0) { Chris@16: if (!pptr()) setp(obeg_, oend_); Chris@16: ptrdiff_t next = 0; Chris@16: switch (way) { Chris@16: case BOOST_IOS::beg: next = off; break; Chris@16: case BOOST_IOS::cur: next = (pptr() - obeg_) + off; break; Chris@16: case BOOST_IOS::end: next = (oend_ - obeg_) + off; break; Chris@16: default: BOOST_ASSERT(0); Chris@16: } Chris@16: if (next < 0 || next > (oend_ - obeg_)) Chris@16: boost::throw_exception(bad_seek()); Chris@16: pbump(static_cast(next - (pptr() - obeg_))); Chris@16: result = next; Chris@16: } Chris@16: return offset_to_position(result); Chris@16: } Chris@16: Chris@16: template Chris@16: void direct_streambuf::init_input(input) Chris@16: { Chris@16: std::pair p = input_sequence(*storage_); Chris@16: ibeg_ = p.first; Chris@16: iend_ = p.second; Chris@16: } Chris@16: Chris@16: template Chris@16: void direct_streambuf::init_output(output) Chris@16: { Chris@16: std::pair p = output_sequence(*storage_); Chris@16: obeg_ = p.first; Chris@16: oend_ = p.second; Chris@16: } Chris@16: Chris@16: template Chris@16: void direct_streambuf::init_get_area() Chris@16: { Chris@16: setg(ibeg_, ibeg_, iend_); Chris@16: if (one_head() && pptr()) { Chris@16: gbump(static_cast(pptr() - obeg_)); Chris@16: setp(0, 0); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: void direct_streambuf::init_put_area() Chris@16: { Chris@16: setp(obeg_, oend_); Chris@16: if (one_head() && gptr()) { Chris@16: pbump(static_cast(gptr() - ibeg_)); Chris@16: setg(0, 0, 0); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool direct_streambuf::one_head() const Chris@16: { return ibeg_ && obeg_ && ibeg_ == obeg_; } Chris@16: Chris@16: template Chris@16: inline bool direct_streambuf::two_head() const Chris@16: { return ibeg_ && obeg_ && ibeg_ != obeg_; } Chris@16: Chris@16: //----------------------------------------------------------------------------// Chris@16: Chris@16: } // End namespace detail. Chris@16: Chris@16: } } // End namespaces iostreams, boost. Chris@16: Chris@16: #include // MSVC Chris@16: Chris@16: #endif // #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED