From f7bf8c704dc24ad40fe2f7454dc6e24ef88a937d Mon Sep 17 00:00:00 2001 From: Jonathan Turkanis Date: Fri, 4 Feb 2005 21:11:14 +0000 Subject: [PATCH] rewrote to allow customization by specializing xxx_impl templates [SVN r27107] --- include/boost/iostreams/operations.hpp | 566 ++++++++++++------------- 1 file changed, 279 insertions(+), 287 deletions(-) diff --git a/include/boost/iostreams/operations.hpp b/include/boost/iostreams/operations.hpp index d307523..da7cd61 100755 --- a/include/boost/iostreams/operations.hpp +++ b/include/boost/iostreams/operations.hpp @@ -11,8 +11,8 @@ # pragma once #endif -#include // pair. -#include // BOOST_NO_STD_LOCALE. +#include // pair. +#include // NO_STD_LOCALE, DEDUCED_TYPENAME, MSVC. #include #include #include @@ -24,76 +24,112 @@ #include #include +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-----------------------------------// +# include +#else // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //--------------------------// + namespace boost { namespace iostreams { //--------------Fundamental i/o operations------------------------------------// -template -BOOST_IOSTREAMS_INT_TYPE(T) get(T&); - -template -std::streamsize read(T&, BOOST_IOSTREAMS_CHAR_TYPE(T)*, std::streamsize); - -template -void putback(T&, BOOST_IOSTREAMS_CHAR_TYPE(T)); - -template -void put(T&, BOOST_IOSTREAMS_CHAR_TYPE(T)); - -template -void write(T&, const BOOST_IOSTREAMS_CHAR_TYPE(T)*, std::streamsize); - -template -std::streamoff -seek( T&, std::streamoff, std::ios::seekdir, - std::ios::openmode mode = - std::ios::in | std::ios::out ); - -template -std::streamsize -read(T&, Source&, BOOST_IOSTREAMS_CHAR_TYPE(T)*, std::streamsize); - -template -void write(T&, Sink&, const BOOST_IOSTREAMS_CHAR_TYPE(T)*, std::streamsize); - -template -void close(T&, std::ios::openmode); - -template -void close(T&, Sink&, std::ios::openmode which); - -// Avoid including . -template -void imbue(T&, const Locale& loc); - -template -std::pair -input_sequence(T&); - -template -std::pair -output_sequence(T&); - -//--------------Implementation of read, write, get and put--------------------// - namespace detail { // Implementation templates for simulated tag dispatch. template struct read_impl; template struct write_impl; +template struct filter_impl; +template struct direct_impl; template struct seek_impl; template struct close_impl; -template struct read_filter_impl; -template struct write_filter_impl; -template struct close_filter_impl; +template struct imbue_impl; + +} // End namespace detail. + +template +typename io_int::type get(T& t) +{ return detail::read_impl::get(detail::unwrap(t)); } + +template +inline std::streamsize +read(T& t, typename io_char::type* s, std::streamsize n) +{ return detail::read_impl::read(detail::unwrap(t), s, n); } + +template +std::streamsize +read(T& t, Source& src, typename io_char::type* s, std::streamsize n) +{ return detail::filter_impl::read(detail::unwrap(t), src, s, n); } + +template +void putback(T& t, typename io_char::type c) +{ return detail::read_impl::putback(detail::unwrap(t), c); } + +template +void put(T& t, typename io_char::type c) +{ detail::write_impl::put(detail::unwrap(t), c); } + +template +inline void write(T& t, const typename io_char::type* s, std::streamsize n) +{ detail::write_impl::write(detail::unwrap(t), s, n); } + +template +void write(T& t, Sink& snk, const typename io_char::type* s, std::streamsize n) +{ detail::filter_impl::write(detail::unwrap(t), snk, s, n); } + +template +inline std::streamoff +seek( T& t, std::streamoff off, std::ios::seekdir way, + std::ios::openmode which = std::ios::in | std::ios::out ) +{ return detail::seek_impl::seek(detail::unwrap(t), off, way, which); } + +template +inline std::pair< + BOOST_DEDUCED_TYPENAME io_char::type*, + BOOST_DEDUCED_TYPENAME io_char::type* +> +input_sequence(T& t) { return detail::direct_impl::input_sequence(t); } + +template +inline std::pair< + BOOST_DEDUCED_TYPENAME io_char::type*, + BOOST_DEDUCED_TYPENAME io_char::type* +> +output_sequence(T& t) { return detail::direct_impl::output_sequence(t); } + +template +void close(T& t, std::ios::openmode which) +{ detail::close_impl::close(detail::unwrap(t), which); } + +template +void close(T& t, Sink& snk, std::ios::openmode which) +{ detail::close_impl::close(detail::unwrap(t), snk, which); } + +template +void imbue(T& t, const Locale& loc) +{ detail::imbue_impl::imbue(detail::unwrap(t), loc); } + +//----------------------------------------------------------------------------// + +namespace detail { + +//------------------Definition of read_impl-----------------------------------// + +template< typename T> +struct read_impl + : read_impl< + BOOST_DEDUCED_TYPENAME + detail::dispatch< + T, istream_tag, streambuf_tag, input + >::type + > + { }; template<> struct read_impl { template - static BOOST_IOSTREAMS_INT_TYPE(T) get(T& t) + static typename io_int::type get(T& t) { - typedef std::char_traits traits_type; - BOOST_IOSTREAMS_CHAR_TYPE(T) c; + typedef std::char_traits::type> traits_type; + typename io_char::type c; return t.read(&c, 1) == 1 ? traits_type::to_int_type(c) : traits_type::eof(); @@ -101,28 +137,22 @@ struct read_impl { template static std::streamsize - read(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T)* s, std::streamsize n) + read(T& t, typename io_char::type* s, std::streamsize n) { return t.read(s, n); } - // Suggeted by Peter Dimov. See - // http://lists.boost.org/MailArchives/boost/msg06980.php. - template struct always_false : mpl::false_ { }; - template - static void putback(T&, BOOST_IOSTREAMS_CHAR_TYPE(T)) - { BOOST_STATIC_ASSERT(always_false::value); } -}; - -template<> -struct read_impl : read_impl { - template - static void putback(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T) c) { t.putback(c); } + static void putback(T& t, typename io_char::type c) + { + typedef typename io_category::type category; + BOOST_STATIC_ASSERT((is_convertible::value)); + t.putback(c); + } }; template<> struct read_impl { template - static BOOST_IOSTREAMS_INT_TYPE(T) get(T& t) + static typename io_int::type get(T& t) { return t.get(); } template @@ -131,14 +161,14 @@ struct read_impl { { t.read(s, n); return t.gcount(); } template - static void putback(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T) c) + static void putback(T& t, typename io_char::type c) { t.putback(c); } }; template<> struct read_impl { template - static BOOST_IOSTREAMS_INT_TYPE(T) get(T& t) + static typename io_int::type get(T& t) { return t.sbumpc(); } template @@ -147,26 +177,38 @@ struct read_impl { { return t.sgetn(s, n); } template - static void putback(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T) c) + static void putback(T& t, typename io_char::type c) { t.sputbackc(c); } }; +//------------------Definition of write_impl----------------------------------// + +template +struct write_impl + : write_impl< + BOOST_DEDUCED_TYPENAME + detail::dispatch< + T, ostream_tag, streambuf_tag, output + >::type + > + { }; + template<> struct write_impl { template - static void put(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T) c) + static void put(T& t, typename io_char::type c) { t.write(&c, 1); } template static void - write(T& t, const BOOST_IOSTREAMS_CHAR_TYPE(T)* s, std::streamsize n) + write(T& t, const typename io_char::type* s, std::streamsize n) { t.write(s, n); } }; template<> struct write_impl { template - static void put(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T) c) + static void put(T& t, typename io_char::type c) { t.put(c); } template @@ -177,7 +219,7 @@ struct write_impl { template<> struct write_impl { template - static void put(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T) c) + static void put(T& t, typename io_char::type c) { t.sputc(c); } template @@ -185,6 +227,86 @@ struct write_impl { { t.sputn(s, n); } }; +//------------------Definition of filter_impl---------------------------------// + +template +struct filter_impl + : filter_impl< + BOOST_DEDUCED_TYPENAME + detail::dispatch< + T, multichar_tag, any_tag + >::type + > + { }; + +template<> +struct filter_impl { + template + static std::streamsize read + (T& t, Source& src, typename io_char::type* s, std::streamsize n) + { return t.read(src, s, n); } + + template + static void write( T& t, Sink& snk, const typename io_char::type* s, + std::streamsize n ) + { t.write(snk, s, n); } +}; + +template<> +struct filter_impl { + template + static std::streamsize read + (T& t, Source& src, typename io_char::type* s, std::streamsize n) + { + typedef typename io_char::type char_type; + typedef std::char_traits traits_type; + std::streamsize result; + for (result = 0; result < n; ++result) { + typename io_int::type c = t.get(src); + if (traits_type::eq_int_type(c, traits_type::eof())) + break; + s[result] = traits_type::to_int_type(c); + } + return result; + } + template + static void write( T& t, Sink& snk, const typename io_char::type* s, + std::streamsize n ) + { for (std::streamsize off = 0; off < n; ++off) t.put(snk, s[off]); } +}; + +//------------------Definition of direct_impl-------------------------------// + +template +struct direct_impl { + template + static std::pair< + BOOST_DEDUCED_TYPENAME io_char::type*, + BOOST_DEDUCED_TYPENAME io_char::type* + > + input_sequence(U& u) { return u.input_sequence(); } + + template + static std::pair< + BOOST_DEDUCED_TYPENAME io_char::type*, + BOOST_DEDUCED_TYPENAME io_char::type* + > + output_sequence(U& u) { return u.output_sequence(); } +}; + +//------------------Definition of seek_impl-----------------------------------// + +template +struct seek_impl + : seek_impl< + BOOST_DEDUCED_TYPENAME + detail::dispatch< + T, iostream_tag, istream_tag, ostream_tag, + streambuf_tag, detail::two_head, any_tag + >::type + > + { }; + template<> struct seek_impl { template @@ -225,246 +347,116 @@ struct seek_impl { { return t.pubseekoff(off, way, which); } }; +//------------------Definition of close_impl----------------------------------// + +template +struct close_tag { + typedef typename io_category::type category; + typedef typename + mpl::eval_if< + is_convertible, + mpl::if_< + mpl::or_< + is_convertible, + is_convertible + >, + detail::two_sequence, + closable_tag + >, + mpl::identity + >::type type; +}; + +template +struct close_impl + : close_impl::type> + { }; + +// VC6 has trouble deducing the first template argument in each of the +// following implementation functions, and yields an ICE when it is explicitly +// specified. As a result, for VC6 we have made this template parameter a +// parameter of an enclosing struct 'inner'; the implementation functions each +// have one fewer template parameters than they do for other compilers. + +// A consequence is that with VC6 close() cannot be customized for user-defined +// classes by specializing close_impl in the usual way. + template<> struct close_impl { template static void close(T&, std::ios::openmode) { } + template + static void close(T&, Sink&, std::ios::openmode) { } }; +#include // Borland. template<> struct close_impl { template static void close(T& t, std::ios::openmode which) { - typedef BOOST_IOSTREAMS_CATEGORY(T) category; + typedef typename io_category::type category; const bool in = is_convertible::value && !is_convertible::value; if (in == ((which & std::ios::in) != 0)) t.close(); } + template + static void close(T& t, Sink& snk, std::ios::openmode which) + { + typedef typename io_category::type category; + const bool in = is_convertible::value && + !is_convertible::value; + if (in == ((which & std::ios::in) != 0)) + t.close(snk); + } }; +#include template<> struct close_impl { template static void close(T& t, std::ios::openmode which) { t.close(which); } -}; - -template<> -struct read_filter_impl { - template - static std::streamsize read - (T& t, Source& src, BOOST_IOSTREAMS_CHAR_TYPE(T)* s, std::streamsize n) - { - typedef BOOST_IOSTREAMS_CHAR_TYPE(T) char_type; - typedef std::char_traits traits_type; - std::streamsize result; - for (result = 0; result < n; ++result) { - BOOST_IOSTREAMS_INT_TYPE(T) c = t.get(src); - if (traits_type::eq_int_type(c, traits_type::eof())) - break; - s[result] = traits_type::to_int_type(c); - } - return result; - } -}; - -template<> -struct read_filter_impl { - template - static std::streamsize read - (T& t, Source& src, BOOST_IOSTREAMS_CHAR_TYPE(T)* s, std::streamsize n) - { return t.read(src, s, n); } -}; - -template<> -struct write_filter_impl { template - static void write( T& t, Sink& snk, const BOOST_IOSTREAMS_CHAR_TYPE(T)* s, - std::streamsize n ) - { for (std::streamsize off = 0; off < n; ++off) t.put(snk, s[off]); } + static void close(T& t, Sink& snk, std::ios::openmode which) + { t.close(snk, which); } +}; + +//------------------Definition of imbue_impl----------------------------------// + +template +struct imbue_impl + : imbue_impl< + BOOST_DEDUCED_TYPENAME + detail::dispatch< + T, streambuf_tag, localizable_tag, any_tag + >::type + > + { }; + +template<> +struct imbue_impl { +template + static void imbue(T&, const Locale&) { } }; template<> -struct write_filter_impl { - template - static void write( T& t, Sink& snk, const BOOST_IOSTREAMS_CHAR_TYPE(T)* s, - std::streamsize n ) - { t.write(snk, s, n); } +struct imbue_impl { +template + static void imbue(T& t, const Locale& loc) { t.pubimbue(loc); } +}; + +template<> +struct imbue_impl { +template + static void imbue(T& t, const Locale& loc) { t.imbue(loc); } }; } // End namespace detail. -template -BOOST_IOSTREAMS_INT_TYPE(T) get(T& t) -{ - typedef typename detail::dispatch< - T, istream_tag, streambuf_tag, input - >::type tag; - return detail::read_impl::get(detail::unwrap(t)); -} - -template -inline std::streamsize -read(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T)* s, std::streamsize n) -{ - typedef typename detail::dispatch< - T, istream_tag, streambuf_tag, input - >::type tag; - return detail::read_impl::read(detail::unwrap(t), s, n); -} - -template -void putback(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T) c) -{ - typedef typename detail::dispatch< - T, istream_tag, streambuf_tag, peekable_tag, input - >::type tag; - return detail::read_impl::putback(detail::unwrap(t), c); -} - -template -void put(T& t, BOOST_IOSTREAMS_CHAR_TYPE(T) c) -{ - typedef typename detail::dispatch< - T, ostream_tag, streambuf_tag, output - >::type tag; - detail::write_impl::put(detail::unwrap(t), c); -} - -template -inline void -write(T& t, const BOOST_IOSTREAMS_CHAR_TYPE(T)* s, std::streamsize n) -{ - typedef typename detail::dispatch< - T, ostream_tag, streambuf_tag, output - >::type tag; - detail::write_impl::write(detail::unwrap(t), s, n); -} - -template -inline std::streamoff -seek( T& t, std::streamoff off, std::ios::seekdir way, - std::ios::openmode which ) -{ - typedef typename detail::dispatch< - T, iostream_tag, istream_tag, ostream_tag, - streambuf_tag, detail::two_head, any_tag - >::type tag; - return detail::seek_impl::seek(detail::unwrap(t), off, way, which); -} - -template -void close(T& t, std::ios::openmode which) -{ - typedef BOOST_IOSTREAMS_CATEGORY(T) category; - typedef typename - mpl::eval_if< - is_convertible, - mpl::if_< - is_convertible, - detail::two_sequence, - closable_tag - >, - mpl::identity - >::type tag; - detail::close_impl::close(detail::unwrap(t), which); -} - -template -std::streamsize -read(T& t, Source& src, BOOST_IOSTREAMS_CHAR_TYPE(T)* s, std::streamsize n) -{ - typedef typename detail::dispatch< - T, multichar_tag, any_tag - >::type tag; - return detail::read_filter_impl::read(detail::unwrap(t), src, s, n); -} - -template -void write(T& t, Sink& snk, const BOOST_IOSTREAMS_CHAR_TYPE(T)* s, std::streamsize n) -{ - typedef typename detail::dispatch< - T, multichar_tag, any_tag - >::type tag; - detail::write_filter_impl::write(detail::unwrap(t), snk, s, n); -} - -//--------------Implementation of close---------------------------------------// - -namespace detail { - - // Implemention of close for filter types. - -#include // Borland. -template -void close_filter( T& t, Sink& snk, std::ios::openmode which, - closable_tag, any_tag ) -{ - typedef BOOST_IOSTREAMS_CATEGORY(T) category; - const bool in = is_convertible::value && - !is_convertible::value; - if (in == ((which & std::ios::in) != 0)) - t.close(snk); -} -#include - -template -void close_filter( T& t, Sink& snk, std::ios::openmode which, - closable_tag, dual_use ) -{ t.close(snk, which); } - -template -void close_filter( T& t, Sink& snk, std::ios::openmode which, - closable_tag, two_sequence ) -{ t.close(snk, which); } - -template -void close_filter( T&, Sink&, std::ios::openmode, any_tag ) -{ } - -template -void close_filter( T& t, Sink& snk, std::ios::openmode which, - closable_tag ) -{ -#if BOOST_WORKAROUND(__BORLANDC__, < 0x600) - typedef io_category::type category; - close_filter(t, snk, which, closable_tag(), category()); -#else - close_filter(t, snk, which, closable_tag(), get_category(t)); -#endif -} - -template -void imbue(T&, const Locale&, any_tag) { } - -// Covers streams as well as localizable filters and devices. -template -void imbue(T& t, const Locale& loc, localizable_tag) { t.imbue(loc); } - -template -void imbue(T& t, const Locale& loc, streambuf_tag) { t.pubimbue(loc); } - -} // End namespace detail. - -template -void close(T& t, Sink& snk, std::ios::openmode which) -{ detail::close_filter(detail::unwrap(t), snk, which, get_category(t)); } - -template -void imbue(T& t, const Locale& loc) -{ detail::imbue(detail::unwrap(t), loc, get_category(t)); } - -//--------------Implementation of input_sequence and output_sequence----------// - -template -inline std::pair -input_sequence(T& t) { return t.input_sequence(); } - -template -inline std::pair -output_sequence(T& t) { return t.output_sequence(); } +//----------------------------------------------------------------------------// } } // End namespaces iostreams, boost. -#endif // #ifndef BOOST_IOSTREAMS_OPERATIONS_HPP_INCLUDED //-------------------------// +#endif // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-------------------------// +#endif // #ifndef BOOST_IOSTREAMS_OPERATIONS_HPP_INCLUDED //------------------//