From 87ffdc6697411e08dea5331fe45cde51837a7c1e Mon Sep 17 00:00:00 2001 From: Jonathan Turkanis Date: Thu, 26 May 2005 08:53:25 +0000 Subject: [PATCH] initial commitment [SVN r29217] --- include/boost/iostreams/invert.hpp | 162 +++++++++++ include/boost/iostreams/restrict.hpp | 418 +++++++++++++++++++++++++++ 2 files changed, 580 insertions(+) create mode 100755 include/boost/iostreams/invert.hpp create mode 100755 include/boost/iostreams/restrict.hpp diff --git a/include/boost/iostreams/invert.hpp b/include/boost/iostreams/invert.hpp new file mode 100755 index 0000000..0395ceb --- /dev/null +++ b/include/boost/iostreams/invert.hpp @@ -0,0 +1,162 @@ +// (C) Copyright Jonathan Turkanis 2003. +// 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. + +#ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED +#define BOOST_IOSTREAMS_INVERT_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // copy, min. +#include +#include // BOOST_DEDUCED_TYPENAME. +#include // default_filter_buffer_size. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { + +// +// Template name: inverse. +// Template paramters: +// Filter - A filter adapter which +// Description: Returns an instance of an appropriate specialization of inverse. +// +template +class inverse { +private: + typedef typename category_of::type base_category; + typedef reference_wrapper filter_ref; +public: + typedef typename char_type_of::type char_type; + typedef typename int_type_of::type int_type; + typedef char_traits traits_type; + typedef typename + mpl::if_< + is_convertible< + base_category, + input + >, + output, + input + >::type mode; + struct category + : mode, + filter_tag, + multichar_tag, + closable_tag + { }; + explicit inverse( const Filter& filter, + std::streamsize buffer_size = + default_filter_buffer_size) + : pimpl_(new impl(filter, buffer_size)) + { } + + template + std::streamsize read(Source& src, char* s, std::streamsize n) + { + typedef detail::counted_array_sink array_sink; + typedef composite filtered_array_sink; + + assert((flags() & f_write) == 0); + if (flags() == 0) { + flags() = f_read; + buf().set(0, 0); + } + + filtered_array_sink snk(filter(), array_sink(s, n)); + int_type status; + for ( status = traits_type::good(); + snk.second().count() < n && status == traits_type::good(); ) + { + status = buf().fill(src); + buf().flush(snk); + } + return snk.second().count() == 0 && + status == traits_type::eof() + ? + -1 + : + snk.second().count(); + } + + template + std::streamsize write(Sink& dest, const char* s, std::streamsize n) + { + typedef detail::counted_array_source array_source; + typedef composite filtered_array_source; + + assert((flags() & f_read) == 0); + if (flags() == 0) { + flags() = f_write; + buf().set(0, 0); + } + + filtered_array_source src(filter(), array_source(s, n)); + for (bool good = true; src.second().count() < n && good; ) { + buf().fill(src); + good = buf().flush(dest); + } + return src.second().count(); + } + + template + void close( Device& dev, + BOOST_IOS::openmode which = + BOOST_IOS::in | BOOST_IOS::out ) + { + if ((which & BOOST_IOS::out) != 0 && (flags() & f_write) != 0) + buf().flush(dev); + flags() = 0; + } +private: + filter_ref filter() { return boost::ref(pimpl_->filter_); } + detail::buffer& buf() { return pimpl_->buf_; } + int& flags() { return pimpl_->flags_; } + + enum flags_ { + f_read = 1, f_write = 2 + }; + + struct impl { + impl(const Filter& filter, std::streamsize n) + : filter_(filter), buf_(n), flags_(0) + { buf_.set(0, 0); } + Filter filter_; + detail::buffer buf_; + int flags_; + }; + shared_ptr pimpl_; +}; + +// +// Template name: invert. +// Template paramters: +// Filter - A model of InputFilter or OutputFilter. +// Description: Returns an instance of an appropriate specialization of inverse. +// +template +inverse invert(const Filter& f) { return inverse(f); } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED diff --git a/include/boost/iostreams/restrict.hpp b/include/boost/iostreams/restrict.hpp new file mode 100755 index 0000000..bbc0668 --- /dev/null +++ b/include/boost/iostreams/restrict.hpp @@ -0,0 +1,418 @@ +// (C) Copyright Jonathan Turkanis 2005. +// 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. + +#ifndef BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED +#define BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // min. +#include // pair. +#include // intmax_t. +#include // DEDUCED_TYPENAME. +#include +#include +#include +#include +#include +#include +#include // failure. +#include +#include +#include +#include // mode_of, is_direct. +#include +#include +#include + +#include // VC7.1 C4244. + +namespace boost { namespace iostreams { + +namespace detail { + +// +// Template name: restricted_indirect_device. +// Description: Provides an restricted view of an indirect Device. +// Template paramters: +// Device - An indirect model of Device that models either Source or +// SeekableDevice. +// +template +class restricted_indirect_device : public basic_adapter { +private: + typedef typename detail::param_type::type param_type; +public: + typedef typename char_type_of::type char_type; + struct category + : mode_of::type, + device_tag, + closable_tag, + flushable_tag, + localizable_tag, + optimally_buffered_tag + { }; + restricted_indirect_device( param_type dev, stream_offset off, + stream_offset len = -1 ); + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + stream_offset seek(stream_offset off, BOOST_IOS::seekdir way); +private: + stream_offset beg_, pos_, end_; +}; + +// +// Template name: restricted_direct_device. +// Description: Provides an restricted view of a Direct Device. +// Template paramters: +// Device - A model of Direct and Device. +// +template +class restricted_direct_device : public basic_adapter { +public: + typedef typename char_type_of::type char_type; + typedef std::pair pair_type; + struct category + : mode_of::type, + device_tag, + direct_tag, + closable_tag, + localizable_tag + { }; + restricted_direct_device( const Device& dev, stream_offset off, + stream_offset len = -1 ); + pair_type input_sequence(); + pair_type output_sequence(); +private: + pair_type sequence(mpl::true_); + pair_type sequence(mpl::false_); + char_type *beg_, *end_; +}; + +// +// Template name: restricted_filter. +// Description: Provides an restricted view of a Filter. +// Template paramters: +// Filter - An indirect model of Filter. +// +template +class restricted_filter : public basic_adapter { +public: + typedef typename char_type_of::type char_type; + struct category + : mode_of::type, + filter_tag, + multichar_tag, + closable_tag, + localizable_tag, + optimally_buffered_tag + { }; + restricted_filter( const Filter& flt, stream_offset off, + stream_offset len = -1 ); + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + using namespace std; + if (!open_) + open(src); + streamsize amt = + end_ != -1 ? + (std::min) (n, static_cast(end_ - pos_)) : + n; + streamsize result = iostreams::read(this->component(), src, s, amt); + if (result != -1) + pos_ += result; + return result; + } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + if (!open_) + open(snk); + if (end_ != -1 && pos_ + n >= end_) + bad_write(); + std::streamsize result = + iostreams::write(this->component(), snk, s, n); + pos_ += result; + return result; + } + + template + stream_offset seek(Device& dev, stream_offset off, BOOST_IOS::seekdir way) + { + stream_offset next; + if (way == BOOST_IOS::beg) { + next = beg_ + off; + } else if (way == BOOST_IOS::cur) { + next = pos_ + off; + } else if (end_ != -1) { + next = end_ + off; + } else { + // Restriction is half-open; seek relative to the actual end. + pos_ = this->component().seek(dev, off, BOOST_IOS::end); + if (pos_ < beg_) + bad_seek(); + return pos_ - beg_; + } + if (next < beg_ || end_ != -1 && next >= end_) + bad_seek(); + pos_ = this->component().seek(dev, next, BOOST_IOS::cur); + return pos_ - beg_; + } +private: + template + void open(Device& dev) + { + open_ = true; + iostreams::skip(this->component(), dev, beg_); + } + stream_offset beg_, pos_, end_; + bool open_; +}; + +template +struct restriction_traits + : iostreams::select< // Disambiguation for Tru64. + is_filter, restricted_filter, + is_direct, restricted_direct_device, + else_, restricted_indirect_device + > + { }; + +} // End namespace detail. + +template +struct restriction : public detail::restriction_traits::type { + typedef typename detail::param_type::type param_type; + typedef typename detail::restriction_traits::type base_type; + restriction(param_type t, stream_offset off, stream_offset len = -1) + : base_type(t, off, len) + { } +}; + +//--------------Implementation of restrict------------------------------------// + +// Note: The following workarounds are patterned after resolve.hpp. It has not +// yet been confirmed that they are necessary. + +#ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //-------------------------// +# ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-------------------------------// + +template +restriction restrict( const T& t, stream_offset off, stream_offset len = -1 + BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) ) +{ return restriction(t, off, len); } + +template +restriction< std::basic_streambuf > +restrict(std::basic_streambuf& sb, stream_offset off, stream_offset len = -1) +{ return restriction< std::basic_streambuf >(sb, off, len); } + +template +restriction< std::basic_istream > +restrict(std::basic_istream& is, stream_offset off, stream_offset len = -1) +{ return restriction< std::basic_istream >(is, off, len); } + +template +restriction< std::basic_ostream > +restrict(std::basic_ostream& os, stream_offset off, stream_offset len = -1) +{ return restriction< std::basic_ostream >(os, off, len); } + +template +restriction< std::basic_iostream > +restrict(std::basic_iostream& io, stream_offset off, stream_offset len = -1) +{ return restriction< std::basic_iostream >(io, off, len); } + +# else // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //---------------------// + +template +restriction restrict( const T& t, stream_offset off, stream_offset len = -1 + BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) ) +{ return restriction(t, off, len); } + +restriction +restrict(std::streambuf& sb, stream_offset off, stream_offset len = -1) +{ return restriction(sb, off, len); } + +restriction +restrict(std::istream& is, stream_offset off, stream_offset len = -1) +{ return restriction(is, off, len); } + +restriction +restrict(std::ostream& os, stream_offset off, stream_offset len = -1) +{ return restriction(os, off, len); } + +restriction +restrict(std::iostream& io, stream_offset off, stream_offset len = -1) +{ return restriction(io, off, len); } + +# endif // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------// +#else // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //----------------// + +template +restriction +restrict(const T& t, stream_offset off, stream_offset len, mpl::true_) +{ // Bad overload resolution. + return restriction(const_cast(t, off, len)); +} + +template +restriction +restrict(const T& t, stream_offset off, stream_offset len, mpl::false_) +{ return restriction(t, off, len); } + +template +restriction +restrict( const T& t, stream_offset off, stream_offset len = -1 + BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) ) +{ return restrict(t, off, len, is_std_io()); } + +# if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && \ + !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \ + !defined(__GNUC__) // ---------------------------------------------------// + +template +restriction +restrict(T& t, stream_offset off, stream_offset len = -1) +{ return restriction(t, off, len); } + +# endif // Borland 5.x, VC6-7.0 or GCC 2.9x //--------------------------------// +#endif // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //---------------// +//----------------------------------------------------------------------------// + +namespace detail { + +//--------------Implementation of restricted_indirect_device------------------// + +template +restricted_indirect_device::restricted_indirect_device + (param_type dev, stream_offset off, stream_offset len) + : basic_adapter(dev), beg_(off), pos_(off), + end_(len != -1 ? off + len : -1) +{ + if (len < -1 || off < 0) + throw BOOST_IOSTREAMS_FAILURE("bad offset"); + iostreams::skip(this->component(), off); +} + +template +inline std::streamsize restricted_indirect_device::read + (char_type* s, std::streamsize n) +{ + using namespace std; + streamsize amt = + end_ != -1 ? + (std::min) (n, static_cast(end_ - pos_)) : + n; + streamsize result = iostreams::read(this->component(), s, amt); + if (result != -1) + pos_ += result; + return result; +} + +template +inline std::streamsize restricted_indirect_device::write + (const char_type* s, std::streamsize n) +{ + if (end_ != -1 && pos_ + n >= end_) + bad_write(); + std::streamsize result = iostreams::write(this->component(), s, n); + pos_ += result; + return result; +} + +template +stream_offset restricted_indirect_device::seek + (stream_offset off, BOOST_IOS::seekdir way) +{ + stream_offset next; + if (way == BOOST_IOS::beg) { + next = beg_ + off; + } else if (way == BOOST_IOS::cur) { + next = pos_ + off; + } else if (end_ != -1) { + next = end_ + off; + } else { + // Restriction is half-open; seek relative to the actual end. + pos_ = iostreams::seek(this->component(), off, BOOST_IOS::end); + if (pos_ < beg_) + bad_seek(); + return pos_ - beg_; + } + if (next < beg_ || end_ != -1 && next >= end_) + bad_seek(); + pos_ = iostreams::seek(this->component(), next - pos_, BOOST_IOS::cur); + return pos_ - beg_; +} + +//--------------Implementation of restricted_direct_device--------------------// + +template +restricted_direct_device::restricted_direct_device + (const Device& dev, stream_offset off, stream_offset len) + : basic_adapter(dev), beg_(0), end_(0) +{ + std::pair seq = + sequence(is_convertible()); + if ( off < 0 || len < -1 || + len != -1 && off + len > seq.second - seq.first ) + { + throw BOOST_IOSTREAMS_FAILURE("bad offset"); + } + beg_ = seq.first + off; + end_ = len != -1 ? + seq.first + off + len : + seq.second; +} + +template +typename restricted_direct_device::pair_type +restricted_direct_device::input_sequence() +{ + BOOST_STATIC_ASSERT((is_convertible::value)); + return std::make_pair(beg_, end_); +} + +template +typename restricted_direct_device::pair_type +restricted_direct_device::output_sequence() +{ + BOOST_STATIC_ASSERT((is_convertible::value)); + return std::make_pair(beg_, end_); +} + +template +typename restricted_direct_device::pair_type +restricted_direct_device::sequence(mpl::true_) +{ return iostreams::input_sequence(this->component()); } + +template +typename restricted_direct_device::pair_type +restricted_direct_device::sequence(mpl::false_) +{ return iostreams::output_sequence(this->component()); } + +//--------------Implementation of restricted_filter---------------------------// + +template +restricted_filter::restricted_filter + (const Filter& flt, stream_offset off, stream_offset len) + : basic_adapter(flt), beg_(off), + pos_(off), end_(len != -1 ? off + len : -1), open_(false) +{ + if (len < -1 || off < 0) + throw BOOST_IOSTREAMS_FAILURE("bad offset"); +} + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + + +#endif // #ifndef BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED