1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2003-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
6 // See http://www.boost.org/libs/iostreams for documentation.
8 #ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED
9 #define BOOST_IOSTREAMS_INVERT_HPP_INCLUDED
11 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
15 #include <algorithm> // copy, min.
17 #include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME.
18 #include <boost/detail/workaround.hpp> // default_filter_buffer_size.
19 #include <boost/iostreams/char_traits.hpp>
20 #include <boost/iostreams/compose.hpp>
21 #include <boost/iostreams/constants.hpp>
22 #include <boost/iostreams/device/array.hpp>
23 #include <boost/iostreams/detail/buffer.hpp>
24 #include <boost/iostreams/detail/counted_array.hpp>
25 #include <boost/iostreams/detail/execute.hpp>
26 #include <boost/iostreams/detail/functional.hpp> // clear_flags, call_reset
27 #include <boost/mpl/if.hpp>
28 #include <boost/ref.hpp>
29 #include <boost/shared_ptr.hpp>
30 #include <boost/type_traits/is_convertible.hpp>
33 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
35 namespace boost
{ namespace iostreams
{
38 // Template name: inverse.
39 // Template paramters:
40 // Filter - A model of InputFilter or OutputFilter.
41 // Description: Generates an InputFilter from an OutputFilter or
44 template<typename Filter
>
47 BOOST_STATIC_ASSERT(is_filter
<Filter
>::value
);
48 typedef typename category_of
<Filter
>::type base_category
;
49 typedef reference_wrapper
<Filter
> filter_ref
;
51 typedef typename char_type_of
<Filter
>::type char_type
;
52 typedef typename int_type_of
<Filter
>::type int_type
;
53 typedef char_traits
<char_type
> traits_type
;
69 explicit inverse( const Filter
& filter
,
70 std::streamsize buffer_size
=
71 default_filter_buffer_size
)
72 : pimpl_(new impl(filter
, buffer_size
))
75 template<typename Source
>
76 std::streamsize
read(Source
& src
, char* s
, std::streamsize n
)
78 typedef detail::counted_array_sink
<char_type
> array_sink
;
79 typedef composite
<filter_ref
, array_sink
> filtered_array_sink
;
81 assert((flags() & f_write
) == 0);
87 filtered_array_sink
snk(filter(), array_sink(s
, n
));
89 for ( status
= traits_type::good();
90 snk
.second().count() < n
&& status
== traits_type::good(); )
92 status
= buf().fill(src
);
95 return snk
.second().count() == 0 &&
96 status
== traits_type::eof()
100 snk
.second().count();
103 template<typename Sink
>
104 std::streamsize
write(Sink
& dest
, const char* s
, std::streamsize n
)
106 typedef detail::counted_array_source
<char_type
> array_source
;
107 typedef composite
<filter_ref
, array_source
> filtered_array_source
;
109 assert((flags() & f_read
) == 0);
115 filtered_array_source
src(filter(), array_source(s
, n
));
116 for (bool good
= true; src
.second().count() < n
&& good
; ) {
118 good
= buf().flush(dest
);
120 return src
.second().count();
123 template<typename Device
>
124 void close(Device
& dev
)
127 detail::flush_buffer(buf(), dev
, (flags() & f_write
) != 0),
128 detail::call_close_all(pimpl_
->filter_
, dev
),
129 detail::clear_flags(flags())
133 filter_ref
filter() { return boost::ref(pimpl_
->filter_
); }
134 detail::buffer
<char_type
>& buf() { return pimpl_
->buf_
; }
135 int& flags() { return pimpl_
->flags_
; }
138 f_read
= 1, f_write
= 2
142 impl(const Filter
& filter
, std::streamsize n
)
143 : filter_(filter
), buf_(n
), flags_(0)
146 detail::buffer
<char_type
> buf_
;
149 shared_ptr
<impl
> pimpl_
;
153 // Template name: invert.
154 // Template paramters:
155 // Filter - A model of InputFilter or OutputFilter.
156 // Description: Returns an instance of an appropriate specialization of inverse.
158 template<typename Filter
>
159 inverse
<Filter
> invert(const Filter
& f
) { return inverse
<Filter
>(f
); }
161 //----------------------------------------------------------------------------//
163 } } // End namespaces iostreams, boost.
165 #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC.
167 #endif // #ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED