Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / iostreams / compose.hpp
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
31 namespace boost { namespace iostreams {
32
33 namespace detail {
34
35 template<typename Filter, typename Device>
36 struct 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 //
55 template< typename Filter,
56           typename Device,
57           typename Mode =
58               BOOST_DEDUCED_TYPENAME composite_mode<Filter, Device>::type >
59 class composite_device {
60 private:
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;
68 public:
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_; }
99 private:
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 //
111 template<typename Filter1, typename Filter2>
112 class composite_filter {
113 private:
114      typedef reference_wrapper<Filter2>           filter_ref;
115 public:
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_; }
185 private:
186     Filter1  filter1_;
187     Filter2  filter2_;
188 };
189
190 template<typename Filter, typename FilterOrDevice>
191 struct 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
201 template<typename Filter, typename FilterOrDevice>
202 struct 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
218 template<typename Filter, typename FilterOrDevice>
219 composite<Filter, FilterOrDevice>
220 compose( const Filter& filter, const FilterOrDevice& fod
221          BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) )
222 { return composite<Filter, FilterOrDevice>(filter, fod); }
223
224 template<typename Filter, typename Ch, typename Tr>
225 composite< Filter, std::basic_streambuf<Ch, Tr> >
226 compose(const Filter& filter, std::basic_streambuf<Ch, Tr>& sb)
227 { return composite< Filter, std::basic_streambuf<Ch, Tr> >(filter, sb); }
228
229 template<typename Filter, typename Ch, typename Tr>
230 composite< Filter, std::basic_istream<Ch, Tr> >
231 compose(const Filter& filter, std::basic_istream<Ch, Tr>& is)
232 { return composite< Filter, std::basic_istream<Ch, Tr> >(filter, is); }
233
234 template<typename Filter, typename Ch, typename Tr>
235 composite< Filter, std::basic_ostream<Ch, Tr> >
236 compose(const Filter& filter, std::basic_ostream<Ch, Tr>& os)
237 { return composite< Filter, std::basic_ostream<Ch, Tr> >(filter, os); }
238
239 template<typename Filter, typename Ch, typename Tr>
240 composite< Filter, std::basic_iostream<Ch, Tr> >
241 compose(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
246 template<typename Filter, typename FilterOrDevice>
247 composite<Filter, FilterOrDevice>
248 compose( const Filter& filter, const FilterOrDevice& fod
249          BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) )
250 { return composite<Filter, FilterOrDevice>(filter, fod); }
251
252 template<typename Filter>
253 composite<Filter, std::streambuf>
254 compose(const Filter& filter, std::streambuf& sb)
255 { return composite<Filter, std::streambuf>(filter, sb); }
256
257 template<typename Filter>
258 composite<Filter, std::istream>
259 compose(const Filter& filter, std::istream& is)
260 { return composite<Filter, std::istream>(filter, is); }
261
262 template<typename Filter>
263 composite<Filter, std::ostream>
264 compose(const Filter& filter, std::ostream& os)
265 { return composite<Filter, std::ostream>(filter, os); }
266
267 template<typename Filter>
268 composite<Filter, std::iostream>
269 compose(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
275 template<typename Filter, typename Stream>
276 composite<Filter, Stream>
277 compose(const Filter& flt, const Stream& strm, mpl::true_)
278 {   // Bad overload resolution.
279     return composite<Filter, Stream>(flt, const_cast<Stream&>(strm));
280 }
281
282 template<typename Filter, typename FilterOrDevice>
283 composite<Filter, FilterOrDevice>
284 compose(const Filter& flt, const FilterOrDevice& fod, mpl::false_)
285 { return composite<Filter, FilterOrDevice>(flt, fod); }
286
287 template<typename Filter, typename FilterOrDevice>
288 composite<Filter, FilterOrDevice>
289 compose( 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
297 template<typename Filter, typename FilterOrDevice>
298 composite<Filter, FilterOrDevice>
299 compose (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
307 namespace detail {
308
309 //--------------Implementation of composite_device---------------------------//
310
311 template<typename Filter, typename Device, typename Mode>
312 composite_device<Filter, Device, Mode>::composite_device
313     (const Filter& flt, param_type dev)
314     : filter_(flt), device_(dev)
315     { }
316
317 template<typename Filter, typename Device, typename Mode>
318 inline std::streamsize composite_device<Filter, Device, Mode>::read
319     (char_type* s, std::streamsize n)
320 { return iostreams::read(filter_, device_, s, n); }
321
322 template<typename Filter, typename Device, typename Mode>
323 inline 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
327 template<typename Filter, typename Device, typename Mode>
328 std::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
332 template<typename Filter, typename Device, typename Mode>
333 void 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
343 template<typename Filter, typename Device, typename Mode>
344 void 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
351 template<typename Filter, typename Device, typename Mode>
352 bool 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
359 template<typename Filter, typename Device, typename Mode>
360 std::streamsize
361 composite_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