source: NonGTP/Boost/boost/iostreams/compose.hpp @ 857

Revision 857, 13.3 KB checked in by igarcia, 18 years ago (diff)
Line 
1// (C) Copyright Jonathan Turkanis 2005.
2// Distributed under the Boost Software License, Version 1.0. (See accompanying
3// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4
5// See http://www.boost.org/libs/iostreams for documentation.
6
7// Note: bidirectional streams are not supported.
8
9#ifndef BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED
10#define BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED
11
12#if defined(_MSC_VER) && (_MSC_VER >= 1020)
13# pragma once
14#endif
15
16#include <algorithm>          // min.
17#include <utility>            // pair.
18#include <boost/config.hpp>   // DEDUCED_TYPENAME.
19#include <boost/iostreams/categories.hpp>
20#include <boost/iostreams/detail/adapter/direct_adapter.hpp>
21#include <boost/iostreams/detail/call_traits.hpp>
22#include <boost/iostreams/detail/closer.hpp>
23#include <boost/iostreams/detail/enable_if_stream.hpp>
24#include <boost/iostreams/operations.hpp>
25#include <boost/iostreams/traits.hpp>      // mode_of, is_direct.
26#include <boost/mpl/if.hpp>
27#include <boost/ref.hpp>
28#include <boost/static_assert.hpp>
29#include <boost/type_traits/is_convertible.hpp>
30
31namespace boost { namespace iostreams {
32
33namespace detail {
34
35template<typename Filter, typename Device>
36struct composite_mode {
37    typedef typename mode_of<Filter>::type           filter_mode;
38    typedef typename mode_of<Device>::type           device_mode;
39    typedef is_convertible<filter_mode, dual_use>    is_dual_use;
40    typedef typename
41            mpl::if_<
42                is_convertible<device_mode, input>,
43                input,
44                output
45            >::type                                  type;
46};
47
48//
49// Template name: composite_device.
50// Description: Provides a Device view of a Filter, Device pair.
51// Template paramters:
52//      Filter - A model of Filter.
53//      Device - An indirect model of Device.
54//
55template< typename Filter,
56          typename Device,
57          typename Mode =
58              BOOST_DEDUCED_TYPENAME composite_mode<Filter, Device>::type >
59class composite_device {
60private:
61    typedef typename detail::param_type<Device>::type       param_type;
62    typedef typename
63            iostreams::select<  // Disambiguation for Tru64.
64                is_direct<Device>,  direct_adapter<Device>,
65                is_std_io<Device>,  Device&,
66                else_,              Device
67            >::type                                         value_type;
68public:
69    typedef typename char_type_of<Filter>::type             char_type;
70    struct category
71        : Mode,
72          device_tag,
73          closable_tag,
74          flushable_tag,
75          localizable_tag,
76          optimally_buffered_tag
77        { };
78    composite_device(const Filter& flt, param_type dev);
79    std::streamsize read(char_type* s, std::streamsize n);
80    std::streamsize write(const char_type* s, std::streamsize n);
81    std::streampos seek( stream_offset off, BOOST_IOS::seekdir way,
82                         BOOST_IOS::openmode which =
83                             BOOST_IOS::in | BOOST_IOS::out );
84
85    void close();
86    void close(BOOST_IOS::openmode which);
87    bool flush();
88    std::streamsize optimal_buffer_size() const;
89
90    template<typename Locale> // Avoid dependency on <locale>
91    void imbue(const Locale& loc)
92    {
93        iostreams::imbue(filter_, loc);
94        iostreams::imbue(device_, loc);
95    }
96
97    Filter& first() { return filter_; }
98    Device& second() { return device_; }
99private:
100    Filter      filter_;
101    value_type  device_;
102};
103
104//
105// Template name: composite_device.
106// Description: Provides a Device view of a Filter, Device pair.
107// Template paramters:
108//      Filter - A model of Filter.
109//      Device - An indirect model of Device.
110//
111template<typename Filter1, typename Filter2>
112class composite_filter {
113private:
114     typedef reference_wrapper<Filter2>           filter_ref;
115public:
116    typedef typename char_type_of<Filter1>::type  char_type;
117    struct category
118        : mode_of<Filter1>::type,
119          filter_tag,
120          multichar_tag,
121          closable_tag,
122          flushable_tag,
123          localizable_tag,
124          optimally_buffered_tag
125        { };
126    composite_filter(const Filter1& filter1, const Filter2& filter2)
127        : filter1_(filter1), filter2_(filter2)
128        { }
129
130    template<typename Source>
131    std::streamsize read(Source& src, char_type* s, std::streamsize n)
132    {
133        composite_device<filter_ref, Source> cmp(boost::ref(filter2_), src);
134        return iostreams::read(filter1_, cmp, s, n);
135    }
136
137    template<typename Sink>
138    std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
139    {
140        composite_device<filter_ref, Sink> cmp(boost::ref(filter2_), snk);
141        return iostreams::write(filter1_, cmp, s, n);
142    }
143
144    template<typename Device>
145    std::streampos seek( Device& dev, stream_offset off, BOOST_IOS::seekdir way,
146                         BOOST_IOS::openmode which =
147                             BOOST_IOS::in | BOOST_IOS::out )
148    {
149        composite_device<filter_ref, Device> cmp(boost::ref(filter2_), dev);
150        return iostreams::seek(filter1_, cmp, off, way, which);
151    }
152
153    template<typename Device>
154    void close( Device& dev,
155                BOOST_IOS::openmode which =
156                    BOOST_IOS::in | BOOST_IOS::out )
157    {
158        composite_device<filter_ref, Device> cmp(boost::ref(filter2_), dev);
159        iostreams::close(filter1_, cmp, which);
160    }
161
162    template<typename Device>
163    bool flush(Device& dev)
164    {
165        composite_device<Filter2, Device> cmp(filter2_, dev);
166        return iostreams::flush(filter1_, cmp);
167    }
168
169    std::streamsize optimal_buffer_size() const
170    {
171        std::streamsize first = iostreams::optimal_buffer_size(filter1_);
172        std::streamsize second = iostreams::optimal_buffer_size(filter2_);
173        return first < second ? second : first;
174    }
175
176    template<typename Locale> // Avoid dependency on <locale>
177    void imbue(const Locale& loc)
178    {   // To do: consider using RAII.
179        iostreams::imbue(filter1_, loc);
180        iostreams::imbue(filter2_, loc);
181    }
182
183    Filter1& first() { return filter1_; }
184    Filter2& second() { return filter2_; }
185private:
186    Filter1  filter1_;
187    Filter2  filter2_;
188};
189
190template<typename Filter, typename FilterOrDevice>
191struct composite_traits
192    : mpl::if_<
193          is_device<FilterOrDevice>,
194          composite_device<Filter, FilterOrDevice>,
195          composite_filter<Filter, FilterOrDevice>
196      >
197    { };
198
199} // End namespace detail.
200
201template<typename Filter, typename FilterOrDevice>
202struct composite : detail::composite_traits<Filter, FilterOrDevice>::type {
203    typedef typename detail::param_type<FilterOrDevice>::type param_type;
204    typedef typename detail::composite_traits<Filter, FilterOrDevice>::type base;
205    composite(const Filter& flt, param_type dev)
206        : base(flt, dev)
207        { }
208};
209
210//--------------Implementation of compose-------------------------------------//
211
212// Note: The following workarounds are patterned after resolve.hpp. It has not
213// yet been confirmed that they are necessary.
214
215#ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //-------------------------//
216# ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-------------------------------//
217
218template<typename Filter, typename FilterOrDevice>
219composite<Filter, FilterOrDevice>
220compose( const Filter& filter, const FilterOrDevice& fod
221         BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) )
222{ return composite<Filter, FilterOrDevice>(filter, fod); }
223
224template<typename Filter, typename Ch, typename Tr>
225composite< Filter, std::basic_streambuf<Ch, Tr> >
226compose(const Filter& filter, std::basic_streambuf<Ch, Tr>& sb)
227{ return composite< Filter, std::basic_streambuf<Ch, Tr> >(filter, sb); }
228
229template<typename Filter, typename Ch, typename Tr>
230composite< Filter, std::basic_istream<Ch, Tr> >
231compose(const Filter& filter, std::basic_istream<Ch, Tr>& is)
232{ return composite< Filter, std::basic_istream<Ch, Tr> >(filter, is); }
233
234template<typename Filter, typename Ch, typename Tr>
235composite< Filter, std::basic_ostream<Ch, Tr> >
236compose(const Filter& filter, std::basic_ostream<Ch, Tr>& os)
237{ return composite< Filter, std::basic_ostream<Ch, Tr> >(filter, os); }
238
239template<typename Filter, typename Ch, typename Tr>
240composite< Filter, std::basic_iostream<Ch, Tr> >
241compose(const Filter& filter, std::basic_iostream<Ch, Tr>& io)
242{ return composite< Filter, std::basic_iostream<Ch, Tr> >(filter, io); }
243
244# else // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //---------------------//
245
246template<typename Filter, typename FilterOrDevice>
247composite<Filter, FilterOrDevice>
248compose( const Filter& filter, const FilterOrDevice& fod
249         BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) )
250{ return composite<Filter, FilterOrDevice>(filter, fod); }
251
252template<typename Filter>
253composite<Filter, std::streambuf>
254compose(const Filter& filter, std::streambuf& sb)
255{ return composite<Filter, std::streambuf>(filter, sb); }
256
257template<typename Filter>
258composite<Filter, std::istream>
259compose(const Filter& filter, std::istream& is)
260{ return composite<Filter, std::istream>(filter, is); }
261
262template<typename Filter>
263composite<Filter, std::ostream>
264compose(const Filter& filter, std::ostream& os)
265{ return composite<Filter, std::ostream>(filter, os); }
266
267template<typename Filter>
268composite<Filter, std::iostream>
269compose(const Filter& filter, std::iostream& io)
270{ return composite<Filter, std::iostream>(filter, io); }
271
272# endif // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------//
273#else // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //----------------//
274
275template<typename Filter, typename Stream>
276composite<Filter, Stream>
277compose(const Filter& flt, const Stream& strm, mpl::true_)
278{   // Bad overload resolution.
279    return composite<Filter, Stream>(flt, const_cast<Stream&>(strm));
280}
281
282template<typename Filter, typename FilterOrDevice>
283composite<Filter, FilterOrDevice>
284compose(const Filter& flt, const FilterOrDevice& fod, mpl::false_)
285{ return composite<Filter, FilterOrDevice>(flt, fod); }
286
287template<typename Filter, typename FilterOrDevice>
288composite<Filter, FilterOrDevice>
289compose( const Filter& flt, const FilterOrDevice& fod
290         BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) )
291{ return compose(flt, fod, is_std_io<FilterOrDevice>()); }
292
293# if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && \
294     !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \
295     !defined(__GNUC__) // ---------------------------------------------------//
296
297template<typename Filter, typename FilterOrDevice>
298composite<Filter, FilterOrDevice>
299compose (const Filter& filter, FilterOrDevice& fod)
300{ return composite<Filter, FilterOrDevice>(filter, fod); }
301
302# endif // Borland 5.x, VC6-7.0 or GCC 2.9x //--------------------------------//
303#endif // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //---------------//
304
305//----------------------------------------------------------------------------//
306
307namespace detail {
308
309//--------------Implementation of composite_device---------------------------//
310
311template<typename Filter, typename Device, typename Mode>
312composite_device<Filter, Device, Mode>::composite_device
313    (const Filter& flt, param_type dev)
314    : filter_(flt), device_(dev)
315    { }
316
317template<typename Filter, typename Device, typename Mode>
318inline std::streamsize composite_device<Filter, Device, Mode>::read
319    (char_type* s, std::streamsize n)
320{ return iostreams::read(filter_, device_, s, n); }
321
322template<typename Filter, typename Device, typename Mode>
323inline std::streamsize composite_device<Filter, Device, Mode>::write
324    (const char_type* s, std::streamsize n)
325{ return iostreams::write(filter_, device_, s, n); }
326
327template<typename Filter, typename Device, typename Mode>
328std::streampos composite_device<Filter, Device, Mode>::seek
329    (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
330{ return iostreams::seek(filter_, device_, off, way, which); }
331
332template<typename Filter, typename Device, typename Mode>
333void composite_device<Filter, Device, Mode>::close()
334{
335    typedef typename mode_of<Device>::type device_mode;
336    BOOST_IOS::openmode which =
337        is_convertible<device_mode, input>() ?
338            BOOST_IOS::in :
339            BOOST_IOS::out;
340    close(which);
341}
342
343template<typename Filter, typename Device, typename Mode>
344void composite_device<Filter, Device, Mode>::close(BOOST_IOS::openmode which)
345{
346    bool                                 nothrow = false;
347    external_closer<value_type>          close_device(device_, which, nothrow);
348    external_closer<Filter, value_type>  close_filter(filter_, device_, which, nothrow);
349}
350
351template<typename Filter, typename Device, typename Mode>
352bool composite_device<Filter, Device, Mode>::flush()
353{   // To do: consider using RAII.
354    bool r1 = iostreams::flush(filter_, device_);
355    bool r2 = iostreams::flush(device_);
356    return r1 && r2;
357}
358
359template<typename Filter, typename Device, typename Mode>
360std::streamsize
361composite_device<Filter, Device, Mode>::optimal_buffer_size() const
362{ return iostreams::optimal_buffer_size(device_); }
363
364} // End namespace detail.
365
366} } // End namespaces iostreams, boost.
367
368#endif // #ifndef BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.